]> Cypherpunks.ru repositories - gostls13.git/commitdiff
go/types, types2: handle unbound type parameters in switch (cleanup)
authorRobert Griesemer <gri@golang.org>
Tue, 28 Feb 2023 17:43:36 +0000 (09:43 -0800)
committerGopher Robot <gobot@golang.org>
Wed, 1 Mar 2023 21:23:47 +0000 (21:23 +0000)
This simply moves the special handling for unbound type parameters
into the switch (which already looks for type parameters).

Change-Id: I2d6d22f3fdffc443065c3681a442288cd1d375ef
Reviewed-on: https://go-review.googlesource.com/c/go/+/472115
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
src/cmd/compile/internal/types2/unify.go
src/go/types/unify.go

index 7bd7493c7d677808efd81a04132f3c8af6c72614..23362bf76651b0da1073cb9f102e02d0df1aeaf3 100644 (file)
@@ -341,50 +341,20 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
                return true
        }
 
+       // x != y if we get here
+       assert(x != y)
+
        // If we get here and x or y is a type parameter, they are unbound
        // (not recorded with the unifier).
-       // By definition, a valid type argument must be in the type set of
-       // the respective type constraint. Therefore, the type argument's
-       // underlying type must be in the set of underlying types of that
-       // constraint. If there is a single such underlying type, it's the
-       // constraint's core type. It must match the type argument's under-
-       // lying type, irrespective of whether the actual type argument,
-       // which may be a defined type, is actually in the type set (that
-       // will be determined at instantiation time).
-       // Thus, if we have the core type of an unbound type parameter,
-       // we know the structure of the possible types satisfying such
-       // parameters. Use that core type for further unification
-       // (see go.dev/issue/50755 for a test case).
-       if enableCoreTypeUnification {
-               // swap x and y as needed
-               // (the earlier swap checks for _recorded_ type parameters only)
-               if isTypeParam(y) {
-                       if traceInference {
-                               u.tracef("%s ≡ %s (swap)", y, x)
-                       }
-                       x, y = y, x
-               }
-               if isTypeParam(x) {
-                       // When considering the type parameter for unification
-                       // we look at the core type.
-                       // Because the core type is always an underlying type,
-                       // unification will take care of matching against a
-                       // defined or literal type automatically.
-                       // If y is also an unbound type parameter, we will end
-                       // up here again with x and y swapped, so we don't
-                       // need to take care of that case separately.
-                       if cx := coreType(x); cx != nil {
-                               if traceInference {
-                                       u.tracef("core %s ≡ %s", x, y)
-                               }
-                               return u.nify(cx, y, p)
-                       }
+       // Ensure that if we have at least one type parameter, it is in x
+       // (the earlier swap checks for _recorded_ type parameters only).
+       if isTypeParam(y) {
+               if traceInference {
+                       u.tracef("%s ≡ %s (swap)", y, x)
                }
+               x, y = y, x
        }
 
-       // x != y if we reach here
-       assert(x != y)
-
        switch x := x.(type) {
        case *Basic:
                // Basic types are singletons except for the rune and byte
@@ -559,7 +529,37 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
                }
 
        case *TypeParam:
-               // nothing to do - we know x != y
+               // x must be an unbound type parameter (see comment above).
+               if debug {
+                       assert(u.asTypeParam(x) == nil)
+               }
+               // By definition, a valid type argument must be in the type set of
+               // the respective type constraint. Therefore, the type argument's
+               // underlying type must be in the set of underlying types of that
+               // constraint. If there is a single such underlying type, it's the
+               // constraint's core type. It must match the type argument's under-
+               // lying type, irrespective of whether the actual type argument,
+               // which may be a defined type, is actually in the type set (that
+               // will be determined at instantiation time).
+               // Thus, if we have the core type of an unbound type parameter,
+               // we know the structure of the possible types satisfying such
+               // parameters. Use that core type for further unification
+               // (see go.dev/issue/50755 for a test case).
+               if enableCoreTypeUnification {
+                       // Because the core type is always an underlying type,
+                       // unification will take care of matching against a
+                       // defined or literal type automatically.
+                       // If y is also an unbound type parameter, we will end
+                       // up here again with x and y swapped, so we don't
+                       // need to take care of that case separately.
+                       if cx := coreType(x); cx != nil {
+                               if traceInference {
+                                       u.tracef("core %s ≡ %s", x, y)
+                               }
+                               return u.nify(cx, y, p)
+                       }
+               }
+               // x != y and there's nothing to do
 
        case nil:
                // avoid a crash in case of nil type
index b41b7af96a4fd2570ed1a0d48bac22af8002185c..89af7745b43e73f11ca6a17b1f6e8b02f2dd6f9b 100644 (file)
@@ -343,50 +343,20 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
                return true
        }
 
+       // x != y if we get here
+       assert(x != y)
+
        // If we get here and x or y is a type parameter, they are unbound
        // (not recorded with the unifier).
-       // By definition, a valid type argument must be in the type set of
-       // the respective type constraint. Therefore, the type argument's
-       // underlying type must be in the set of underlying types of that
-       // constraint. If there is a single such underlying type, it's the
-       // constraint's core type. It must match the type argument's under-
-       // lying type, irrespective of whether the actual type argument,
-       // which may be a defined type, is actually in the type set (that
-       // will be determined at instantiation time).
-       // Thus, if we have the core type of an unbound type parameter,
-       // we know the structure of the possible types satisfying such
-       // parameters. Use that core type for further unification
-       // (see go.dev/issue/50755 for a test case).
-       if enableCoreTypeUnification {
-               // swap x and y as needed
-               // (the earlier swap checks for _recorded_ type parameters only)
-               if isTypeParam(y) {
-                       if traceInference {
-                               u.tracef("%s ≡ %s (swap)", y, x)
-                       }
-                       x, y = y, x
-               }
-               if isTypeParam(x) {
-                       // When considering the type parameter for unification
-                       // we look at the core type.
-                       // Because the core type is always an underlying type,
-                       // unification will take care of matching against a
-                       // defined or literal type automatically.
-                       // If y is also an unbound type parameter, we will end
-                       // up here again with x and y swapped, so we don't
-                       // need to take care of that case separately.
-                       if cx := coreType(x); cx != nil {
-                               if traceInference {
-                                       u.tracef("core %s ≡ %s", x, y)
-                               }
-                               return u.nify(cx, y, p)
-                       }
+       // Ensure that if we have at least one type parameter, it is in x
+       // (the earlier swap checks for _recorded_ type parameters only).
+       if isTypeParam(y) {
+               if traceInference {
+                       u.tracef("%s ≡ %s (swap)", y, x)
                }
+               x, y = y, x
        }
 
-       // x != y if we reach here
-       assert(x != y)
-
        switch x := x.(type) {
        case *Basic:
                // Basic types are singletons except for the rune and byte
@@ -561,7 +531,37 @@ func (u *unifier) nify(x, y Type, p *ifacePair) (result bool) {
                }
 
        case *TypeParam:
-               // nothing to do - we know x != y
+               // x must be an unbound type parameter (see comment above).
+               if debug {
+                       assert(u.asTypeParam(x) == nil)
+               }
+               // By definition, a valid type argument must be in the type set of
+               // the respective type constraint. Therefore, the type argument's
+               // underlying type must be in the set of underlying types of that
+               // constraint. If there is a single such underlying type, it's the
+               // constraint's core type. It must match the type argument's under-
+               // lying type, irrespective of whether the actual type argument,
+               // which may be a defined type, is actually in the type set (that
+               // will be determined at instantiation time).
+               // Thus, if we have the core type of an unbound type parameter,
+               // we know the structure of the possible types satisfying such
+               // parameters. Use that core type for further unification
+               // (see go.dev/issue/50755 for a test case).
+               if enableCoreTypeUnification {
+                       // Because the core type is always an underlying type,
+                       // unification will take care of matching against a
+                       // defined or literal type automatically.
+                       // If y is also an unbound type parameter, we will end
+                       // up here again with x and y swapped, so we don't
+                       // need to take care of that case separately.
+                       if cx := coreType(x); cx != nil {
+                               if traceInference {
+                                       u.tracef("core %s ≡ %s", x, y)
+                               }
+                               return u.nify(cx, y, p)
+                       }
+               }
+               // x != y and there's nothing to do
 
        case nil:
                // avoid a crash in case of nil type