From fc27eb50ffcada3d4f5e7e00a5c120f474cc0da4 Mon Sep 17 00:00:00 2001 From: Rob Findley Date: Tue, 10 Aug 2021 14:00:56 -0400 Subject: cmd/compile/internal/types2: merge Instantiate and InstantiateLazy Instantiate and InstantiateLazy have the same signature; on first principles, if Instantiate should work for importers it should be possible to consolidate these APIs. This CL does this. In order to make it work, a typMap needs to be threaded through type expansion to prevent infinite recursion in the case that the Checker is nil. Notably, Named types now must be expanded before returning from Underlying(). This makes Underlying generally unsafe to call while type checking a package, so a helper function safeUnderlying is added to provide the previous behavior. This is probably overly conservative at most call sites, but cleanup is deferred to a later CL. Change-Id: I03cfb75bea0750862cd6eea4e3cdc875a7daa989 Reviewed-on: https://go-review.googlesource.com/c/go/+/341855 Trust: Robert Findley Run-TryBot: Robert Findley TryBot-Result: Go Bot Reviewed-by: Robert Griesemer --- src/cmd/compile/internal/types2/subst.go | 22 +++++++++++++++------- 1 file changed, 15 insertions(+), 7 deletions(-) (limited to 'src/cmd/compile/internal/types2/subst.go') diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go index 26796fc604..044544f1f9 100644 --- a/src/cmd/compile/internal/types2/subst.go +++ b/src/cmd/compile/internal/types2/subst.go @@ -51,7 +51,9 @@ func (m *substMap) lookup(tpar *TypeParam) Type { // subst is functional in the sense that it doesn't modify the incoming // type. If a substitution took place, the result type is different from // from the incoming type. -func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap) Type { +// +// If the given typMap is nil and check is non-nil, check.typMap is used. +func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap, typMap map[string]*Named) Type { if smap.empty() { return typ } @@ -68,16 +70,21 @@ func (check *Checker) subst(pos syntax.Pos, typ Type, smap *substMap) Type { var subst subster subst.pos = pos subst.smap = smap + if check != nil { subst.check = check - subst.typMap = check.typMap - } else { + if typMap == nil { + typMap = check.typMap + } + } + if typMap == nil { // If we don't have a *Checker and its global type map, // use a local version. Besides avoiding duplicate work, // the type map prevents infinite recursive substitution // for recursive types (example: type T[P any] *T[P]). - subst.typMap = make(map[string]*Named) + typMap = make(map[string]*Named) } + subst.typMap = typMap return subst.typ(typ) } @@ -234,14 +241,15 @@ func (subst *subster) typ(typ Type) Type { // create a new named type and populate typMap to avoid endless recursion tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) - named := subst.check.newNamed(tname, t, t.Underlying(), t.TParams(), t.methods) // method signatures are updated lazily + t.load() + named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily named.targs = new_targs subst.typMap[h] = named - t.expand() // must happen after typMap update to avoid infinite recursion + t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion // do the substitution dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, new_targs) - named.underlying = subst.typOrNil(t.Underlying()) + named.underlying = subst.typOrNil(t.underlying) dump(">>> underlying: %v", named.underlying) assert(named.underlying != nil) named.fromRHS = named.underlying // for cycle detection (Checker.validType) -- cgit v1.2.3-54-g00ecf