aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder/stencil.go
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-05-20 15:35:55 -0700
committerDan Scales <danscales@google.com>2021-05-20 23:01:37 +0000
commit468efd5e2fb05860430c0bdede4e1cd0f8c07f65 (patch)
tree62426b4571bd10a3ae584cea4b3442f76b0f0c5f /src/cmd/compile/internal/noder/stencil.go
parent382c5dd5f754392444fbe2c3489d09b2f36f3939 (diff)
downloadgo-468efd5e2fb05860430c0bdede4e1cd0f8c07f65.tar.xz
[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 <danscales@google.com> Reviewed-by: Keith Randall <khr@golang.org> TryBot-Result: Go Bot <gobot@golang.org> Trust: Dan Scales <danscales@google.com>
Diffstat (limited to 'src/cmd/compile/internal/noder/stencil.go')
-rw-r--r--src/cmd/compile/internal/noder/stencil.go52
1 files 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)