Skip to content

Commit

Permalink
[release-branch.go1.20] cmd/compile/internal/noder: stop creating TUN…
Browse files Browse the repository at this point in the history
…ION 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 a7de684)
Reviewed-on: https://go-review.googlesource.com/c/go/+/466435
Reviewed-by: Than McIntosh <thanm@google.com>
Run-TryBot: David Chase <drchase@google.com>
  • Loading branch information
mdempsky authored and dr2chase committed Feb 9, 2023
1 parent 487be3f commit 90b0600
Show file tree
Hide file tree
Showing 2 changed files with 29 additions and 7 deletions.
32 changes: 26 additions & 6 deletions src/cmd/compile/internal/noder/reader.go
Expand Up @@ -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 {
Expand Down
4 changes: 3 additions & 1 deletion test/typeparam/issue52124.go
Expand Up @@ -6,7 +6,9 @@

package p

type I interface{ any | int }
type Any any

type I interface{ Any | int }

var (
X I = 42
Expand Down

0 comments on commit 90b0600

Please sign in to comment.