aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types2/typeset.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/types2/typeset.go')
-rw-r--r--src/cmd/compile/internal/types2/typeset.go27
1 files changed, 24 insertions, 3 deletions
diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go
index da364699ce..5955bbe805 100644
--- a/src/cmd/compile/internal/types2/typeset.go
+++ b/src/cmd/compile/internal/types2/typeset.go
@@ -268,9 +268,9 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T
pos = (*ityp.embedPos)[i]
}
var terms termlist
- switch t := under(typ).(type) {
+ switch u := under(typ).(type) {
case *Interface:
- tset := computeInterfaceTypeSet(check, pos, t)
+ tset := computeInterfaceTypeSet(check, pos, u)
if tset.comparable {
ityp.tset.comparable = true
}
@@ -279,7 +279,10 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T
}
terms = tset.terms
case *Union:
- tset := computeUnionTypeSet(check, pos, t)
+ tset := computeUnionTypeSet(check, pos, u)
+ if tset == &invalidTypeSet {
+ continue // ignore invalid unions
+ }
terms = tset.terms
case *TypeParam:
// Embedding stand-alone type parameters is not permitted.
@@ -297,6 +300,8 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *T
}
// The type set of an interface is the intersection
// of the type sets of all its elements.
+ // Intersection cannot produce longer termlists and
+ // thus cannot overflow.
allTerms = allTerms.intersect(terms)
}
ityp.embedPos = nil // not needed anymore (errors have been reported)
@@ -339,7 +344,13 @@ func (a byUniqueMethodName) Len() int { return len(a) }
func (a byUniqueMethodName) Less(i, j int) bool { return a[i].less(&a[j].object) }
func (a byUniqueMethodName) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
+// invalidTypeSet is a singleton type set to signal an invalid type set
+// due to an error. It's also a valid empty type set, so consumers of
+// type sets may choose to ignore it.
+var invalidTypeSet TypeSet
+
// computeUnionTypeSet may be called with check == nil.
+// The result is &invalidTypeSet if the union overflows.
func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *TypeSet {
if utyp.tset != nil {
return utyp.tset
@@ -359,11 +370,21 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *TypeSet {
// This case is handled during union parsing.
unreachable()
default:
+ if t.typ == Typ[Invalid] {
+ continue
+ }
terms = termlist{(*term)(t)}
}
// The type set of a union expression is the union
// of the type sets of each term.
allTerms = allTerms.union(terms)
+ if len(allTerms) > maxTermCount {
+ if check != nil {
+ check.errorf(pos, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
+ }
+ utyp.tset = &invalidTypeSet
+ return utyp.tset
+ }
}
utyp.tset.terms = allTerms