go/types: remove targs from substMap

This is a straightforward port of CL 341859 to go/types.

Change-Id: I5d2508f516b5cf4d8775c3a77cc8bed5d4bec338
Reviewed-on: https://go-review.googlesource.com/c/go/+/342480
Trust: Robert Findley <rfindley@google.com>
Run-TryBot: Robert Findley <rfindley@google.com>
Reviewed-by: Robert Griesemer <gri@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
This commit is contained in:
Robert Findley 2021-08-16 13:36:27 -04:00
parent d1ba047edf
commit 631af58e20
2 changed files with 34 additions and 52 deletions

View file

@ -153,7 +153,7 @@ func (check *Checker) verify(pos token.Pos, tparams []*TypeName, targs []Type, p
// parameter tpar (after any of its type parameters have been substituted through smap). // parameter tpar (after any of its type parameters have been substituted through smap).
// A suitable error is reported if the result is false. // A suitable error is reported if the result is false.
// TODO(gri) This should be a method of interfaces or type sets. // TODO(gri) This should be a method of interfaces or type sets.
func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap *substMap) bool { func (check *Checker) satisfies(pos token.Pos, targ Type, tpar *TypeParam, smap substMap) bool {
iface := tpar.iface() iface := tpar.iface()
if iface.Empty() { if iface.Empty() {
return true // no type bound return true // no type bound

View file

@ -8,42 +8,31 @@ package types
import ( import (
"bytes" "bytes"
"fmt"
"go/token" "go/token"
) )
// TODO(rFindley) decide error codes for the errors in this file, and check // TODO(rFindley) decide error codes for the errors in this file, and check
// if error spans can be improved // if error spans can be improved
type substMap struct { type substMap map[*TypeParam]Type
// The targs field is currently needed for *Named type substitution.
// TODO(gri) rewrite that code, get rid of this field, and make this
// struct just the map (proj)
targs []Type
proj map[*TypeParam]Type
}
// makeSubstMap creates a new substitution map mapping tpars[i] to targs[i]. // makeSubstMap creates a new substitution map mapping tpars[i] to targs[i].
// If targs[i] is nil, tpars[i] is not substituted. // If targs[i] is nil, tpars[i] is not substituted.
func makeSubstMap(tpars []*TypeName, targs []Type) *substMap { func makeSubstMap(tpars []*TypeName, targs []Type) substMap {
assert(len(tpars) == len(targs)) assert(len(tpars) == len(targs))
proj := make(map[*TypeParam]Type, len(tpars)) proj := make(substMap, len(tpars))
for i, tpar := range tpars { for i, tpar := range tpars {
proj[tpar.typ.(*TypeParam)] = targs[i] proj[tpar.typ.(*TypeParam)] = targs[i]
} }
return &substMap{targs, proj} return proj
} }
func (m *substMap) String() string { func (m substMap) empty() bool {
return fmt.Sprintf("%s", m.proj) return len(m) == 0
} }
func (m *substMap) empty() bool { func (m substMap) lookup(tpar *TypeParam) Type {
return len(m.proj) == 0 if t := m[tpar]; t != nil {
}
func (m *substMap) lookup(tpar *TypeParam) Type {
if t := m.proj[tpar]; t != nil {
return t return t
} }
return tpar return tpar
@ -56,7 +45,7 @@ func (m *substMap) lookup(tpar *TypeParam) Type {
// from the incoming type. // from the incoming type.
// //
// If the given typMap is nil and check is non-nil, check.typMap is used. // If the given typMap is nil and check is non-nil, check.typMap is used.
func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap, typMap map[string]*Named) Type { func (check *Checker) subst(pos token.Pos, typ Type, smap substMap, typMap map[string]*Named) Type {
if smap.empty() { if smap.empty() {
return typ return typ
} }
@ -94,7 +83,7 @@ func (check *Checker) subst(pos token.Pos, typ Type, smap *substMap, typMap map[
type subster struct { type subster struct {
pos token.Pos pos token.Pos
smap *substMap smap substMap
check *Checker // nil if called via Instantiate check *Checker // nil if called via Instantiate
typMap map[string]*Named typMap map[string]*Named
} }
@ -205,41 +194,34 @@ func (subst *subster) typ(typ Type) Type {
return t // type is not parameterized return t // type is not parameterized
} }
var newTargs []Type var newTArgs []Type
assert(len(t.targs) == t.TParams().Len())
if len(t.targs) > 0 {
// already instantiated // already instantiated
dump(">>> %s already instantiated", t) dump(">>> %s already instantiated", t)
assert(len(t.targs) == t.TParams().Len())
// For each (existing) type argument targ, determine if it needs // For each (existing) type argument targ, determine if it needs
// to be substituted; i.e., if it is or contains a type parameter // to be substituted; i.e., if it is or contains a type parameter
// that has a type argument for it. // that has a type argument for it.
for i, targ := range t.targs { for i, targ := range t.targs {
dump(">>> %d targ = %s", i, targ) dump(">>> %d targ = %s", i, targ)
newTarg := subst.typ(targ) new_targ := subst.typ(targ)
if newTarg != targ { if new_targ != targ {
dump(">>> substituted %d targ %s => %s", i, targ, newTarg) dump(">>> substituted %d targ %s => %s", i, targ, new_targ)
if newTargs == nil { if newTArgs == nil {
newTargs = make([]Type, t.TParams().Len()) newTArgs = make([]Type, t.TParams().Len())
copy(newTargs, t.targs) copy(newTArgs, t.targs)
} }
newTargs[i] = newTarg newTArgs[i] = new_targ
} }
} }
if newTargs == nil { if newTArgs == nil {
dump(">>> nothing to substitute in %s", t) dump(">>> nothing to substitute in %s", t)
return t // nothing to substitute return t // nothing to substitute
} }
} else {
// not yet instantiated
dump(">>> first instantiation of %s", t)
// TODO(rFindley) can we instead subst the tparam types here?
newTargs = subst.smap.targs
}
// before creating a new named type, check if we have this one already // before creating a new named type, check if we have this one already
h := instantiatedHash(t, newTargs) h := instantiatedHash(t, newTArgs)
dump(">>> new type hash: %s", h) dump(">>> new type hash: %s", h)
if named, found := subst.typMap[h]; found { if named, found := subst.typMap[h]; found {
dump(">>> found %s", named) dump(">>> found %s", named)
@ -250,12 +232,12 @@ func (subst *subster) typ(typ Type) Type {
tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil) tname := NewTypeName(subst.pos, t.obj.pkg, t.obj.name, nil)
t.load() t.load()
named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily named := subst.check.newNamed(tname, t.orig, t.underlying, t.TParams(), t.methods) // method signatures are updated lazily
named.targs = newTargs named.targs = newTArgs
subst.typMap[h] = named subst.typMap[h] = named
t.expand(subst.typMap) // 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 // do the substitution
dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTargs) dump(">>> subst %s with %s (new: %s)", t.underlying, subst.smap, newTArgs)
named.underlying = subst.typOrNil(t.underlying) named.underlying = subst.typOrNil(t.underlying)
dump(">>> underlying: %v", named.underlying) dump(">>> underlying: %v", named.underlying)
assert(named.underlying != nil) assert(named.underlying != nil)