diff options
Diffstat (limited to 'src/cmd/compile/internal/types2/instantiate.go')
-rw-r--r-- | src/cmd/compile/internal/types2/instantiate.go | 62 |
1 files changed, 24 insertions, 38 deletions
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go index c882699d1d5..7a9279943c1 100644 --- a/src/cmd/compile/internal/types2/instantiate.go +++ b/src/cmd/compile/internal/types2/instantiate.go @@ -13,21 +13,6 @@ import ( "fmt" ) -// An Environment is an opaque type checking environment. It may be used to -// share identical type instances across type checked packages or calls to -// Instantiate. -type Environment struct { - // For now, Environment just hides a Checker. - // Eventually, we strive to remove the need for a checker. - check *Checker -} - -// NewEnvironment returns a new Environment, initialized with the given -// Checker, or nil. -func NewEnvironment(check *Checker) *Environment { - return &Environment{check} -} - // Instantiate instantiates the type typ with the given type arguments targs. // typ must be a *Named or a *Signature type, and its number of type parameters // must match the number of provided type arguments. The result is a new, @@ -46,22 +31,18 @@ func NewEnvironment(check *Checker) *Environment { // TODO(rfindley): change this function to also return an error if lengths of // tparams and targs do not match. func Instantiate(env *Environment, typ Type, targs []Type, validate bool) (Type, error) { - var check *Checker - if env != nil { - check = env.check - } - inst := check.instance(nopos, typ, targs) + inst := (*Checker)(nil).instance(nopos, typ, targs, env) var err error if validate { var tparams []*TypeParam switch t := typ.(type) { case *Named: - tparams = t.TParams().list() + tparams = t.TypeParams().list() case *Signature: - tparams = t.TParams().list() + tparams = t.TypeParams().list() } - if i, err := check.verify(nopos, tparams, targs); err != nil { + if i, err := (*Checker)(nil).verify(nopos, tparams, targs); err != nil { return inst, ArgumentError{i, err} } } @@ -90,7 +71,7 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis }() } - inst := check.instance(pos, typ, targs) + inst := check.instance(pos, typ, targs, check.conf.Environment) assert(len(posList) <= len(targs)) check.later(func() { @@ -99,9 +80,9 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis var tparams []*TypeParam switch t := typ.(type) { case *Named: - tparams = t.TParams().list() + tparams = t.TypeParams().list() case *Signature: - tparams = t.TParams().list() + tparams = t.TypeParams().list() } // Avoid duplicate errors; instantiate will have complained if tparams // and targs do not have the same length. @@ -122,35 +103,40 @@ func (check *Checker) instantiate(pos syntax.Pos, typ Type, targs []Type, posLis // instance creates a type or function instance using the given original type // typ and arguments targs. For Named types the resulting instance will be // unexpanded. -func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type { +func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type, env *Environment) Type { switch t := typ.(type) { case *Named: - h := typeHash(t, targs) - if check != nil { - // typ may already have been instantiated with identical type arguments. - // In that case, re-use the existing instance. - if named := check.typMap[h]; named != nil { + var h string + if env != nil { + h = env.TypeHash(t, targs) + // typ may already have been instantiated with identical type arguments. In + // that case, re-use the existing instance. + if named := env.typeForHash(h, nil); named != nil { return named } } tname := NewTypeName(pos, t.obj.pkg, t.obj.name, nil) - named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is loaded + named := check.newNamed(tname, t, nil, nil, nil) // methods and tparams are set when named is resolved named.targs = NewTypeList(targs) - named.instPos = &pos - if check != nil { - check.typMap[h] = named + named.resolver = func(env *Environment, n *Named) (*TypeParamList, Type, []*Func) { + return expandNamed(env, n, pos) + } + if env != nil { + // It's possible that we've lost a race to add named to the environment. + // In this case, use whichever instance is recorded in the environment. + named = env.typeForHash(h, named) } return named case *Signature: - tparams := t.TParams() + tparams := t.TypeParams() if !check.validateTArgLen(pos, tparams.Len(), len(targs)) { return Typ[Invalid] } if tparams.Len() == 0 { return typ // nothing to do (minor optimization) } - sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil).(*Signature) + sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), env).(*Signature) // If the signature doesn't use its type parameters, subst // will not make a copy. In that case, make a copy now (so // we can set tparams to nil w/o causing side-effects). |