aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cmd/compile/internal/importer/iimport.go8
-rw-r--r--src/cmd/compile/internal/noder/expr.go8
-rw-r--r--src/cmd/compile/internal/noder/types.go20
-rw-r--r--src/cmd/compile/internal/noder/writer.go16
-rw-r--r--src/cmd/compile/internal/types2/infer.go2
-rw-r--r--src/cmd/compile/internal/types2/instantiate.go12
-rw-r--r--src/cmd/compile/internal/types2/lookup.go4
-rw-r--r--src/cmd/compile/internal/types2/named.go14
-rw-r--r--src/cmd/compile/internal/types2/predicates.go4
-rw-r--r--src/cmd/compile/internal/types2/sizeof_test.go2
-rw-r--r--src/cmd/compile/internal/types2/subst.go8
-rw-r--r--src/cmd/compile/internal/types2/typelists.go69
-rw-r--r--src/cmd/compile/internal/types2/typeparam.go34
-rw-r--r--src/cmd/compile/internal/types2/typestring.go2
-rw-r--r--src/cmd/compile/internal/types2/unify.go10
15 files changed, 128 insertions, 85 deletions
diff --git a/src/cmd/compile/internal/importer/iimport.go b/src/cmd/compile/internal/importer/iimport.go
index a46971d0a7..c303126ea6 100644
--- a/src/cmd/compile/internal/importer/iimport.go
+++ b/src/cmd/compile/internal/importer/iimport.go
@@ -346,10 +346,10 @@ func (r *importReader) obj(name string) {
// rparams of the method (since those are the
// typeparams being used in the method sig/body).
targs := baseType(msig.Recv().Type()).TArgs()
- if len(targs) > 0 {
- rparams := make([]*types2.TypeParam, len(targs))
- for i, targ := range targs {
- rparams[i] = types2.AsTypeParam(targ)
+ if targs.Len() > 0 {
+ rparams := make([]*types2.TypeParam, targs.Len())
+ for i := range rparams {
+ rparams[i] = types2.AsTypeParam(targs.At(i))
}
msig.SetRParams(rparams)
}
diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go
index 3e3c352a32..cb20d645aa 100644
--- a/src/cmd/compile/internal/noder/expr.go
+++ b/src/cmd/compile/internal/noder/expr.go
@@ -360,9 +360,9 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
// selinfo.Targs() are the types used to
// instantiate the type of receiver
targs2 := getTargs(selinfo)
- targs := make([]ir.Node, len(targs2))
- for i, targ2 := range targs2 {
- targs[i] = ir.TypeNode(g.typ(targ2))
+ targs := make([]ir.Node, targs2.Len())
+ for i := range targs {
+ targs[i] = ir.TypeNode(g.typ(targs2.At(i)))
}
// Create function instantiation with the type
@@ -386,7 +386,7 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
}
// getTargs gets the targs associated with the receiver of a selected method
-func getTargs(selinfo *types2.Selection) []types2.Type {
+func getTargs(selinfo *types2.Selection) *types2.TypeList {
r := deref2(selinfo.Recv())
n := types2.AsNamed(r)
if n == nil {
diff --git a/src/cmd/compile/internal/noder/types.go b/src/cmd/compile/internal/noder/types.go
index dd1fdcf96b..541ed68ef3 100644
--- a/src/cmd/compile/internal/noder/types.go
+++ b/src/cmd/compile/internal/noder/types.go
@@ -66,10 +66,12 @@ func (g *irgen) typ1(typ types2.Type) *types.Type {
// instTypeName2 creates a name for an instantiated type, base on the type args
// (given as types2 types).
-func instTypeName2(name string, targs []types2.Type) string {
+func instTypeName2(name string, targs *types2.TypeList) string {
b := bytes.NewBufferString(name)
b.WriteByte('[')
- for i, targ := range targs {
+ n := targs.Len()
+ for i := 0; i < n; i++ {
+ targ := targs.At(i)
if i > 0 {
b.WriteByte(',')
}
@@ -140,9 +142,10 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
// non-generic types used to instantiate this type. We'll
// use these when instantiating the methods of the
// instantiated type.
- rparams := make([]*types.Type, len(typ.TArgs()))
- for i, targ := range typ.TArgs() {
- rparams[i] = g.typ1(targ)
+ targs := typ.TArgs()
+ rparams := make([]*types.Type, targs.Len())
+ for i := range rparams {
+ rparams[i] = g.typ1(targs.At(i))
}
ntyp.SetRParams(rparams)
//fmt.Printf("Saw new type %v %v\n", instName, ntyp.HasTParam())
@@ -267,9 +270,10 @@ func (g *irgen) typ0(typ types2.Type) *types.Type {
// and for actually generating the methods for instantiated types.
func (g *irgen) fillinMethods(typ *types2.Named, ntyp *types.Type) {
if typ.NumMethods() != 0 {
- targs := make([]*types.Type, len(typ.TArgs()))
- for i, targ := range typ.TArgs() {
- targs[i] = g.typ1(targ)
+ targs2 := typ.TArgs()
+ targs := make([]*types.Type, targs2.Len())
+ for i := range targs {
+ targs[i] = g.typ1(targs2.At(i))
}
methods := make([]*types.Field, typ.NumMethods())
diff --git a/src/cmd/compile/internal/noder/writer.go b/src/cmd/compile/internal/noder/writer.go
index 02df9a43de..a6bd8b2426 100644
--- a/src/cmd/compile/internal/noder/writer.go
+++ b/src/cmd/compile/internal/noder/writer.go
@@ -299,7 +299,7 @@ func (pw *pkgWriter) typIdx(typ types2.Type, dict *writerDict) typeInfo {
// Type aliases can refer to uninstantiated generic types, so we
// might see len(TParams) != 0 && len(TArgs) == 0 here.
// TODO(mdempsky): Revisit after #46477 is resolved.
- assert(typ.TParams().Len() == len(typ.TArgs()) || len(typ.TArgs()) == 0)
+ assert(typ.TParams().Len() == typ.TArgs().Len() || typ.TArgs().Len() == 0)
// TODO(mdempsky): Why do we need to loop here?
orig := typ
@@ -441,10 +441,10 @@ func (w *writer) param(param *types2.Var) {
// @@@ Objects
-func (w *writer) obj(obj types2.Object, explicits []types2.Type) {
- explicitInfos := make([]typeInfo, len(explicits))
- for i, explicit := range explicits {
- explicitInfos[i] = w.p.typIdx(explicit, w.dict)
+func (w *writer) obj(obj types2.Object, explicits *types2.TypeList) {
+ explicitInfos := make([]typeInfo, explicits.Len())
+ for i := range explicitInfos {
+ explicitInfos[i] = w.p.typIdx(explicits.At(i), w.dict)
}
info := objInfo{idx: w.p.objIdx(obj), explicits: explicitInfos}
@@ -1212,7 +1212,7 @@ func (w *writer) expr(expr syntax.Expr) {
if obj != nil {
if isGlobal(obj) {
w.code(exprName)
- w.obj(obj, targs)
+ w.obj(obj, types2.NewTypeList(targs))
return
}
@@ -1321,7 +1321,7 @@ func (w *writer) expr(expr syntax.Expr) {
// As if w.expr(expr.Fun), but using inf.TArgs instead.
w.code(exprName)
- w.obj(obj, inf.TArgs)
+ w.obj(obj, types2.NewTypeList(inf.TArgs))
} else {
w.expr(expr.Fun)
}
@@ -1711,7 +1711,7 @@ func (w *writer) pkgDecl(decl syntax.Decl) {
// TODO(mdempsky): Revisit after #46477 is resolved.
if name.IsAlias() {
named, ok := name.Type().(*types2.Named)
- if ok && named.TParams().Len() != 0 && len(named.TArgs()) == 0 {
+ if ok && named.TParams().Len() != 0 && named.TArgs().Len() == 0 {
break
}
}
diff --git a/src/cmd/compile/internal/types2/infer.go b/src/cmd/compile/internal/types2/infer.go
index 6e4fe502b6..5badecc070 100644
--- a/src/cmd/compile/internal/types2/infer.go
+++ b/src/cmd/compile/internal/types2/infer.go
@@ -335,7 +335,7 @@ func (w *tpWalker) isParameterized(typ Type) (res bool) {
return w.isParameterized(t.elem)
case *Named:
- return w.isParameterizedTypeList(t.targs)
+ return w.isParameterizedTypeList(t.targs.list())
case *TypeParam:
// t must be one of w.tparams
diff --git a/src/cmd/compile/internal/types2/instantiate.go b/src/cmd/compile/internal/types2/instantiate.go
index 06cbcda58e..8bea63ec86 100644
--- a/src/cmd/compile/internal/types2/instantiate.go
+++ b/src/cmd/compile/internal/types2/instantiate.go
@@ -137,7 +137,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type
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 = targs
+ named.targs = NewTypeList(targs)
named.instance = &instance{pos}
if check != nil {
check.typMap[h] = named
@@ -145,7 +145,7 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type
res = named
case *Signature:
tparams := t.TParams()
- if !check.validateTArgLen(pos, tparams, targs) {
+ if !check.validateTArgLen(pos, tparams.Len(), len(targs)) {
return Typ[Invalid]
}
if tparams.Len() == 0 {
@@ -180,14 +180,14 @@ func (check *Checker) instance(pos syntax.Pos, typ Type, targs []Type) (res Type
// validateTArgLen verifies that the length of targs and tparams matches,
// reporting an error if not. If validation fails and check is nil,
// validateTArgLen panics.
-func (check *Checker) validateTArgLen(pos syntax.Pos, tparams *TParamList, targs []Type) bool {
- if len(targs) != tparams.Len() {
+func (check *Checker) validateTArgLen(pos syntax.Pos, ntparams, ntargs int) bool {
+ if ntargs != ntparams {
// TODO(gri) provide better error message
if check != nil {
- check.errorf(pos, "got %d arguments but %d type parameters", len(targs), tparams.Len())
+ check.errorf(pos, "got %d arguments but %d type parameters", ntargs, ntparams)
return false
}
- panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, len(targs), tparams.Len()))
+ panic(fmt.Sprintf("%v: got %d arguments but %d type parameters", pos, ntargs, ntparams))
}
return true
}
diff --git a/src/cmd/compile/internal/types2/lookup.go b/src/cmd/compile/internal/types2/lookup.go
index 668c5ff3ec..d0718e51e2 100644
--- a/src/cmd/compile/internal/types2/lookup.go
+++ b/src/cmd/compile/internal/types2/lookup.go
@@ -394,10 +394,10 @@ func (check *Checker) missingMethod(V Type, T *Interface, static bool) (method,
// here. Exit early in this case to prevent an assertion
// failure in makeSubstMap.
// TODO(gri) Can we avoid this check by fixing the lengths?
- if len(ftyp.RParams().list()) != len(Vn.targs) {
+ if len(ftyp.RParams().list()) != Vn.targs.Len() {
return
}
- ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs), nil).(*Signature)
+ ftyp = check.subst(nopos, ftyp, makeSubstMap(ftyp.RParams().list(), Vn.targs.list()), nil).(*Signature)
}
// If the methods have type parameters we don't care whether they
diff --git a/src/cmd/compile/internal/types2/named.go b/src/cmd/compile/internal/types2/named.go
index db12b08e67..a3a2595a22 100644
--- a/src/cmd/compile/internal/types2/named.go
+++ b/src/cmd/compile/internal/types2/named.go
@@ -21,7 +21,7 @@ type Named struct {
underlying Type // possibly a *Named during setup; never a *Named once set up completely
instance *instance // position information for lazy instantiation, or nil
tparams *TParamList // type parameters, or nil
- targs []Type // type arguments (after instantiation), or nil
+ targs *TypeList // type arguments (after instantiation), or nil
methods []*Func // methods declared for this type (not the method set of this type); signatures are type-checked lazily
resolve func(*Named) ([]*TypeParam, Type, []*Func)
@@ -46,7 +46,7 @@ func (t *Named) load() *Named {
// underlying is set when t is expanded.
//
// By convention, a type instance is loaded iff its tparams are set.
- if len(t.targs) > 0 && t.tparams == nil {
+ if t.targs.Len() > 0 && t.tparams == nil {
t.orig.load()
t.tparams = t.orig.tparams
t.methods = t.orig.methods
@@ -128,8 +128,8 @@ func (t *Named) TParams() *TParamList { return t.load().tparams }
// SetTParams sets the type parameters of the named type t.
func (t *Named) SetTParams(tparams []*TypeParam) { t.load().tparams = bindTParams(tparams) }
-// TArgs returns the type arguments after instantiation of the named type t, or nil if not instantiated.
-func (t *Named) TArgs() []Type { return t.targs }
+// TArgs returns the type arguments used to instantiate the named type t.
+func (t *Named) TArgs() *TypeList { return t.targs }
// NumMethods returns the number of explicit methods whose receiver is named type t.
func (t *Named) NumMethods() int { return len(t.load().methods) }
@@ -259,7 +259,7 @@ func (n *Named) expand(typMap map[string]*Named) *Named {
// explicit is harmless: load is idempotent.
n.load()
var u Type
- if n.check.validateTArgLen(n.instance.pos, n.tparams, n.targs) {
+ if n.check.validateTArgLen(n.instance.pos, n.tparams.Len(), n.targs.Len()) {
if typMap == nil {
if n.check != nil {
typMap = n.check.typMap
@@ -268,11 +268,11 @@ func (n *Named) expand(typMap map[string]*Named) *Named {
// type-checking pass. In that case we won't have a pre-existing
// typMap, but don't want to create a duplicate of the current instance
// in the process of expansion.
- h := instantiatedHash(n.orig, n.targs)
+ h := instantiatedHash(n.orig, n.targs.list())
typMap = map[string]*Named{h: n}
}
}
- u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs), typMap)
+ u = n.check.subst(n.instance.pos, n.orig.underlying, makeSubstMap(n.TParams().list(), n.targs.list()), typMap)
} else {
u = Typ[Invalid]
}
diff --git a/src/cmd/compile/internal/types2/predicates.go b/src/cmd/compile/internal/types2/predicates.go
index ed62743f6d..3ccafef990 100644
--- a/src/cmd/compile/internal/types2/predicates.go
+++ b/src/cmd/compile/internal/types2/predicates.go
@@ -305,8 +305,8 @@ func identical(x, y Type, cmpTags bool, p *ifacePair) bool {
x.expand(nil)
y.expand(nil)
- xargs := x.TArgs()
- yargs := y.TArgs()
+ xargs := x.TArgs().list()
+ yargs := y.TArgs().list()
if len(xargs) != len(yargs) {
return false
diff --git a/src/cmd/compile/internal/types2/sizeof_test.go b/src/cmd/compile/internal/types2/sizeof_test.go
index 718d2d266a..5be369d843 100644
--- a/src/cmd/compile/internal/types2/sizeof_test.go
+++ b/src/cmd/compile/internal/types2/sizeof_test.go
@@ -31,7 +31,7 @@ func TestSizeof(t *testing.T) {
{Interface{}, 40, 80},
{Map{}, 16, 32},
{Chan{}, 12, 24},
- {Named{}, 80, 152},
+ {Named{}, 72, 136},
{TypeParam{}, 28, 48},
{term{}, 12, 24},
{top{}, 0, 0},
diff --git a/src/cmd/compile/internal/types2/subst.go b/src/cmd/compile/internal/types2/subst.go
index 467066cc69..918e5f3043 100644
--- a/src/cmd/compile/internal/types2/subst.go
+++ b/src/cmd/compile/internal/types2/subst.go
@@ -188,21 +188,21 @@ func (subst *subster) typ(typ Type) Type {
}
var newTArgs []Type
- assert(len(t.targs) == t.TParams().Len())
+ assert(t.targs.Len() == t.TParams().Len())
// already instantiated
dump(">>> %s already instantiated", t)
// For each (existing) type argument targ, determine if it needs
// to be substituted; i.e., if it is or contains a type parameter
// that has a type argument for it.
- for i, targ := range t.targs {
+ for i, targ := range t.targs.list() {
dump(">>> %d targ = %s", i, targ)
new_targ := subst.typ(targ)
if new_targ != targ {
dump(">>> substituted %d targ %s => %s", i, targ, new_targ)
if newTArgs == nil {
newTArgs = make([]Type, t.TParams().Len())
- copy(newTArgs, t.targs)
+ copy(newTArgs, t.targs.list())
}
newTArgs[i] = new_targ
}
@@ -230,7 +230,7 @@ func (subst *subster) typ(typ Type) Type {
// It's ok to provide a nil *Checker because the newly created type
// doesn't need to be (lazily) expanded; it's expanded below.
named := (*Checker)(nil).newNamed(tname, t.orig, nil, t.tparams, t.methods) // t is loaded, so tparams and methods are available
- named.targs = newTArgs
+ named.targs = NewTypeList(newTArgs)
subst.typMap[h] = named
t.expand(subst.typMap) // must happen after typMap update to avoid infinite recursion
diff --git a/src/cmd/compile/internal/types2/typelists.go b/src/cmd/compile/internal/types2/typelists.go
new file mode 100644
index 0000000000..3258a5e9f8
--- /dev/null
+++ b/src/cmd/compile/internal/types2/typelists.go
@@ -0,0 +1,69 @@
+// Copyright 2021 The Go Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style
+// license that can be found in the LICENSE file.
+
+package types2
+
+// TParamList holds a list of type parameters.
+type TParamList struct{ tparams []*TypeParam }
+
+// Len returns the number of type parameters in the list.
+// It is safe to call on a nil receiver.
+func (l *TParamList) Len() int { return len(l.list()) }
+
+// At returns the i'th type parameter in the list.
+func (l *TParamList) At(i int) *TypeParam { return l.tparams[i] }
+
+// list is for internal use where we expect a []*TypeParam.
+// TODO(rfindley): list should probably be eliminated: we can pass around a
+// TParamList instead.
+func (l *TParamList) list() []*TypeParam {
+ if l == nil {
+ return nil
+ }
+ return l.tparams
+}
+
+// TypeList holds a list of types.
+type TypeList struct{ types []Type }
+
+// NewTypeList returns a new TypeList with the types in list.
+func NewTypeList(list []Type) *TypeList {
+ if len(list) == 0 {
+ return nil
+ }
+ return &TypeList{list}
+}
+
+// Len returns the number of types in the list.
+// It is safe to call on a nil receiver.
+func (l *TypeList) Len() int { return len(l.list()) }
+
+// At returns the i'th type in the list.
+func (l *TypeList) At(i int) Type { return l.types[i] }
+
+// list is for internal use where we expect a []Type.
+// TODO(rfindley): list should probably be eliminated: we can pass around a
+// TypeList instead.
+func (l *TypeList) list() []Type {
+ if l == nil {
+ return nil
+ }
+ return l.types
+}
+
+// ----------------------------------------------------------------------------
+// Implementation
+
+func bindTParams(list []*TypeParam) *TParamList {
+ if len(list) == 0 {
+ return nil
+ }
+ for i, typ := range list {
+ if typ.index >= 0 {
+ panic("type parameter bound more than once")
+ }
+ typ.index = i
+ }
+ return &TParamList{tparams: list}
+}
diff --git a/src/cmd/compile/internal/types2/typeparam.go b/src/cmd/compile/internal/types2/typeparam.go
index 0d76dd1a6e..445337fee8 100644
--- a/src/cmd/compile/internal/types2/typeparam.go
+++ b/src/cmd/compile/internal/types2/typeparam.go
@@ -83,40 +83,6 @@ func (t *TypeParam) SetConstraint(bound Type) {
func (t *TypeParam) Underlying() Type { return t }
func (t *TypeParam) String() string { return TypeString(t, nil) }
-// TParamList holds a list of type parameters bound to a type.
-type TParamList struct{ tparams []*TypeParam }
-
-// Len returns the number of type parameters in the list.
-// It is safe to call on a nil receiver.
-func (tps *TParamList) Len() int {
- return len(tps.list())
-}
-
-// At returns the i'th type parameter in the list.
-func (tps *TParamList) At(i int) *TypeParam {
- return tps.list()[i]
-}
-
-func (tps *TParamList) list() []*TypeParam {
- if tps == nil {
- return nil
- }
- return tps.tparams
-}
-
-func bindTParams(list []*TypeParam) *TParamList {
- if len(list) == 0 {
- return nil
- }
- for i, typ := range list {
- if typ.index >= 0 {
- panic("type parameter bound more than once")
- }
- typ.index = i
- }
- return &TParamList{tparams: list}
-}
-
// ----------------------------------------------------------------------------
// Implementation
diff --git a/src/cmd/compile/internal/types2/typestring.go b/src/cmd/compile/internal/types2/typestring.go
index 5759118c94..2c34d036db 100644
--- a/src/cmd/compile/internal/types2/typestring.go
+++ b/src/cmd/compile/internal/types2/typestring.go
@@ -202,7 +202,7 @@ func writeType(buf *bytes.Buffer, typ Type, qf Qualifier, visited []Type) {
if t.targs != nil {
// instantiated type
buf.WriteByte('[')
- writeTypeList(buf, t.targs, qf, visited)
+ writeTypeList(buf, t.targs.list(), qf, visited)
buf.WriteByte(']')
} else if t.TParams().Len() != 0 {
// parameterized type
diff --git a/src/cmd/compile/internal/types2/unify.go b/src/cmd/compile/internal/types2/unify.go
index 58f5c17e5f..d4fbebc11b 100644
--- a/src/cmd/compile/internal/types2/unify.go
+++ b/src/cmd/compile/internal/types2/unify.go
@@ -429,13 +429,17 @@ func (u *unifier) nify(x, y Type, p *ifacePair) bool {
if y, ok := y.(*Named); ok {
x.expand(nil)
y.expand(nil)
+
+ xargs := x.targs.list()
+ yargs := y.targs.list()
+
// TODO(gri) This is not always correct: two types may have the same names
// in the same package if one of them is nested in a function.
// Extremely unlikely but we need an always correct solution.
if x.obj.pkg == y.obj.pkg && x.obj.name == y.obj.name {
- assert(len(x.targs) == len(y.targs))
- for i, x := range x.targs {
- if !u.nify(x, y.targs[i], p) {
+ assert(len(xargs) == len(yargs))
+ for i, x := range xargs {
+ if !u.nify(x, yargs[i], p) {
return false
}
}