aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/types2/unify.go4
-rw-r--r--src/go/types/unify.go4
-rw-r--r--src/internal/types/testdata/spec/methods.go8
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