1
0
mirror of https://github.com/golang/go synced 2024-11-17 19:04:47 -07:00

go/types, types2: handle unbound type parameters in switch (cleanup)

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>
This commit is contained in:
Robert Griesemer 2023-02-28 09:43:36 -08:00 committed by Gopher Robot
parent 4eb3aea2b5
commit 052a36ccbe
2 changed files with 80 additions and 80 deletions

View 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

View 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