]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: change method instantiations back to being functions
authorDan Scales <danscales@google.com>
Thu, 20 May 2021 22:35:55 +0000 (15:35 -0700)
committerDan Scales <danscales@google.com>
Thu, 20 May 2021 23:01:37 +0000 (23:01 +0000)
Change all instantiated methods to being functions again. We found that
this is easier for adding the dictionary argument consistently. A method
wrapper will usually be added around the instantiation call, so that
eliminate the inconsistency in the type of the top-level method and the
the associated function node type.

Change-Id: I9034a0c5cc901e7a89e60756bff574c1346adbc7
Reviewed-on: https://go-review.googlesource.com/c/go/+/321609
Run-TryBot: Dan Scales <danscales@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Dan Scales <danscales@google.com>

src/cmd/compile/internal/noder/stencil.go

index e6498e5ef848e72a414e7d71cb911cc7df7e069b..f9cf6d8a1a9079c5c809710a47d703d763b06f6f 100644 (file)
@@ -86,21 +86,20 @@ func (g *irgen) stencil() {
                        // instantiation.
                        call := n.(*ir.CallExpr)
                        inst := call.X.(*ir.InstExpr)
+                       // Replace the OFUNCINST with a direct reference to the
+                       // new stenciled function
                        st := g.getInstantiationForNode(inst)
+                       call.X = st.Nname
                        if inst.X.Op() == ir.OCALLPART {
-                               // Replace the OFUNCINST with the selector
-                               // expression, and update the selector expression
-                               // to refer to the new stenciled function.
-                               call.X = inst.X
-                               se := call.X.(*ir.SelectorExpr)
-                               se.Selection = types.NewField(se.Pos(), se.Sel, st.Type())
-                               se.Selection.Nname = st.Nname
-                               se.SetOp(ir.ODOTMETH)
-                               se.SetType(st.Type())
-                       } else {
-                               // Replace the OFUNCINST with a direct reference to the
-                               // new stenciled function
-                               call.X = st.Nname
+                               // When we create an instantiation of a method
+                               // call, we make it a function. So, move the
+                               // receiver to be the first arg of the function
+                               // call.
+                               withRecv := make([]ir.Node, len(call.Args)+1)
+                               dot := inst.X.(*ir.SelectorExpr)
+                               withRecv[0] = dot.X
+                               copy(withRecv[1:], call.Args)
+                               call.Args = withRecv
                        }
                        // Transform the Call now, which changes OCALL
                        // to OCALLFUNC and does typecheckaste/assignconvfn.
@@ -166,9 +165,13 @@ 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() {
+                       name := m.Nname.(*ir.Name)
                        baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
-                       f := g.getInstantiation(baseNname, typ.RParams(), true)
-                       m.Nname = f.Nname
+                       // Note: we are breaking an invariant here:
+                       // m.Nname is now not equal m.Nname.Func.Nname.
+                       // m.Nname has the type of a method, whereas m.Nname.Func.Nname has
+                       // the type of a function, since it is an function instantiation.
+                       name.Func = g.getInstantiation(baseNname, typ.RParams(), true)
                }
        }
        g.instTypeList = nil
@@ -279,20 +282,11 @@ func (g *irgen) genericSubst(newsym *types.Sym, nameNode *ir.Name, targs []*type
        // the function type. The current function type has no Nname fields set,
        // because it came via conversion from the types2 type.
        oldt := nameNode.Type()
-       dcl := newf.Dcl
-       var newrecv *types.Field
-       if oldt.Recv() != nil {
-               newrecv = subst.fields(ir.PPARAM, oldt.Recvs().FieldSlice(), dcl)[0]
-               if newrecv.Nname != nil {
-                       // If we found the receiver in the dcl list, then skip it
-                       // when we scan for the remaining params below.
-                       assert(newrecv.Nname == dcl[0])
-                       dcl = dcl[1:]
-               }
-       }
-       newt := types.NewSignature(oldt.Pkg(), newrecv, nil,
-               subst.fields(ir.PPARAM, oldt.Params().FieldSlice(), dcl),
-               subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), dcl))
+       // We also transform a generic method type to the corresponding
+       // instantiated function type where the receiver is the first parameter.
+       newt := types.NewSignature(oldt.Pkg(), nil, nil,
+               subst.fields(ir.PPARAM, append(oldt.Recvs().FieldSlice(), oldt.Params().FieldSlice()...), newf.Dcl),
+               subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl))
 
        newf.Nname.SetType(newt)
        ir.MarkFunc(newf.Nname)