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.go51
1 files changed, 21 insertions, 30 deletions
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index 8bea63ec86..f9cde24dfc 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -122,27 +122,26 @@ 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) (res Type) {
- // TODO(gri) What is better here: work with TypeParams, or work with TypeNames?
+func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) Type {
switch t := typ.(type) {
case *Named:
h := instantiatedHash(t, targs)
if check != nil {
- // typ may already have been instantiated with identical type arguments. In
- // that case, re-use the existing instance.
+ // 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 {
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.targs = NewTypeList(targs)
- named.instance = &instance{pos}
+ named.instPos = &pos
if check != nil {
check.typMap[h] = named
}
- res = named
+ return named
+
case *Signature:
tparams := t.TParams()
if !check.validateTArgLen(pos, tparams.Len(), len(targs)) {
@@ -151,30 +150,22 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type
if tparams.Len() == 0 {
return typ // nothing to do (minor optimization)
}
- defer func() {
- // If we had an unexpected failure somewhere don't panic below when
- // asserting res.(*Signature). Check for *Signature in case Typ[Invalid]
- // is returned.
- if _, ok := res.(*Signature); !ok {
- return
- }
- // 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).
- if t == res {
- copy := *t
- res = &copy
- }
- // After instantiating a generic signature, it is not generic
- // anymore; we need to set tparams to nil.
- res.(*Signature).tparams = nil
- }()
- res = check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil)
- default:
- // only types and functions can be generic
- panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
+ sig := check.subst(pos, typ, makeSubstMap(tparams.list(), targs), nil).(*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).
+ if sig == t {
+ copy := *sig
+ sig = &copy
+ }
+ // After instantiating a generic signature, it is not generic
+ // anymore; we need to set tparams to nil.
+ sig.tparams = nil
+ return sig
}
- return res
+
+ // only types and functions can be generic
+ panic(fmt.Sprintf("%v: cannot instantiate %v", pos, typ))
}
// validateTArgLen verifies that the length of targs and tparams matches,