go/types, types2: use exact matching when unifying constraint method signatures

Fixes #60556.

Change-Id: I203a0bc79eff607654c3e8350d259e694cb035b2
Reviewed-on: https://go-review.googlesource.com/c/go/+/499995
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
This commit is contained in:
Robert Griesemer 2023-06-01 10:16:01 -07:00 committed by Gopher Robot
parent 936ce874ac
commit 7183e77cc0
3 changed files with 33 additions and 2 deletions

View File

@ -249,9 +249,15 @@ func (check *Checker) infer(pos syntax.Pos, tparams []*TypeParam, targs []Type,
// It must have (at least) all the methods of the type constraint,
// and the method signatures must unify; otherwise tx cannot satisfy
// the constraint.
// TODO(gri) Now that unification handles interfaces, this code can
// be reduced to calling u.unify(tx, tpar.iface(), assign)
// (which will compare signatures exactly as we do below).
// We leave it as is for now because missingMethod provides
// a failure cause which allows for a better error message.
// Eventually, unify should return an error with cause.
var cause string
constraint := tpar.iface()
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, 0) }, &cause); m != nil {
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, exact) }, &cause); m != nil {
// TODO(gri) better error message (see TODO above)
check.errorf(pos, CannotInferTypeArgs, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
return nil

View File

@ -251,9 +251,15 @@ func (check *Checker) infer(posn positioner, tparams []*TypeParam, targs []Type,
// It must have (at least) all the methods of the type constraint,
// and the method signatures must unify; otherwise tx cannot satisfy
// the constraint.
// TODO(gri) Now that unification handles interfaces, this code can
// be reduced to calling u.unify(tx, tpar.iface(), assign)
// (which will compare signatures exactly as we do below).
// We leave it as is for now because missingMethod provides
// a failure cause which allows for a better error message.
// Eventually, unify should return an error with cause.
var cause string
constraint := tpar.iface()
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, 0) }, &cause); m != nil {
if m, _ := check.missingMethod(tx, constraint, true, func(x, y Type) bool { return u.unify(x, y, exact) }, &cause); m != nil {
// TODO(gri) better error message (see TODO above)
check.errorf(posn, CannotInferTypeArgs, "%s (type %s) does not satisfy %s %s", tpar, tx, tpar.Constraint(), cause)
return nil

View File

@ -0,0 +1,19 @@
// 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 I[T any] interface {
m(I[T])
}
type S[T any] struct{}
func (S[T]) m(I[T]) {}
func f[T I[E], E any](T) {}
func _() {
f(S[int]{})
}