]> Cypherpunks repositories - gostls13.git/commitdiff
exp/template: fix endless loop
authorRobert Griesemer <gri@golang.org>
Sun, 31 Jul 2011 00:11:52 +0000 (17:11 -0700)
committerRobert Griesemer <gri@golang.org>
Sun, 31 Jul 2011 00:11:52 +0000 (17:11 -0700)
No progress was made in indirect() if the reflect.Value
was an non-nil and non-empty interface.

R=r, r
CC=golang-dev
https://golang.org/cl/4810060

src/pkg/exp/template/exec.go
src/pkg/exp/template/exec_test.go

index 40a947dbf05563070c63b62caf1083e4e6fdbfcb..e500465d12f9950855d385fa6d53c90714a8f821 100644 (file)
@@ -585,12 +585,12 @@ func (s *state) evalEmptyInterface(dot reflect.Value, n node) reflect.Value {
 // 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
index d9b8afbcd2775644ebb2a1a5dad773a9a3f6fb51..ed27e71223500cbbdd43f64c8285b4903350c47f 100644 (file)
@@ -75,6 +75,13 @@ var tVal = &T{
        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)
@@ -344,6 +351,9 @@ var execTests = []execTest{
        // 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 {