Commit 0fd270ab authored by Andrew Gerrand's avatar Andrew Gerrand

text/template: emit field error over nil pointer error where appropriate

When evaluating "{{.MissingField}}" on a nil *T, Exec returns
"can't evaluate field MissingField in type *T" instead of
"nil pointer evaluating *T.MissingField".

Fixes golang/go#15125

Change-Id: I6e73f61b8a72c694179c1f8cdc808766c90b6f57
Reviewed-on: https://go-review.googlesource.com/21705Reviewed-by: default avatarRob Pike <r@golang.org>
parent 0004f34c
...@@ -538,14 +538,14 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, ...@@ -538,14 +538,14 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
return s.evalCall(dot, method, node, fieldName, args, final) return s.evalCall(dot, method, node, fieldName, args, final)
} }
hasArgs := len(args) > 1 || final.IsValid() hasArgs := len(args) > 1 || final.IsValid()
// It's not a method; must be a field of a struct or an element of a map. The receiver must not be nil. // It's not a method; must be a field of a struct or an element of a map.
if isNil {
s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
}
switch receiver.Kind() { switch receiver.Kind() {
case reflect.Struct: case reflect.Struct:
tField, ok := receiver.Type().FieldByName(fieldName) tField, ok := receiver.Type().FieldByName(fieldName)
if ok { if ok {
if isNil {
s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
}
field := receiver.FieldByIndex(tField.Index) field := receiver.FieldByIndex(tField.Index)
if tField.PkgPath != "" { // field is unexported if tField.PkgPath != "" { // field is unexported
s.errorf("%s is an unexported field of struct type %s", fieldName, typ) s.errorf("%s is an unexported field of struct type %s", fieldName, typ)
...@@ -556,8 +556,10 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node, ...@@ -556,8 +556,10 @@ func (s *state) evalField(dot reflect.Value, fieldName string, node parse.Node,
} }
return field return field
} }
s.errorf("%s is not a field of struct type %s", fieldName, typ)
case reflect.Map: case reflect.Map:
if isNil {
s.errorf("nil pointer evaluating %s.%s", typ, fieldName)
}
// If it's a map, attempt to use the field name as a key. // If it's a map, attempt to use the field name as a key.
nameVal := reflect.ValueOf(fieldName) nameVal := reflect.ValueOf(fieldName)
if nameVal.Type().AssignableTo(receiver.Type().Key()) { if nameVal.Type().AssignableTo(receiver.Type().Key()) {
......
...@@ -1280,3 +1280,20 @@ func TestBlock(t *testing.T) { ...@@ -1280,3 +1280,20 @@ func TestBlock(t *testing.T) {
t.Errorf("got %q, want %q", got, want2) t.Errorf("got %q, want %q", got, want2)
} }
} }
// Check that calling an invalid field on nil pointer prints
// a field error instead of a distracting nil pointer error.
// https://golang.org/issue/15125
func TestMissingFieldOnNil(t *testing.T) {
tmpl := Must(New("tmpl").Parse("{{.MissingField}}"))
var d *T
err := tmpl.Execute(ioutil.Discard, d)
got := "<nil>"
if err != nil {
got = err.Error()
}
want := "can't evaluate field MissingField in type *template.T"
if !strings.HasSuffix(got, want) {
t.Errorf("got error %q, want %q", got, want)
}
}
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