]> Cypherpunks repositories - gostls13.git/commitdiff
go/types: delay union element checks
authorRobert Griesemer <gri@golang.org>
Fri, 24 Sep 2021 00:35:36 +0000 (17:35 -0700)
committerRobert Griesemer <gri@golang.org>
Fri, 24 Sep 2021 01:18:01 +0000 (01:18 +0000)
This is a clean port of CL 351969 from types2 to go/types
with a minor adjustment for error handling (provide an error
code).

For #46461.

Change-Id: I493dde12d8ccf86aa33f4913ac6e82f2eb459088
Reviewed-on: https://go-review.googlesource.com/c/go/+/351971
Trust: Robert Griesemer <gri@golang.org>
Reviewed-by: Robert Findley <rfindley@google.com>
src/go/types/testdata/fixedbugs/issue46461.go2
src/go/types/typeset.go
src/go/types/union.go

index bfeaf3a96689adf35ab04861ad98df7f9e729001..8bf31090b8b5e76be7b8549fe6732cdf55fef3d1 100644 (file)
@@ -4,8 +4,17 @@
 
 package p
 
+// test case 1
 type T[U interface{ M() T[U] }] int
 
 type X int
 
 func (X) M() T[X] { return 0 }
+
+// test case 2
+type A[T interface{ A[T] }] interface{}
+
+// test case 3
+type A2[U interface{ A2[U] }] interface{ M() A2[U] }
+
+type I interface{ A2[I]; M() A2[I] }
index 648d3c7bf3ff9c6a8642fe555a5aca19e0333bca..3e59155e5c6b5acfaba58f94e8cbdf968c408ccf 100644 (file)
@@ -289,8 +289,8 @@ func computeInterfaceTypeSet(check *Checker, pos token.Pos, ityp *Interface) *_T
                        terms = tset.terms
                case *TypeParam:
                        // Embedding stand-alone type parameters is not permitted.
-                       // This case is handled during union parsing.
-                       unreachable()
+                       // Union parsing reports a (delayed) error, so we can ignore this entry.
+                       continue
                default:
                        if typ == Typ[Invalid] {
                                continue
@@ -370,8 +370,8 @@ func computeUnionTypeSet(check *Checker, pos token.Pos, utyp *Union) *_TypeSet {
                        terms = computeInterfaceTypeSet(check, pos, u).terms
                case *TypeParam:
                        // A stand-alone type parameters is not permitted as union term.
-                       // This case is handled during union parsing.
-                       unreachable()
+                       // Union parsing reports a (delayed) error, so we can ignore this entry.
+                       continue
                default:
                        if t.typ == Typ[Invalid] {
                                continue
index f6b32b9e5df0450ae688f9db7616e8ba9c05b66c..88b2a9ff8f074a2c53d73ea054dc5f4f6927090d 100644 (file)
@@ -57,7 +57,10 @@ func parseUnion(check *Checker, tlist []ast.Expr) Type {
        for _, x := range tlist {
                tilde, typ := parseTilde(check, x)
                if len(tlist) == 1 && !tilde {
-                       return typ // single type (optimization)
+                       // Single type. Ok to return early because all relevant
+                       // checks have been performed in parseTilde (no need to
+                       // run through term validity check below).
+                       return typ
                }
                if len(terms) >= maxTermCount {
                        check.errorf(x, _Todo, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
@@ -126,11 +129,16 @@ func parseTilde(check *Checker, x ast.Expr) (tilde bool, typ Type) {
                tilde = true
        }
        typ = check.typ(x)
-       // embedding stand-alone type parameters is not permitted (issue #47127).
-       if _, ok := under(typ).(*TypeParam); ok {
-               check.error(x, _Todo, "cannot embed a type parameter")
-               typ = Typ[Invalid]
-       }
+       // Embedding stand-alone type parameters is not permitted (issue #47127).
+       // Do this check later because it requires computation of the underlying type (see also issue #46461).
+       // Note: If an underlying type cannot be a type parameter, the call to
+       //       under() will not be needed and then we don't need to delay this
+       //       check to later and could return Typ[Invalid] instead.
+       check.later(func() {
+               if _, ok := under(typ).(*TypeParam); ok {
+                       check.error(x, _Todo, "cannot embed a type parameter")
+               }
+       })
        return
 }