mirror of https://github.com/golang/go.git
go/types, types2: better error when method is missing due to ambiguity
If a type doesn't implement an interface due to an ambiguous method, say so in the error message instead of just reporting a missing method. Fixes #57352. Change-Id: I5608f893c485de578b7f86362ca6f66033653695 Reviewed-on: https://go-review.googlesource.com/c/go/+/473658 TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Robert Findley <rfindley@google.com> Auto-Submit: Robert Griesemer <gri@google.com> Reviewed-by: Robert Griesemer <gri@google.com> Run-TryBot: Robert Griesemer <gri@google.com>
This commit is contained in:
parent
ebc2aaae24
commit
c6cdfdabef
|
|
@ -343,6 +343,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
|
|||
notFound
|
||||
wrongName
|
||||
wrongSig
|
||||
ambigSel
|
||||
ptrRecv
|
||||
field
|
||||
)
|
||||
|
|
@ -371,21 +372,23 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
|
|||
}
|
||||
} else {
|
||||
for _, m = range methods {
|
||||
obj, _, indirect := lookupFieldOrMethodImpl(V, false, m.pkg, m.name, false)
|
||||
obj, index, indirect := lookupFieldOrMethodImpl(V, false, m.pkg, m.name, false)
|
||||
|
||||
// check if m is on *V, or on V with case-folding
|
||||
// check if m is ambiguous, on *V, or on V with case-folding
|
||||
if obj == nil {
|
||||
if indirect {
|
||||
switch {
|
||||
case index != nil:
|
||||
state = ambigSel
|
||||
case indirect:
|
||||
state = ptrRecv
|
||||
break
|
||||
default:
|
||||
state = notFound
|
||||
obj, _, _ = lookupFieldOrMethodImpl(V, false, m.pkg, m.name, true /* fold case */)
|
||||
f, _ = obj.(*Func)
|
||||
if f != nil {
|
||||
state = wrongName
|
||||
}
|
||||
}
|
||||
obj, _, _ = lookupFieldOrMethodImpl(V, false, m.pkg, m.name, true /* fold case */)
|
||||
f, _ = obj.(*Func)
|
||||
if f != nil {
|
||||
state = wrongName
|
||||
break
|
||||
}
|
||||
state = notFound
|
||||
break
|
||||
}
|
||||
|
||||
|
|
@ -436,6 +439,8 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
|
|||
}
|
||||
*cause = check.sprintf("(wrong type for method %s)\n\t\thave %s\n\t\twant %s",
|
||||
m.Name(), fs, ms)
|
||||
case ambigSel:
|
||||
*cause = check.sprintf("(ambiguous selector %s.%s)", V, m.Name())
|
||||
case ptrRecv:
|
||||
*cause = check.sprintf("(method %s has pointer receiver)", m.Name())
|
||||
case field:
|
||||
|
|
|
|||
|
|
@ -345,6 +345,7 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
|
|||
notFound
|
||||
wrongName
|
||||
wrongSig
|
||||
ambigSel
|
||||
ptrRecv
|
||||
field
|
||||
)
|
||||
|
|
@ -373,21 +374,23 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
|
|||
}
|
||||
} else {
|
||||
for _, m = range methods {
|
||||
obj, _, indirect := lookupFieldOrMethodImpl(V, false, m.pkg, m.name, false)
|
||||
obj, index, indirect := lookupFieldOrMethodImpl(V, false, m.pkg, m.name, false)
|
||||
|
||||
// check if m is on *V, or on V with case-folding
|
||||
// check if m is ambiguous, on *V, or on V with case-folding
|
||||
if obj == nil {
|
||||
if indirect {
|
||||
switch {
|
||||
case index != nil:
|
||||
state = ambigSel
|
||||
case indirect:
|
||||
state = ptrRecv
|
||||
break
|
||||
default:
|
||||
state = notFound
|
||||
obj, _, _ = lookupFieldOrMethodImpl(V, false, m.pkg, m.name, true /* fold case */)
|
||||
f, _ = obj.(*Func)
|
||||
if f != nil {
|
||||
state = wrongName
|
||||
}
|
||||
}
|
||||
obj, _, _ = lookupFieldOrMethodImpl(V, false, m.pkg, m.name, true /* fold case */)
|
||||
f, _ = obj.(*Func)
|
||||
if f != nil {
|
||||
state = wrongName
|
||||
break
|
||||
}
|
||||
state = notFound
|
||||
break
|
||||
}
|
||||
|
||||
|
|
@ -438,6 +441,8 @@ func (check *Checker) missingMethod(V, T Type, static bool, equivalent func(x, y
|
|||
}
|
||||
*cause = check.sprintf("(wrong type for method %s)\n\t\thave %s\n\t\twant %s",
|
||||
m.Name(), fs, ms)
|
||||
case ambigSel:
|
||||
*cause = check.sprintf("(ambiguous selector %s.%s)", V, m.Name())
|
||||
case ptrRecv:
|
||||
*cause = check.sprintf("(method %s has pointer receiver)", m.Name())
|
||||
case field:
|
||||
|
|
|
|||
|
|
@ -195,5 +195,5 @@ var (
|
|||
)
|
||||
|
||||
var (
|
||||
_ interface{ xm() } = eD /* ERROR "missing method xm" */ {}
|
||||
_ interface{ xm() } = eD /* ERROR "ambiguous selector eD.xm" */ {}
|
||||
)
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// Copyright 2023 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 p
|
||||
|
||||
type A interface {
|
||||
a()
|
||||
}
|
||||
|
||||
type AB interface {
|
||||
A
|
||||
b()
|
||||
}
|
||||
|
||||
type AAB struct {
|
||||
A
|
||||
AB
|
||||
}
|
||||
|
||||
var _ AB = AAB /* ERROR "ambiguous selector AAB.a" */ {}
|
||||
Loading…
Reference in New Issue