diff options
author | Robert Griesemer <gri@golang.org> | 2023-08-22 14:53:57 -0700 |
---|---|---|
committer | Gopher Robot <gobot@golang.org> | 2023-11-09 17:24:42 +0000 |
commit | bea55136b2d50fc514ddfba4380311295975a660 (patch) | |
tree | edc6d9d139d337afaaf5a51483a5261d6e2946a2 /src/cmd/compile/internal/types2/predicates.go | |
parent | 1b03ec8a25412342ca072c0860bdf046d58e82ac (diff) | |
download | go-bea55136b2d50fc514ddfba4380311295975a660.tar.gz go-bea55136b2d50fc514ddfba4380311295975a660.zip |
go/types, types2: introduce _Alias type node
This change introduces a new (unexported for now) _Alias type node
which serves as an explicit representation for alias types in type
alias declarations:
type A = T
The _Alias node stands for the type A in this declaration, with
the _Alias' actual type pointing to (the type node for) T.
Without the _Alias node, (the object for) A points directly to T.
Explicit _Alias nodes permit better error messages (they mention
A instead of T if the type in the source was named A) and can help
with certain type cycle problems. They are also needed to hold
type parameters for alias types, eventually.
Because an _Alias node is simply an alternative representation for
an aliased type, code that makes type-specific choices must always
look at the actual (unaliased) type denoted by a type alias.
The new function
func _Unalias(t Type) Type
performs the necessary indirection. Type switches that consider
type nodes, must either switch on _Unalias(typ) or handle the
_Alias case.
To avoid breaking clients, _Alias nodes must be enabled explicitly,
through the new Config flag _EnableAlias.
To run tests with the _EnableAlias set, use the new -alias flag as
in "go test -run short -alias". The testing harness understands
the flag as well and it may be used to enable/disable _Alias nodes
on a per-file basis, with a comment ("// -alias" or // -alias=false)
on the first line in those files. The file-based flag overrides the
command-line flag.
The use of _Alias nodes is disabled by default and must be enabled
by setting _EnableAlias.
Passes type checker tests with and without -alias flag set.
For #25838.
For #44410.
For #46477.
Change-Id: I78e178a1aef4d7f325088c0c6cbae4cfb1e5fb5c
Reviewed-on: https://go-review.googlesource.com/c/go/+/521956
Reviewed-by: Matthew Dempsky <mdempsky@google.com>
Reviewed-by: Robert Findley <rfindley@google.com>
Auto-Submit: Robert Griesemer <gri@google.com>
Reviewed-by: Robert Griesemer <gri@google.com>
TryBot-Result: Gopher Robot <gobot@golang.org>
Run-TryBot: Robert Griesemer <gri@google.com>
Diffstat (limited to 'src/cmd/compile/internal/types2/predicates.go')
-rw-r--r-- | src/cmd/compile/internal/types2/predicates.go | 23 |
1 files changed, 14 insertions, 9 deletions
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go index 11f543f475..9ec7d58d6f 100644 --- a/src/cmd/compile/internal/types2/predicates.go +++ b/src/cmd/compile/internal/types2/predicates.go @@ -7,7 +7,7 @@ package types2 // isValid reports whether t is a valid type. -func isValid(t Type) bool { return t != Typ[Invalid] } +func isValid(t Type) bool { return _Unalias(t) != Typ[Invalid] } // The isX predicates below report whether t is an X. // If t is a type parameter the result is false; i.e., @@ -50,7 +50,7 @@ func allNumericOrString(t Type) bool { return allBasic(t, IsNumeric|IsString) } // for all specific types of the type parameter's type set. // allBasic(t, info) is an optimized version of isBasic(coreType(t), info). func allBasic(t Type, info BasicInfo) bool { - if tpar, _ := t.(*TypeParam); tpar != nil { + if tpar, _ := _Unalias(t).(*TypeParam); tpar != nil { return tpar.is(func(t *term) bool { return t != nil && isBasic(t.typ, info) }) } return isBasic(t, info) @@ -60,7 +60,7 @@ func allBasic(t Type, info BasicInfo) bool { // predeclared types, defined types, and type parameters. // hasName may be called with types that are not fully set up. func hasName(t Type) bool { - switch t.(type) { + switch _Unalias(t).(type) { case *Basic, *Named, *TypeParam: return true } @@ -71,7 +71,7 @@ func hasName(t Type) bool { // This includes all non-defined types, but also basic types. // isTypeLit may be called with types that are not fully set up. func isTypeLit(t Type) bool { - switch t.(type) { + switch _Unalias(t).(type) { case *Named, *TypeParam: return false } @@ -82,8 +82,10 @@ func isTypeLit(t Type) bool { // constant or boolean. isTyped may be called with types that // are not fully set up. func isTyped(t Type) bool { - // isTyped is called with types that are not fully - // set up. Must not call under()! + // Alias or Named types cannot denote untyped types, + // thus we don't need to call _Unalias or under + // (which would be unsafe to do for types that are + // not fully set up). b, _ := t.(*Basic) return b == nil || b.info&IsUntyped == 0 } @@ -106,7 +108,7 @@ func isNonTypeParamInterface(t Type) bool { // isTypeParam reports whether t is a type parameter. func isTypeParam(t Type) bool { - _, ok := t.(*TypeParam) + _, ok := _Unalias(t).(*TypeParam) return ok } @@ -115,7 +117,7 @@ func isTypeParam(t Type) bool { // use anywhere, but it may report a false negative if the type set has not been // computed yet. func hasEmptyTypeset(t Type) bool { - if tpar, _ := t.(*TypeParam); tpar != nil && tpar.bound != nil { + if tpar, _ := _Unalias(t).(*TypeParam); tpar != nil && tpar.bound != nil { iface, _ := safeUnderlying(tpar.bound).(*Interface) return iface != nil && iface.tset != nil && iface.tset.IsEmpty() } @@ -221,6 +223,9 @@ type comparer struct { // For changes to this code the corresponding changes should be made to unifier.nify. func (c *comparer) identical(x, y Type, p *ifacePair) bool { + x = _Unalias(x) + y = _Unalias(y) + if x == y { return true } @@ -495,7 +500,7 @@ func identicalInstance(xorig Type, xargs []Type, yorig Type, yargs []Type) bool // it returns the incoming type for all other types. The default type // for untyped nil is untyped nil. func Default(t Type) Type { - if t, ok := t.(*Basic); ok { + if t, ok := _Unalias(t).(*Basic); ok { switch t.kind { case UntypedBool: return Typ[Bool] |