]> Cypherpunks repositories - gostls13.git/commitdiff
go/types, types2: simplify unification when x == y (pointer identity)
authorRobert Griesemer <gri@golang.org>
Fri, 24 Feb 2023 04:47:17 +0000 (20:47 -0800)
committerGopher Robot <gobot@golang.org>
Wed, 1 Mar 2023 21:01:42 +0000 (21:01 +0000)
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>

src/cmd/compile/internal/types2/unify.go
src/go/types/unify.go

index 365767b2e8e35aec611b4476d4bb5fbfdca1ee36..7bd7493c7d677808efd81a04132f3c8af6c72614 100644 (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
index dcbe26e42bcb51e1aa8683068388adbfe4b30f3a..b41b7af96a4fd2570ed1a0d48bac22af8002185c 100644 (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