From 39fa2a5bf2bbc484d00fc6fc943b16315eb039b6 Mon Sep 17 00:00:00 2001 From: Rob Pike Date: Thu, 11 Aug 2011 08:27:16 +1000 Subject: [PATCH] exp/template: truth for interface values. Also protect against invalid (zero Value) reflect.Values. R=rsc, gri CC=golang-dev https://golang.org/cl/4810094 --- src/pkg/exp/template/exec.go | 8 ++++++-- src/pkg/exp/template/exec_test.go | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/src/pkg/exp/template/exec.go b/src/pkg/exp/template/exec.go index 7d7a9c73268..dafdaee914e 100644 --- a/src/pkg/exp/template/exec.go +++ b/src/pkg/exp/template/exec.go @@ -148,7 +148,7 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse. val := s.evalPipeline(dot, pipe) truth, ok := isTrue(val) if !ok { - s.errorf("if/with can't use value of type %T", val.Interface()) + s.errorf("if/with can't use %v", val) } if truth { if typ == parse.NodeWith { @@ -164,6 +164,10 @@ func (s *state) walkIfOrWith(typ parse.NodeType, dot reflect.Value, pipe *parse. // isTrue returns whether the value is 'true', in the sense of not the zero of its type, // and whether the value has a meaningful truth value. func isTrue(val reflect.Value) (truth, ok bool) { + if !val.IsValid() { + // Something like var x interface{}, never set. It's a form of nil. + return false, true + } switch val.Kind() { case reflect.Array, reflect.Map, reflect.Slice, reflect.String: truth = val.Len() > 0 @@ -171,7 +175,7 @@ func isTrue(val reflect.Value) (truth, ok bool) { truth = val.Bool() case reflect.Complex64, reflect.Complex128: truth = val.Complex() != 0 - case reflect.Chan, reflect.Func, reflect.Ptr: + case reflect.Chan, reflect.Func, reflect.Ptr, reflect.Interface: truth = !val.IsNil() case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64: truth = val.Int() != 0 diff --git a/src/pkg/exp/template/exec_test.go b/src/pkg/exp/template/exec_test.go index b7884744027..4013f2ef49b 100644 --- a/src/pkg/exp/template/exec_test.go +++ b/src/pkg/exp/template/exec_test.go @@ -366,7 +366,9 @@ var execTests = []execTest{ // Was taking address of interface field, so method set was empty. {"bug2", "{{$.NonEmptyInterface.Method0}}", "M0", tVal, true}, // Struct values were not legal in with - mere oversight. - {"bug4", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true}, + {"bug3", "{{with $}}{{.Method0}}{{end}}", "M0", tVal, true}, + // Nil interface values in if. + {"bug4", "{{if .Empty0}}non-nil{{else}}nil{{end}}", "nil", tVal, true}, } func zeroArgs() string {