mirror of
https://github.com/golang/go
synced 2024-11-23 21:50:08 -07:00
text/template: resolve non-empty interface
Read what a non-empty interface points to. The deleted lines were added in https://codereview.appspot.com/4810060/, which attempted to break an infinite loop. That was a long time ago. If I just delete these lines with current codebase, the test "bug1" (added in that CL) does not fail. All new tests fail without this fix. Fixes #12924 Change-Id: I9370ca44facd6af3019850aa065b936e5a482d37 Reviewed-on: https://go-review.googlesource.com/15809 Reviewed-by: Andrew Gerrand <adg@golang.org>
This commit is contained in:
parent
65fc379dae
commit
167a712399
@ -829,16 +829,11 @@ func (s *state) evalEmptyInterface(dot reflect.Value, n parse.Node) reflect.Valu
|
||||
}
|
||||
|
||||
// indirect returns the item at the end of indirection, and a bool to indicate if it's nil.
|
||||
// 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; v = v.Elem() {
|
||||
if v.IsNil() {
|
||||
return v, true
|
||||
}
|
||||
if v.Kind() == reflect.Interface && v.NumMethod() > 0 {
|
||||
break
|
||||
}
|
||||
}
|
||||
return v, false
|
||||
}
|
||||
|
@ -51,8 +51,9 @@ type T struct {
|
||||
Empty2 interface{}
|
||||
Empty3 interface{}
|
||||
Empty4 interface{}
|
||||
// Non-empty interface.
|
||||
NonEmptyInterface I
|
||||
// Non-empty interfaces.
|
||||
NonEmptyInterface I
|
||||
NonEmptyInterfacePtS *I
|
||||
// Stringer.
|
||||
Str fmt.Stringer
|
||||
Err error
|
||||
@ -73,6 +74,12 @@ type T struct {
|
||||
unexported int
|
||||
}
|
||||
|
||||
type S []string
|
||||
|
||||
func (S) Method0() string {
|
||||
return "M0"
|
||||
}
|
||||
|
||||
type U struct {
|
||||
V string
|
||||
}
|
||||
@ -99,6 +106,8 @@ func (w *W) Error() string {
|
||||
return fmt.Sprintf("[%d]", w.k)
|
||||
}
|
||||
|
||||
var siVal = I(S{"a", "b"})
|
||||
|
||||
var tVal = &T{
|
||||
True: true,
|
||||
I: 17,
|
||||
@ -119,22 +128,23 @@ var tVal = &T{
|
||||
{"one": 1, "two": 2},
|
||||
{"eleven": 11, "twelve": 12},
|
||||
},
|
||||
Empty1: 3,
|
||||
Empty2: "empty2",
|
||||
Empty3: []int{7, 8},
|
||||
Empty4: &U{"UinEmpty"},
|
||||
NonEmptyInterface: new(T),
|
||||
Str: bytes.NewBuffer([]byte("foozle")),
|
||||
Err: errors.New("erroozle"),
|
||||
PI: newInt(23),
|
||||
PS: newString("a string"),
|
||||
PSI: newIntSlice(21, 22, 23),
|
||||
BinaryFunc: func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
|
||||
VariadicFunc: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
|
||||
VariadicFuncInt: func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
|
||||
NilOKFunc: func(s *int) bool { return s == nil },
|
||||
ErrFunc: func() (string, error) { return "bla", nil },
|
||||
Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X
|
||||
Empty1: 3,
|
||||
Empty2: "empty2",
|
||||
Empty3: []int{7, 8},
|
||||
Empty4: &U{"UinEmpty"},
|
||||
NonEmptyInterface: &T{X: "x"},
|
||||
NonEmptyInterfacePtS: &siVal,
|
||||
Str: bytes.NewBuffer([]byte("foozle")),
|
||||
Err: errors.New("erroozle"),
|
||||
PI: newInt(23),
|
||||
PS: newString("a string"),
|
||||
PSI: newIntSlice(21, 22, 23),
|
||||
BinaryFunc: func(a, b string) string { return fmt.Sprintf("[%s=%s]", a, b) },
|
||||
VariadicFunc: func(s ...string) string { return fmt.Sprint("<", strings.Join(s, "+"), ">") },
|
||||
VariadicFuncInt: func(a int, s ...string) string { return fmt.Sprint(a, "=<", strings.Join(s, "+"), ">") },
|
||||
NilOKFunc: func(s *int) bool { return s == nil },
|
||||
ErrFunc: func() (string, error) { return "bla", nil },
|
||||
Tmpl: Must(New("x").Parse("test template")), // "x" is the value of .X
|
||||
}
|
||||
|
||||
// A non-empty interface.
|
||||
@ -550,6 +560,11 @@ var execTests = []execTest{
|
||||
{"bug16i", "{{\"aaa\"|oneArg}}", "oneArg=aaa", tVal, true},
|
||||
{"bug16j", "{{1+2i|printf \"%v\"}}", "(1+2i)", tVal, true},
|
||||
{"bug16k", "{{\"aaa\"|printf }}", "aaa", tVal, true},
|
||||
{"bug17a", "{{.NonEmptyInterface.X}}", "x", tVal, true},
|
||||
{"bug17b", "-{{.NonEmptyInterface.Method1 1234}}-", "-1234-", tVal, true},
|
||||
{"bug17c", "{{len .NonEmptyInterfacePtS}}", "2", tVal, true},
|
||||
{"bug17d", "{{index .NonEmptyInterfacePtS 0}}", "a", tVal, true},
|
||||
{"bug17e", "{{range .NonEmptyInterfacePtS}}-{{.}}-{{end}}", "-a--b-", tVal, true},
|
||||
}
|
||||
|
||||
func zeroArgs() string {
|
||||
|
Loading…
Reference in New Issue
Block a user