go/types, types2: simplify unification when x == y (pointer identity)

Because we rename type parameters to avoid problems with self-recursive
function calls, there's no need anymore for special (and hard to follow)
logic for pointer-identical types. If they are identical, we have a
match. Simplify the code accordingly.

Change-Id: I2e1838a43e90fa4abfae3ab9e4f7da6463508966
Reviewed-on: https://go-review.googlesource.com/c/go/+/471018
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
This commit is contained in:
Robert Griesemer 2023-02-23 20:47:17 -08:00 committed by Gopher Robot
parent e2f2123e25
commit 35a4d1b3bc
2 changed files with 28 additions and 28 deletions

View File

@ -231,10 +231,6 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
return list
}
func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool {
return x == y || u.nify(x, y, p)
}
// nify implements the core unification algorithm which is an
// adapted version of Checker.identical. For changes to that
// code the corresponding changes should be made here.
@ -251,6 +247,11 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
u.depth--
}()
// nothing to do if x == y
if x == y {
return true
}
// Stop gap for cases where unification fails.
if u.depth > unificationDepthLimit {
if traceInference {
@ -298,6 +299,10 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
// Per the spec, a defined type cannot have an underlying type
// that is a type parameter.
assert(!isTypeParam(y))
// x and y may be identical now
if x == y {
return true
}
}
// Cases where at least one of x or y is a type parameter recorded with u.
@ -313,13 +318,13 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
return true
}
// both x and y have an inferred type - they must match
return u.nifyEq(u.at(px), u.at(py), p)
return u.nify(u.at(px), u.at(py), p)
case px != nil:
// x is a type parameter, y is not
if x := u.at(px); x != nil {
// x has an inferred type which must match y
if u.nifyEq(x, y, p) {
if u.nify(x, y, p) {
// If we have a match, possibly through underlying types,
// and y is a defined type, make sure we record that type
// for type parameter x, which may have until now only
@ -377,10 +382,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
}
}
// For type unification, do not shortcut (x == y) for identical
// types. Instead keep comparing them element-wise to unify the
// matching (and equal type parameter types). A simple test case
// where this matters is: func f[P any](a P) { f(a) } .
// x != y if we reach here
assert(x != y)
switch x := x.(type) {
case *Basic:
@ -556,10 +559,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
}
case *TypeParam:
// Two type parameters (which are not part of the type parameters of the
// enclosing type as those are handled in the beginning of this function)
// are identical if they originate in the same declaration.
return x == y
// nothing to do - we know x != y
case nil:
// avoid a crash in case of nil type

View File

@ -233,10 +233,6 @@ func (u *unifier) inferred(tparams []*TypeParam) []Type {
return list
}
func (u *unifier) nifyEq(x, y Type, p *ifacePair) bool {
return x == y || u.nify(x, y, p)
}
// nify implements the core unification algorithm which is an
// adapted version of Checker.identical. For changes to that
// code the corresponding changes should be made here.
@ -253,6 +249,11 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
u.depth--
}()
// nothing to do if x == y
if x == y {
return true
}
// Stop gap for cases where unification fails.
if u.depth > unificationDepthLimit {
if traceInference {
@ -300,6 +301,10 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
// Per the spec, a defined type cannot have an underlying type
// that is a type parameter.
assert(!isTypeParam(y))
// x and y may be identical now
if x == y {
return true
}
}
// Cases where at least one of x or y is a type parameter recorded with u.
@ -315,13 +320,13 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
return true
}
// both x and y have an inferred type - they must match
return u.nifyEq(u.at(px), u.at(py), p)
return u.nify(u.at(px), u.at(py), p)
case px != nil:
// x is a type parameter, y is not
if x := u.at(px); x != nil {
// x has an inferred type which must match y
if u.nifyEq(x, y, p) {
if u.nify(x, y, p) {
// If we have a match, possibly through underlying types,
// and y is a defined type, make sure we record that type
// for type parameter x, which may have until now only
@ -379,10 +384,8 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
}
}
// For type unification, do not shortcut (x == y) for identical
// types. Instead keep comparing them element-wise to unify the
// matching (and equal type parameter types). A simple test case
// where this matters is: func f[P any](a P) { f(a) } .
// x != y if we reach here
assert(x != y)
switch x := x.(type) {
case *Basic:
@ -558,10 +561,7 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
}
case *TypeParam:
// Two type parameters (which are not part of the type parameters of the
// enclosing type as those are handled in the beginning of this function)
// are identical if they originate in the same declaration.
return x == y
// nothing to do - we know x != y
case nil:
// avoid a crash in case of nil type