Skip to content

Commit c90ead9

Browse files
committed
cmd/compile/internal/types2: delay union element checks
We cannot determine the underlying type right when parsing a union term since it may lead to types that are not yet fully set up. Fixes #46461. Change-Id: I1fcadb1dcef2160be2f088a4a34e99dbab01da67 Reviewed-on: https://go-review.googlesource.com/c/go/+/351969 Trust: Robert Griesemer <[email protected]> Run-TryBot: Robert Griesemer <[email protected]> TryBot-Result: Go Bot <[email protected]> Reviewed-by: Robert Findley <[email protected]>
1 parent 4e308d7 commit c90ead9

File tree

3 files changed

+27
-10
lines changed

3 files changed

+27
-10
lines changed

src/cmd/compile/internal/types2/testdata/fixedbugs/issue46461.go2

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,17 @@
44

55
package p
66

7+
// test case 1
78
type T[U interface{ M() T[U] }] int
89

910
type X int
1011

1112
func (X) M() T[X] { return 0 }
13+
14+
// test case 2
15+
type A[T interface{ A[T] }] interface{}
16+
17+
// test case 3
18+
type A2[U interface{ A2[U] }] interface{ M() A2[U] }
19+
20+
type I interface{ A2[I]; M() A2[I] }

src/cmd/compile/internal/types2/typeset.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
291291
terms = tset.terms
292292
case *TypeParam:
293293
// Embedding stand-alone type parameters is not permitted.
294-
// This case is handled during union parsing.
295-
unreachable()
294+
// Union parsing reports a (delayed) error, so we can ignore this entry.
295+
continue
296296
default:
297297
if typ == Typ[Invalid] {
298298
continue
@@ -372,8 +372,8 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet
372372
terms = computeInterfaceTypeSet(check, pos, u).terms
373373
case *TypeParam:
374374
// A stand-alone type parameters is not permitted as union term.
375-
// This case is handled during union parsing.
376-
unreachable()
375+
// Union parsing reports a (delayed) error, so we can ignore this entry.
376+
continue
377377
default:
378378
if t.typ == Typ[Invalid] {
379379
continue

src/cmd/compile/internal/types2/union.go

Lines changed: 14 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -54,7 +54,10 @@ func parseUnion(check *Checker, tlist []syntax.Expr) Type {
5454
for _, x := range tlist {
5555
tilde, typ := parseTilde(check, x)
5656
if len(tlist) == 1 && !tilde {
57-
return typ // single type (optimization)
57+
// Single type. Ok to return early because all relevant
58+
// checks have been performed in parseTilde (no need to
59+
// run through term validity check below).
60+
return typ
5861
}
5962
if len(terms) >= maxTermCount {
6063
check.errorf(x, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
@@ -123,11 +126,16 @@ func parseTilde(check *Checker, x syntax.Expr) (tilde bool, typ Type) {
123126
tilde = true
124127
}
125128
typ = check.typ(x)
126-
// embedding stand-alone type parameters is not permitted (issue #47127).
127-
if _, ok := under(typ).(*TypeParam); ok {
128-
check.error(x, "cannot embed a type parameter")
129-
typ = Typ[Invalid]
130-
}
129+
// Embedding stand-alone type parameters is not permitted (issue #47127).
130+
// Do this check later because it requires computation of the underlying type (see also issue #46461).
131+
// Note: If an underlying type cannot be a type parameter, the call to
132+
// under() will not be needed and then we don't need to delay this
133+
// check to later and could return Typ[Invalid] instead.
134+
check.later(func() {
135+
if _, ok := under(typ).(*TypeParam); ok {
136+
check.error(x, "cannot embed a type parameter")
137+
}
138+
})
131139
return
132140
}
133141

0 commit comments

Comments
 (0)