mirror of
https://github.com/golang/go
synced 2024-09-04 15:34:21 +00:00
[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>
This commit is contained in:
parent
382c5dd5f7
commit
468efd5e2f
|
@ -86,21 +86,20 @@ func (g *irgen) stencil() {
|
||||||
// instantiation.
|
// instantiation.
|
||||||
call := n.(*ir.CallExpr)
|
call := n.(*ir.CallExpr)
|
||||||
inst := call.X.(*ir.InstExpr)
|
inst := call.X.(*ir.InstExpr)
|
||||||
|
// Replace the OFUNCINST with a direct reference to the
|
||||||
|
// new stenciled function
|
||||||
st := g.getInstantiationForNode(inst)
|
st := g.getInstantiationForNode(inst)
|
||||||
|
call.X = st.Nname
|
||||||
if inst.X.Op() == ir.OCALLPART {
|
if inst.X.Op() == ir.OCALLPART {
|
||||||
// Replace the OFUNCINST with the selector
|
// When we create an instantiation of a method
|
||||||
// expression, and update the selector expression
|
// call, we make it a function. So, move the
|
||||||
// to refer to the new stenciled function.
|
// receiver to be the first arg of the function
|
||||||
call.X = inst.X
|
// call.
|
||||||
se := call.X.(*ir.SelectorExpr)
|
withRecv := make([]ir.Node, len(call.Args)+1)
|
||||||
se.Selection = types.NewField(se.Pos(), se.Sel, st.Type())
|
dot := inst.X.(*ir.SelectorExpr)
|
||||||
se.Selection.Nname = st.Nname
|
withRecv[0] = dot.X
|
||||||
se.SetOp(ir.ODOTMETH)
|
copy(withRecv[1:], call.Args)
|
||||||
se.SetType(st.Type())
|
call.Args = withRecv
|
||||||
} else {
|
|
||||||
// Replace the OFUNCINST with a direct reference to the
|
|
||||||
// new stenciled function
|
|
||||||
call.X = st.Nname
|
|
||||||
}
|
}
|
||||||
// Transform the Call now, which changes OCALL
|
// Transform the Call now, which changes OCALL
|
||||||
// to OCALLFUNC and does typecheckaste/assignconvfn.
|
// to OCALLFUNC and does typecheckaste/assignconvfn.
|
||||||
|
@ -166,9 +165,13 @@ func (g *irgen) instantiateMethods() {
|
||||||
baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym()))
|
baseSym := typ.Sym().Pkg.Lookup(genericTypeName(typ.Sym()))
|
||||||
baseType := baseSym.Def.(*ir.Name).Type()
|
baseType := baseSym.Def.(*ir.Name).Type()
|
||||||
for j, m := range typ.Methods().Slice() {
|
for j, m := range typ.Methods().Slice() {
|
||||||
|
name := m.Nname.(*ir.Name)
|
||||||
baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
|
baseNname := baseType.Methods().Slice()[j].Nname.(*ir.Name)
|
||||||
f := g.getInstantiation(baseNname, typ.RParams(), true)
|
// Note: we are breaking an invariant here:
|
||||||
m.Nname = f.Nname
|
// 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
|
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,
|
// the function type. The current function type has no Nname fields set,
|
||||||
// because it came via conversion from the types2 type.
|
// because it came via conversion from the types2 type.
|
||||||
oldt := nameNode.Type()
|
oldt := nameNode.Type()
|
||||||
dcl := newf.Dcl
|
// We also transform a generic method type to the corresponding
|
||||||
var newrecv *types.Field
|
// instantiated function type where the receiver is the first parameter.
|
||||||
if oldt.Recv() != nil {
|
newt := types.NewSignature(oldt.Pkg(), nil, nil,
|
||||||
newrecv = subst.fields(ir.PPARAM, oldt.Recvs().FieldSlice(), dcl)[0]
|
subst.fields(ir.PPARAM, append(oldt.Recvs().FieldSlice(), oldt.Params().FieldSlice()...), newf.Dcl),
|
||||||
if newrecv.Nname != nil {
|
subst.fields(ir.PPARAMOUT, oldt.Results().FieldSlice(), newf.Dcl))
|
||||||
// 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))
|
|
||||||
|
|
||||||
newf.Nname.SetType(newt)
|
newf.Nname.SetType(newt)
|
||||||
ir.MarkFunc(newf.Nname)
|
ir.MarkFunc(newf.Nname)
|
||||||
|
|
Loading…
Reference in a new issue