mirror of
https://github.com/golang/go
synced 2024-09-06 00:19:45 +00:00
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:
parent
4be3851d19
commit
6761b1eb1b
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
30
test/fixedbugs/issue28268.go
Normal file
30
test/fixedbugs/issue28268.go
Normal 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
|
||||
}
|
Loading…
Reference in a new issue