aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile
diff options
context:
space:
mode:
authorRobert Griesemer <gri@golang.org>2021-12-15 11:24:56 -0800
committerRobert Griesemer <gri@golang.org>2021-12-15 20:26:10 +0000
commit4cda05d41a8585c79bfe00f867ed3513672e69fa (patch)
treec59da2f30e3bdcbe46f65273bed30441f2b33333 /src/cmd/compile
parentbc0aba971705722b6798746b2003908166ee007b (diff)
downloadgo-4cda05d41a8585c79bfe00f867ed3513672e69fa.tar.gz
go-4cda05d41a8585c79bfe00f867ed3513672e69fa.zip
cmd/compile/internal/types2: externalize union type sets
This is a port of CL 371756 from go/types to types2 with minor adjustments due to different error handling or AST. Updates #50093 Change-Id: Iab6a4634f8fc917bf99df439d31098624085f52a Reviewed-on: https://go-review.googlesource.com/c/go/+/372474 Trust: Robert Griesemer <gri@golang.org> Reviewed-by: Robert Findley <rfindley@google.com>
Diffstat (limited to 'src/cmd/compile')
-rw-r--r--src/cmd/compile/internal/types2/check.go2
-rw-r--r--src/cmd/compile/internal/types2/predicates.go7
-rw-r--r--src/cmd/compile/internal/types2/sizeof_test.go2
-rw-r--r--src/cmd/compile/internal/types2/subst.go2
-rw-r--r--src/cmd/compile/internal/types2/typeset.go28
-rw-r--r--src/cmd/compile/internal/types2/union.go7
6 files changed, 31 insertions, 17 deletions
diff --git a/src/cmd/compile/internal/types2/check.go b/src/cmd/compile/internal/types2/check.go
index aacbb25b3b..22a921d0d7 100644
--- a/src/cmd/compile/internal/types2/check.go
+++ b/src/cmd/compile/internal/types2/check.go
@@ -129,6 +129,7 @@ type Checker struct {
imports []*PkgName // list of imported packages
dotImportMap map[dotImportKey]*PkgName // maps dot-imported objects to the package they were dot-imported through
recvTParamMap map[*syntax.Name]*TypeParam // maps blank receiver type parameters to their type
+ unionTypeSets map[*Union]*_TypeSet // computed type sets for union types
mono monoGraph // graph for detecting non-monomorphizable instantiation loops
firstErr error // first error encountered
@@ -330,6 +331,7 @@ func (check *Checker) checkFiles(files []*syntax.File) (err error) {
check.pkgPathMap = nil
check.seenPkgMap = nil
check.recvTParamMap = nil
+ check.unionTypeSets = nil
check.defTypes = nil
check.ctxt = nil
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go
index cf2993f68b..d982866f8e 100644
--- a/src/cmd/compile/internal/types2/predicates.go
+++ b/src/cmd/compile/internal/types2/predicates.go
@@ -287,8 +287,11 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
case *Union:
if y, _ := y.(*Union); y != nil {
- xset := computeUnionTypeSet(nil, nopos, x)
- yset := computeUnionTypeSet(nil, nopos, y)
+ // TODO(rfindley): can this be reached during type checking? If so,
+ // consider passing a type set map.
+ unionSets := make(map[*Union]*_TypeSet)
+ xset := computeUnionTypeSet(nil, unionSets, nopos, x)
+ yset := computeUnionTypeSet(nil, unionSets, nopos, y)
return xset.terms.equal(yset.terms)
}
diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go
index 99b846b80b..8db2d60e80 100644
--- a/src/cmd/compile/internal/types2/sizeof_test.go
+++ b/src/cmd/compile/internal/types2/sizeof_test.go
@@ -27,7 +27,7 @@ func TestSizeof(t *testing.T) {
{Pointer{}, 8, 16},
{Tuple{}, 12, 24},
{Signature{}, 28, 56},
- {Union{}, 16, 32},
+ {Union{}, 12, 24},
{Interface{}, 44, 88},
{Map{}, 16, 32},
{Chan{}, 12, 24},
diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go
index 516f248127..4108f6aa85 100644
--- a/src/cmd/compile/internal/types2/subst.go
+++ b/src/cmd/compile/internal/types2/subst.go
@@ -130,7 +130,7 @@ func (subst *subster) typ(typ Type) Type {
// term list substitution may introduce duplicate terms (unlikely but possible).
// This is ok; lazy type set computation will determine the actual type set
// in normal form.
- return &Union{terms, nil}
+ return &Union{terms}
}
case *Interface:
diff --git a/src/cmd/compile/internal/types2/typeset.go b/src/cmd/compile/internal/types2/typeset.go
index cbb454aa6a..0d8d02662b 100644
--- a/src/cmd/compile/internal/types2/typeset.go
+++ b/src/cmd/compile/internal/types2/typeset.go
@@ -199,6 +199,16 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
// reason.
ityp.tset = &_TypeSet{terms: allTermlist} // TODO(gri) is this sufficient?
+ var unionSets map[*Union]*_TypeSet
+ if check != nil {
+ if check.unionTypeSets == nil {
+ check.unionTypeSets = make(map[*Union]*_TypeSet)
+ }
+ unionSets = check.unionTypeSets
+ } else {
+ unionSets = make(map[*Union]*_TypeSet)
+ }
+
// Methods of embedded interfaces are collected unchanged; i.e., the identity
// of a method I.m's Func Object of an interface I is the same as that of
// the method m in an interface that embeds interface I. On the other hand,
@@ -290,7 +300,7 @@ func computeInterfaceTypeSet(check *Checker, pos syntax.Pos, ityp *Interface) *_
check.versionErrorf(pos, "go1.18", "embedding interface element %s", u)
continue
}
- tset := computeUnionTypeSet(check, pos, u)
+ tset := computeUnionTypeSet(check, unionSets, pos, u)
if tset == &invalidTypeSet {
continue // ignore invalid unions
}
@@ -358,13 +368,13 @@ 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
+func computeUnionTypeSet(check *Checker, unionSets map[*Union]*_TypeSet, pos syntax.Pos, utyp *Union) *_TypeSet {
+ if tset, _ := unionSets[utyp]; tset != nil {
+ return tset
}
// avoid infinite recursion (see also computeInterfaceTypeSet)
- utyp.tset = new(_TypeSet)
+ unionSets[utyp] = new(_TypeSet)
var allTerms termlist
for _, t := range utyp.terms {
@@ -391,11 +401,11 @@ func computeUnionTypeSet(check *Checker, pos syntax.Pos, utyp *Union) *_TypeSet
if check != nil {
check.errorf(pos, "cannot handle more than %d union terms (implementation limitation)", maxTermCount)
}
- utyp.tset = &invalidTypeSet
- return utyp.tset
+ unionSets[utyp] = &invalidTypeSet
+ return unionSets[utyp]
}
}
- utyp.tset.terms = allTerms
+ unionSets[utyp].terms = allTerms
- return utyp.tset
+ return unionSets[utyp]
}
diff --git a/src/cmd/compile/internal/types2/union.go b/src/cmd/compile/internal/types2/union.go
index 97581fe863..98dd6cedc7 100644
--- a/src/cmd/compile/internal/types2/union.go
+++ b/src/cmd/compile/internal/types2/union.go
@@ -11,8 +11,7 @@ import "cmd/compile/internal/syntax"
// A Union represents a union of terms embedded in an interface.
type Union struct {
- terms []*Term // list of syntactical terms (not a canonicalized termlist)
- tset *_TypeSet // type set described by this union, computed lazily
+ terms []*Term // list of syntactical terms (not a canonicalized termlist)
}
// NewUnion returns a new Union type with the given terms.
@@ -21,7 +20,7 @@ func NewUnion(terms []*Term) *Union {
if len(terms) == 0 {
panic("empty union")
}
- return &Union{terms, nil}
+ return &Union{terms}
}
func (u *Union) Len() int { return len(u.terms) }
@@ -107,7 +106,7 @@ func parseUnion(check *Checker, uexpr syntax.Expr) Type {
}
})
- u := &Union{terms, nil}
+ u := &Union{terms}
check.recordTypeAndValue(uexpr, typexpr, u, nil)
return u
}