]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: simplify targ's type
authorKeith Randall <khr@golang.org>
Wed, 19 May 2021 16:58:01 +0000 (09:58 -0700)
committerKeith Randall <khr@golang.org>
Wed, 19 May 2021 17:33:56 +0000 (17:33 +0000)
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>
src/cmd/compile/internal/noder/stencil.go
src/cmd/compile/internal/noder/types.go
src/cmd/compile/internal/typecheck/subr.go

index adcea2c087de627c15881081ce8ca353c555e65f..87c61b2cf1c30a3362db5db9df3cc6ff6d809cad 100644 (file)
@@ -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)
index 8a2c023a1a3627237e01e5a4a032acad81fc75be..107488e6501e17bfa41799f18d084801315b53f9 100644 (file)
@@ -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())
index 9ee7a94b1f24af5bea061042a8d471c8c4758b69..97fb1451327192e010a0010df37c107f01b8d689 100644 (file)
@@ -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")
+       }
+}