// We indirect through pointers and empty interfaces (only) because
// non-empty interfaces have methods we might need.
func indirect(v reflect.Value) (rv reflect.Value, isNil bool) {
- for v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface {
+ for ; v.Kind() == reflect.Ptr || v.Kind() == reflect.Interface; v = v.Elem() {
if v.IsNil() {
return v, true
}
- if v.Kind() == reflect.Ptr || v.NumMethod() == 0 {
- v = v.Elem()
+ if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
+ break
}
}
return v, false
Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X
}
+// A non-empty interface.
+type I interface {
+ Method0() string
+}
+
+var iVal I = tVal
+
// Helpers for creation.
func newInt(n int) *int {
p := new(int)
// Fixed bugs.
// Must separate dot and receiver; otherwise args are evaluated with dot set to variable.
{"bug0", "{{range .MSIone}}{{if $.Method1 .}}X{{end}}{{end}}", "X", tVal, true},
+ // Do not loop endlessly in indirect for non-empty interfaces.
+ // The bug appears with *interface only; this is supposed to fail (cannot invoke Method0), but terminate.
+ {"bug1", "{{.Method0}}", "", &iVal, false},
}
func zeroArgs() string {