mirror of
https://github.com/golang/go
synced 2024-11-22 20:24:47 -07:00
[dev.typeparams] cmd/compile: simplify targ's type
Make the base type of targ a *types.Type instead of an ir.Node containing a type. Also move makeInstName to typecheck, so it can later be used by reflectdata for making wrappers. Change-Id: If148beaa972e5112ead2771d6e32d73f16ca30c1 Reviewed-on: https://go-review.googlesource.com/c/go/+/321209 Trust: Keith Randall <khr@golang.org> Trust: Dan Scales <danscales@google.com> Run-TryBot: Keith Randall <khr@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Dan Scales <danscales@google.com>
This commit is contained in:
parent
c2966ae272
commit
701bd60646
@ -166,12 +166,8 @@ func (g *irgen) instantiateMethods() {
|
||||
baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym()))
|
||||
baseType := baseSym.Def.(*ir.Name).Type()
|
||||
for j, m := range typ.Methods().Slice() {
|
||||
targs := make([]ir.Node, len(typ.RParams()))
|
||||
for k, targ := range typ.RParams() {
|
||||
targs[k] = ir.TypeNode(targ)
|
||||
}
|
||||
baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
|
||||
f := g.getInstantiation(baseNname, targs, true)
|
||||
f := g.getInstantiation(baseNname, typ.RParams(), true)
|
||||
m.Nname = f.Nname
|
||||
}
|
||||
}
|
||||
@ -190,17 +186,17 @@ func genericTypeName(sym *types.Sym) string {
|
||||
// InstExpr node inst.
|
||||
func (g *irgen) getInstantiationForNode(inst *ir.InstExpr) *ir.Func {
|
||||
if meth, ok := inst.X.(*ir.SelectorExpr); ok {
|
||||
return g.getInstantiation(meth.Selection.Nname.(*ir.Name), inst.Targs, true)
|
||||
return g.getInstantiation(meth.Selection.Nname.(*ir.Name), typecheck.TypesOf(inst.Targs), true)
|
||||
} else {
|
||||
return g.getInstantiation(inst.X.(*ir.Name), inst.Targs, false)
|
||||
return g.getInstantiation(inst.X.(*ir.Name), typecheck.TypesOf(inst.Targs), false)
|
||||
}
|
||||
}
|
||||
|
||||
// getInstantiation gets the instantiantion of the function or method nameNode
|
||||
// with the type arguments targs. If the instantiated function is not already
|
||||
// cached, then it calls genericSubst to create the new instantiation.
|
||||
func (g *irgen) getInstantiation(nameNode *ir.Name, targs []ir.Node, isMeth bool) *ir.Func {
|
||||
sym := makeInstName(nameNode.Sym(), targs, isMeth)
|
||||
func (g *irgen) getInstantiation(nameNode *ir.Name, targs []*types.Type, isMeth bool) *ir.Func {
|
||||
sym := typecheck.MakeInstName(nameNode.Sym(), targs, isMeth)
|
||||
st := g.target.Stencils[sym]
|
||||
if st == nil {
|
||||
// If instantiation doesn't exist yet, create it and add
|
||||
@ -215,45 +211,6 @@ func (g *irgen) getInstantiation(nameNode *ir.Name, targs []ir.Node, isMeth bool
|
||||
return st
|
||||
}
|
||||
|
||||
// makeInstName makes the unique name for a stenciled generic function or method,
|
||||
// based on the name of the function fy=nsym and the targs. It replaces any
|
||||
// existing bracket type list in the name. makeInstName asserts that fnsym has
|
||||
// brackets in its name if and only if hasBrackets is true.
|
||||
// TODO(danscales): remove the assertions and the hasBrackets argument later.
|
||||
//
|
||||
// Names of declared generic functions have no brackets originally, so hasBrackets
|
||||
// should be false. Names of generic methods already have brackets, since the new
|
||||
// type parameter is specified in the generic type of the receiver (e.g. func
|
||||
// (func (v *value[T]).set(...) { ... } has the original name (*value[T]).set.
|
||||
//
|
||||
// The standard naming is something like: 'genFn[int,bool]' for functions and
|
||||
// '(*genType[int,bool]).methodName' for methods
|
||||
func makeInstName(fnsym *types.Sym, targs []ir.Node, hasBrackets bool) *types.Sym {
|
||||
b := bytes.NewBufferString("")
|
||||
name := fnsym.Name
|
||||
i := strings.Index(name, "[")
|
||||
assert(hasBrackets == (i >= 0))
|
||||
if i >= 0 {
|
||||
b.WriteString(name[0:i])
|
||||
} else {
|
||||
b.WriteString(name)
|
||||
}
|
||||
b.WriteString("[")
|
||||
for i, targ := range targs {
|
||||
if i > 0 {
|
||||
b.WriteString(",")
|
||||
}
|
||||
b.WriteString(targ.Type().String())
|
||||
}
|
||||
b.WriteString("]")
|
||||
if i >= 0 {
|
||||
i2 := strings.Index(name[i:], "]")
|
||||
assert(i2 >= 0)
|
||||
b.WriteString(name[i+i2+1:])
|
||||
}
|
||||
return typecheck.Lookup(b.String())
|
||||
}
|
||||
|
||||
// Struct containing info needed for doing the substitution as we create the
|
||||
// instantiation of a generic function with specified type arguments.
|
||||
type subster struct {
|
||||
@ -261,7 +218,7 @@ type subster struct {
|
||||
isMethod bool // If a method is being instantiated
|
||||
newf *ir.Func // Func node for the new stenciled function
|
||||
tparams []*types.Field
|
||||
targs []ir.Node
|
||||
targs []*types.Type
|
||||
// The substitution map from name nodes in the generic function to the
|
||||
// name nodes in the new stenciled function.
|
||||
vars map[*ir.Name]*ir.Name
|
||||
@ -273,7 +230,7 @@ type subster struct {
|
||||
// function type where the receiver becomes the first parameter. Otherwise the
|
||||
// instantiated method would still need to be transformed by later compiler
|
||||
// phases.
|
||||
func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []ir.Node, isMethod bool) *ir.Func {
|
||||
func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*types.Type, isMethod bool) *ir.Func {
|
||||
var tparams []*types.Field
|
||||
if isMethod {
|
||||
// Get the type params from the method receiver (after skipping
|
||||
@ -545,7 +502,7 @@ func (subst *subster) node(n ir.Node) ir.Node {
|
||||
m.(*ir.ClosureExpr).Func = newfn
|
||||
// Closure name can already have brackets, if it derives
|
||||
// from a generic method
|
||||
newsym := makeInstName(oldfn.Nname.Sym(), subst.targs, subst.isMethod)
|
||||
newsym := typecheck.MakeInstName(oldfn.Nname.Sym(), subst.targs, subst.isMethod)
|
||||
newfn.Nname = ir.NewNameAt(oldfn.Nname.Pos(), newsym)
|
||||
newfn.Nname.Func = newfn
|
||||
newfn.Nname.Defn = newfn
|
||||
@ -704,7 +661,7 @@ func (subst *subster) typ(t *types.Type) *types.Type {
|
||||
if t.Kind() == types.TTYPEPARAM {
|
||||
for i, tp := range subst.tparams {
|
||||
if tp.Type == t {
|
||||
return subst.targs[i].Type()
|
||||
return subst.targs[i]
|
||||
}
|
||||
}
|
||||
// If t is a simple typeparam T, then t has the name/symbol 'T'
|
||||
@ -872,7 +829,7 @@ func (subst *subster) typ(t *types.Type) *types.Type {
|
||||
for i, f := range t.Methods().Slice() {
|
||||
t2 := subst.typ(f.Type)
|
||||
oldsym := f.Nname.Sym()
|
||||
newsym := makeInstName(oldsym, subst.targs, true)
|
||||
newsym := typecheck.MakeInstName(oldsym, subst.targs, true)
|
||||
var nname *ir.Name
|
||||
if newsym.Def != nil {
|
||||
nname = newsym.Def.(*ir.Name)
|
||||
|
@ -240,9 +240,9 @@ 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([]ir.Node, len(typ.TArgs()))
|
||||
targs := make([]*types.Type, len(typ.TArgs()))
|
||||
for i, targ := range typ.TArgs() {
|
||||
targs[i] = ir.TypeNode(g.typ1(targ))
|
||||
targs[i] = g.typ1(targ)
|
||||
}
|
||||
|
||||
methods := make([]*types.Field, typ.NumMethods())
|
||||
|
@ -5,6 +5,7 @@
|
||||
package typecheck
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"fmt"
|
||||
"sort"
|
||||
"strconv"
|
||||
@ -874,3 +875,60 @@ var slist []symlink
|
||||
type symlink struct {
|
||||
field *types.Field
|
||||
}
|
||||
|
||||
// TypesOf converts a list of nodes to a list
|
||||
// of types of those nodes.
|
||||
func TypesOf(x []ir.Node) []*types.Type {
|
||||
r := make([]*types.Type, len(x))
|
||||
for i, n := range x {
|
||||
r[i] = n.Type()
|
||||
}
|
||||
return r
|
||||
}
|
||||
|
||||
// MakeInstName makes the unique name for a stenciled generic function or method,
|
||||
// based on the name of the function fy=nsym and the targs. It replaces any
|
||||
// existing bracket type list in the name. makeInstName asserts that fnsym has
|
||||
// brackets in its name if and only if hasBrackets is true.
|
||||
// TODO(danscales): remove the assertions and the hasBrackets argument later.
|
||||
//
|
||||
// Names of declared generic functions have no brackets originally, so hasBrackets
|
||||
// should be false. Names of generic methods already have brackets, since the new
|
||||
// type parameter is specified in the generic type of the receiver (e.g. func
|
||||
// (func (v *value[T]).set(...) { ... } has the original name (*value[T]).set.
|
||||
//
|
||||
// The standard naming is something like: 'genFn[int,bool]' for functions and
|
||||
// '(*genType[int,bool]).methodName' for methods
|
||||
func MakeInstName(fnsym *types.Sym, targs []*types.Type, hasBrackets bool) *types.Sym {
|
||||
b := bytes.NewBufferString("")
|
||||
name := fnsym.Name
|
||||
i := strings.Index(name, "[")
|
||||
assert(hasBrackets == (i >= 0))
|
||||
if i >= 0 {
|
||||
b.WriteString(name[0:i])
|
||||
} else {
|
||||
b.WriteString(name)
|
||||
}
|
||||
b.WriteString("[")
|
||||
for i, targ := range targs {
|
||||
if i > 0 {
|
||||
b.WriteString(",")
|
||||
}
|
||||
b.WriteString(targ.String())
|
||||
}
|
||||
b.WriteString("]")
|
||||
if i >= 0 {
|
||||
i2 := strings.Index(name[i:], "]")
|
||||
assert(i2 >= 0)
|
||||
b.WriteString(name[i+i2+1:])
|
||||
}
|
||||
return Lookup(b.String())
|
||||
}
|
||||
|
||||
// For catching problems as we add more features
|
||||
// TODO(danscales): remove assertions or replace with base.FatalfAt()
|
||||
func assert(p bool) {
|
||||
if !p {
|
||||
panic("assertion failed")
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user