Commit 7162f39f authored by Robert Griesemer's avatar Robert Griesemer

exp/template: fix endless loop

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
parent bf184398
......@@ -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
......
......@@ -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 {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment