]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: confusing error if composite literal field is a method
authorMichael Fraenkel <michael.fraenkel@gmail.com>
Wed, 23 Jan 2019 00:10:29 +0000 (19:10 -0500)
committerDaniel Martí <mvdan@mvdan.cc>
Tue, 26 Feb 2019 18:42:07 +0000 (18:42 +0000)
When looking for the field specified in a composite literal, check that
the specified name is actually a field and not a method.

Fixes #29855.

Change-Id: Id77666e846f925907b1eec64213b1d25af8a2466
Reviewed-on: https://go-review.googlesource.com/c/158938
Run-TryBot: Robert Griesemer <gri@golang.org>
TryBot-Result: Gobot Gobot <gobot@golang.org>
Reviewed-by: Robert Griesemer <gri@golang.org>
src/cmd/compile/internal/gc/reflect.go
src/cmd/compile/internal/gc/subr.go
src/cmd/compile/internal/gc/typecheck.go
src/cmd/compile/internal/types/type.go
test/fixedbugs/issue29855.go [new file with mode: 0644]

index 7a93ece8b90365f74dd9318168ddf54091d120f5..8b058330ddee6c8ca30232af3d7e414f99d20335 100644 (file)
@@ -375,7 +375,7 @@ func methods(t *types.Type) []*Sig {
        // generating code if necessary.
        var ms []*Sig
        for _, f := range mt.AllMethods().Slice() {
-               if f.Type.Etype != TFUNC || f.Type.Recv() == nil {
+               if !f.IsMethod() {
                        Fatalf("non-method on %v method %v %v\n", mt, f.Sym, f)
                }
                if f.Type.Recv() == nil {
index 7dcbc6a9e135d9c1a028022e94d7abbfafc97b7e..3a261244d151aae891e0b2f7ad86ccf2a89db98a 100644 (file)
@@ -1180,7 +1180,7 @@ func lookdot0(s *types.Sym, t *types.Type, save **types.Field, ignorecase bool)
        c := 0
        if u.IsStruct() || u.IsInterface() {
                for _, f := range u.Fields().Slice() {
-                       if f.Sym == s || (ignorecase && f.Type.Etype == TFUNC && f.Type.Recv() != nil && strings.EqualFold(f.Sym.Name, s.Name)) {
+                       if f.Sym == s || (ignorecase && f.IsMethod() && strings.EqualFold(f.Sym.Name, s.Name)) {
                                if save != nil {
                                        *save = f
                                }
@@ -1420,7 +1420,7 @@ func expandmeth(t *types.Type) {
                }
 
                // dotpath may have dug out arbitrary fields, we only want methods.
-               if f.Type.Etype != TFUNC || f.Type.Recv() == nil {
+               if !f.IsMethod() {
                        continue
                }
 
@@ -1631,7 +1631,7 @@ func ifacelookdot(s *types.Sym, t *types.Type, ignorecase bool) (m *types.Field,
                }
        }
 
-       if m.Type.Etype != TFUNC || m.Type.Recv() == nil {
+       if !m.IsMethod() {
                yyerror("%v.%v is a field, not a method", t, s)
                return nil, followptr
        }
index e22fd6445a30f2d726b890c454be0d59ffbc51fc..0702da25ee5a0032a084f7cd50219f9ddb4f72c1 100644 (file)
@@ -3250,8 +3250,9 @@ func typecheckcomplit(n *Node) (res *Node) {
                                                }
                                                continue
                                        }
-                                       p, _ := dotpath(l.Sym, t, nil, true)
-                                       if p == nil {
+                                       var f *types.Field
+                                       p, _ := dotpath(l.Sym, t, &f, true)
+                                       if p == nil || f.IsMethod() {
                                                yyerror("unknown field '%v' in struct literal of type %v", l.Sym, t)
                                                continue
                                        }
index 3e5f5cbf4949f3ce943cd45c056403f06fe6515f..7d123e46105c3d8a5aaab1f27f913a0fbe3c512f 100644 (file)
@@ -392,6 +392,11 @@ func (f *Field) End() int64 {
        return f.Offset + f.Type.Width
 }
 
+// IsMethod reports whether f represents a method rather than a struct field.
+func (f *Field) IsMethod() bool {
+       return f.Type.Etype == TFUNC && f.Type.Recv() != nil
+}
+
 // Fields is a pointer to a slice of *Field.
 // This saves space in Types that do not have fields or methods
 // compared to a simple slice of *Field.
diff --git a/test/fixedbugs/issue29855.go b/test/fixedbugs/issue29855.go
new file mode 100644 (file)
index 0000000..b57eae2
--- /dev/null
@@ -0,0 +1,17 @@
+// errorcheck
+
+// Copyright 2018 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package main
+
+type T struct {
+       GlobalName string
+}
+
+var t = T{Name: "foo"} // ERROR "unknown field 'Name' in struct literal of type T"
+
+func (t T) Name() string {
+       return t.GlobalName
+}