diff options
author | Robert Griesemer <gri@golang.org> | 2021-12-15 11:24:56 -0800 |
---|---|---|
committer | Robert Griesemer <gri@golang.org> | 2021-12-15 20:26:10 +0000 |
commit | 4cda05d41a8585c79bfe00f867ed3513672e69fa (patch) | |
tree | c59da2f30e3bdcbe46f65273bed30441f2b33333 /src/cmd/compile | |
parent | bc0aba971705722b6798746b2003908166ee007b (diff) | |
download | go-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.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/predicates.go | 7 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/sizeof_test.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/subst.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/typeset.go | 28 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/union.go | 7 |
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 } |