cmd/compile: better errors for structs with conflicting fields and methods

If a field and method have the same name, mark the respective struct field
so that we don't report follow-on errors when the field/method is accessed.

Per suggestion of @mdempsky.

Fixes #28268.

Change-Id: Ia1ca4cdfe9bacd3739d1fd7ca5e014ca094245ee
Reviewed-on: https://go-review.googlesource.com/c/144259
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
This commit is contained in:
Robert Griesemer 2018-10-23 14:45:09 -07:00
parent 4be3851d19
commit 6761b1eb1b
3 changed files with 34 additions and 3 deletions

View file

@ -863,7 +863,7 @@ func methodSymSuffix(recv *types.Type, msym *types.Sym, suffix string) *types.Sy
// Add a method, declared as a function.
// - msym is the method symbol
// - t is function type (with receiver)
// Returns a pointer to the existing or added Field.
// Returns a pointer to the existing or added Field; or nil if there's an error.
func addmethod(msym *types.Sym, t *types.Type, local, nointerface bool) *types.Field {
if msym == nil {
Fatalf("no method symbol")
@ -918,6 +918,7 @@ func addmethod(msym *types.Sym, t *types.Type, local, nointerface bool) *types.F
for _, f := range mt.Fields().Slice() {
if f.Sym == msym {
yyerror("type %v has both field and method named %v", mt, msym)
f.SetBroke(true)
return nil
}
}
@ -927,7 +928,7 @@ func addmethod(msym *types.Sym, t *types.Type, local, nointerface bool) *types.F
if msym.Name != f.Sym.Name {
continue
}
// eqtype only checks that incoming and result parameters match,
// types.Identical only checks that incoming and result parameters match,
// so explicitly check that the receiver parameters match too.
if !types.Identical(t, f.Type) || !types.Identical(t.Recv().Type, f.Type.Recv().Type) {
yyerror("method redeclared: %v.%v\n\t%v\n\t%v", mt, msym, f.Type, t)

View file

@ -2443,7 +2443,7 @@ func lookdot(n *Node, t *types.Type, dostrcmp int) *types.Field {
}
if f1 != nil {
if dostrcmp > 1 {
if dostrcmp > 1 || f1.Broke() {
// Already in the process of diagnosing an error.
return f1
}

View file

@ -0,0 +1,30 @@
// 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.
// Verify that follow-on errors due to conflicting
// struct field and method names are suppressed.
package p
type T struct {
a, b, c int
E
}
type E struct{}
func (T) b() {} // ERROR "field and method named b"
func (*T) E() {} // ERROR "field and method named E"
func _() {
var x T
_ = x.a
_ = x.b // no follow-on error here
x.b() // no follow-on error here
_ = x.c
_ = x.E // no follow-on error here
x.E() // no follow-on error here
}