aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/types2/instantiate.go
diff options
context:
space:
mode:
Diffstat (limited to 'src/cmd/compile/internal/types2/instantiate.go')
-rw-r--r--src/cmd/compile/internal/types2/instantiate.go62
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).