From 468efd5e2fb05860430c0bdede4e1cd0f8c07f65 Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 20 May 2021 15:35:55 -0700 Subject: [PATCH] [dev.typeparams] cmd/compile: change method instantiations back to being functions 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 Reviewed-by: Keith Randall TryBot-Result: Go Bot Trust: Dan Scales --- src/cmd/compile/internal/noder/stencil.go | 52 ++++++++++------------- 1 file changed, 23 insertions(+), 29 deletions(-) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index e6498e5ef8..f9cf6d8a1a 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -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)