diff options
| -rw-r--r-- | src/cmd/compile/internal/types2/unify.go | 4 | ||||
| -rw-r--r-- | src/go/types/unify.go | 4 | ||||
| -rw-r--r-- | src/internal/types/testdata/spec/methods.go | 8 |
3 files changed, 14 insertions, 2 deletions
diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go index 7250d82478..9e90c5fc7d 100644 --- a/src/cmd/compile/internal/types2/unify.go +++ b/src/cmd/compile/internal/types2/unify.go @@ -534,10 +534,12 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) { // the non-interface type, otherwise unification fails. if xi != nil { // All xi methods must exist in y and corresponding signatures must unify. + // A generic method never satisfies an interface method, so fail rather + // than unify ym's own type parameter into an inference variable. xmethods := xi.typeSet().methods for _, xm := range xmethods { obj, _, _ := LookupFieldOrMethod(y, false, xm.pkg, xm.name) - if ym, _ := obj.(*Func); ym == nil || !u.nify(xm.typ, ym.typ, exact, p) { + if ym, _ := obj.(*Func); ym == nil || ym.Signature().TypeParams().Len() > 0 || !u.nify(xm.typ, ym.typ, exact, p) { return false } } diff --git a/src/go/types/unify.go b/src/go/types/unify.go index bf072c09d9..070f9d4482 100644 --- a/src/go/types/unify.go +++ b/src/go/types/unify.go @@ -537,10 +537,12 @@ func (u *unifier) nify(x, y Type, mode unifyMode, p *ifacePair) (result bool) { // the non-interface type, otherwise unification fails. if xi != nil { // All xi methods must exist in y and corresponding signatures must unify. + // A generic method never satisfies an interface method, so fail rather + // than unify ym's own type parameter into an inference variable. xmethods := xi.typeSet().methods for _, xm := range xmethods { obj, _, _ := LookupFieldOrMethod(y, false, xm.pkg, xm.name) - if ym, _ := obj.(*Func); ym == nil || !u.nify(xm.typ, ym.typ, exact, p) { + if ym, _ := obj.(*Func); ym == nil || ym.Signature().TypeParams().Len() > 0 || !u.nify(xm.typ, ym.typ, exact, p) { return false } } diff --git a/src/internal/types/testdata/spec/methods.go b/src/internal/types/testdata/spec/methods.go index f7eeee5865..532910b1ab 100644 --- a/src/internal/types/testdata/spec/methods.go +++ b/src/internal/types/testdata/spec/methods.go @@ -77,6 +77,14 @@ func (V) m[_ any]() {} var _ J = V /* ERROR "wrong type for method m)\n\t\thave m[_ any]()\n\t\twant m()" */ {} +// In particular, interface inference must not unify a generic method's +// own type parameter into an inference variable. +func need[X any](I[X]) {} + +func _() { + need(T /* ERROR "type T of T{} does not match I[X] (cannot infer X)" */ {}) +} + // Test case from parser smoke test. type List[E any] []E |
