diff options
-rw-r--r-- | src/cmd/compile/internal/importer/iimport.go | 8 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/expr.go | 8 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/types.go | 20 | ||||
-rw-r--r-- | src/cmd/compile/internal/noder/writer.go | 16 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/infer.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/instantiate.go | 12 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/lookup.go | 4 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/named.go | 14 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/predicates.go | 4 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/sizeof_test.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/subst.go | 8 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/typelists.go | 69 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/typeparam.go | 34 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/typestring.go | 2 | ||||
-rw-r--r-- | src/cmd/compile/internal/types2/unify.go | 10 |
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 } } |