aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatthew Dempsky <mdempsky@google.com>2022-12-01 17:24:23 -0800
committerDavid Chase <drchase@google.com>2023-02-09 18:01:12 +0000
commit90b06002c44e7fb8fd4b9227efd2d1423e21176b (patch)
tree7689152b1ffe1cbc8007990a647eeffcc5551600
parent487be3f90bf65c06eb5f1f30aec30cd0e5b24f92 (diff)
downloadgo-90b06002c44e7fb8fd4b9227efd2d1423e21176b.tar.gz
go-90b06002c44e7fb8fd4b9227efd2d1423e21176b.zip
[release-branch.go1.20] cmd/compile/internal/noder: stop creating TUNION types
In the types1 universe under the unified frontend, we never need to worry about type parameter constraints, so we only see pure interfaces. However, we might still see interfaces that contain union types, because of interfaces like "interface{ any | int }" (equivalent to just "any"). We can handle these without needing to actually represent type unions within types1 by simply mapping any union to "any". Fixes #58413. Change-Id: I5e4efcf0339edbb01f4035c54fb6fb1f9ddc0c65 Reviewed-on: https://go-review.googlesource.com/c/go/+/458619 Run-TryBot: Matthew Dempsky <mdempsky@google.com> Reviewed-by: Keith Randall <khr@google.com> TryBot-Result: Gopher Robot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org> (cherry picked from commit a7de684e1b6f460aae7d4dbf2568cb21130ec520) Reviewed-on: https://go-review.googlesource.com/c/go/+/466435 Reviewed-by: Than McIntosh <thanm@google.com> Run-TryBot: David Chase <drchase@google.com>
-rw-r--r--src/cmd/compile/internal/noder/reader.go32
-rw-r--r--test/typeparam/issue52124.go4
2 files changed, 29 insertions, 7 deletions
diff --git a/src/cmd/compile/internal/noder/reader.go b/src/cmd/compile/internal/noder/reader.go
index d03da27a46..189531959e 100644
--- a/src/cmd/compile/internal/noder/reader.go
+++ b/src/cmd/compile/internal/noder/reader.go
@@ -517,13 +517,33 @@ func (r *reader) doTyp() *types.Type {
}
func (r *reader) unionType() *types.Type {
- terms := make([]*types.Type, r.Len())
- tildes := make([]bool, len(terms))
- for i := range terms {
- tildes[i] = r.Bool()
- terms[i] = r.typ()
+ // In the types1 universe, we only need to handle value types.
+ // Impure interfaces (i.e., interfaces with non-trivial type sets
+ // like "int | string") can only appear as type parameter bounds,
+ // and this is enforced by the types2 type checker.
+ //
+ // However, type unions can still appear in pure interfaces if the
+ // type union is equivalent to "any". E.g., typeparam/issue52124.go
+ // declares variables with the type "interface { any | int }".
+ //
+ // To avoid needing to represent type unions in types1 (since we
+ // don't have any uses for that today anyway), we simply fold them
+ // to "any". As a consistency check, we still read the union terms
+ // to make sure this substitution is safe.
+
+ pure := false
+ for i, n := 0, r.Len(); i < n; i++ {
+ _ = r.Bool() // tilde
+ term := r.typ()
+ if term.IsEmptyInterface() {
+ pure = true
+ }
+ }
+ if !pure {
+ base.Fatalf("impure type set used in value type")
}
- return types.NewUnion(terms, tildes)
+
+ return types.Types[types.TINTER]
}
func (r *reader) interfaceType() *types.Type {
diff --git a/test/typeparam/issue52124.go b/test/typeparam/issue52124.go
index a113fc7444..07cba47982 100644
--- a/test/typeparam/issue52124.go
+++ b/test/typeparam/issue52124.go
@@ -6,7 +6,9 @@
package p
-type I interface{ any | int }
+type Any any
+
+type I interface{ Any | int }
var (
X I = 42