mirror of
https://github.com/golang/go
synced 2024-11-26 09:28:07 -07:00
[dev.typeparams] cmd/compile: do transformCall with non-shape type of call
Do the transformCall using the original types2-derived type of the call (in particular, the types of the params as non-shapes). Currently, since we were using the param types of the instantiation, we might add in interface conversions to an interface with shapes in the one case of a full-instantiated generic call. So, we do the transformCall() before installing the shaped-based instantiation. transformCall() works correctly even in the case of OCALL/FUNCINST. Fixed two related bugs: - Fixed case where we still were not correctly substituting the types for a function instantiation. - The type substituter needs to copy field flags while substituting in tstruct. Change-Id: I14e960737d6840a75846ede480e6650534ba3af3 Reviewed-on: https://go-review.googlesource.com/c/go/+/340259 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> Reviewed-by: Keith Randall <khr@golang.org>
This commit is contained in:
parent
ac78501b9c
commit
5e33d11e10
@ -125,13 +125,17 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node {
|
|||||||
}
|
}
|
||||||
if fun.Op() == ir.OFUNCINST {
|
if fun.Op() == ir.OFUNCINST {
|
||||||
// Replace explicit type args with the full list that
|
// Replace explicit type args with the full list that
|
||||||
// includes the additional inferred type args
|
// includes the additional inferred type args.
|
||||||
|
// Substitute the type args for the type params in
|
||||||
|
// the generic function's type.
|
||||||
fun.(*ir.InstExpr).Targs = targs
|
fun.(*ir.InstExpr).Targs = targs
|
||||||
|
newt := g.substType(fun.Type(), fun.Type().TParams(), targs)
|
||||||
|
typed(newt, fun)
|
||||||
} else {
|
} else {
|
||||||
// Create a function instantiation here, given there
|
// Create a function instantiation here, given there
|
||||||
// are only inferred type args (e.g. min(5,6), where
|
// are only inferred type args (e.g. min(5,6), where
|
||||||
// min is a generic function). Substitute the type
|
// min is a generic function). Substitute the type
|
||||||
// args for the type params in the uninstantiated function's
|
// args for the type params in the generic function's
|
||||||
// type.
|
// type.
|
||||||
inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs)
|
inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs)
|
||||||
newt := g.substType(fun.Type(), fun.Type().TParams(), targs)
|
newt := g.substType(fun.Type(), fun.Type().TParams(), targs)
|
||||||
|
@ -119,6 +119,14 @@ func (g *irgen) stencil() {
|
|||||||
fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call)
|
fmt.Printf("%s in %v at generic function call: %v - %v\n", dictkind, decl, inst.X, call)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Transform the Call now, which changes OCALL to
|
||||||
|
// OCALLFUNC and does typecheckaste/assignconvfn. Do
|
||||||
|
// it before installing the instantiation, so we are
|
||||||
|
// checking against non-shape param types in
|
||||||
|
// typecheckaste.
|
||||||
|
transformCall(call)
|
||||||
|
|
||||||
// Replace the OFUNCINST with a direct reference to the
|
// Replace the OFUNCINST with a direct reference to the
|
||||||
// new stenciled function
|
// new stenciled function
|
||||||
call.X = st.Nname
|
call.X = st.Nname
|
||||||
@ -132,9 +140,6 @@ func (g *irgen) stencil() {
|
|||||||
|
|
||||||
// Add dictionary to argument list.
|
// Add dictionary to argument list.
|
||||||
call.Args.Prepend(dictValue)
|
call.Args.Prepend(dictValue)
|
||||||
// Transform the Call now, which changes OCALL
|
|
||||||
// to OCALLFUNC and does typecheckaste/assignconvfn.
|
|
||||||
transformCall(call)
|
|
||||||
modified = true
|
modified = true
|
||||||
}
|
}
|
||||||
if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 {
|
if n.Op() == ir.OCALLMETH && n.(*ir.CallExpr).X.Op() == ir.ODOTMETH && len(deref(n.(*ir.CallExpr).X.Type().Recv().Type).RParams()) > 0 {
|
||||||
|
@ -130,7 +130,8 @@ func transformConvCall(n *ir.CallExpr) ir.Node {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// transformCall transforms a normal function/method call. Corresponds to last half
|
// transformCall transforms a normal function/method call. Corresponds to last half
|
||||||
// (non-conversion, non-builtin part) of typecheck.tcCall.
|
// (non-conversion, non-builtin part) of typecheck.tcCall. This code should work even
|
||||||
|
// in the case of OCALL/OFUNCINST.
|
||||||
func transformCall(n *ir.CallExpr) {
|
func transformCall(n *ir.CallExpr) {
|
||||||
// n.Type() can be nil for calls with no return value
|
// n.Type() can be nil for calls with no return value
|
||||||
assert(n.Typecheck() == 1)
|
assert(n.Typecheck() == 1)
|
||||||
|
@ -1278,6 +1278,12 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type {
|
|||||||
// the type param, not the instantiated type).
|
// the type param, not the instantiated type).
|
||||||
newfields[i] = types.NewField(f.Pos, f.Sym, t2)
|
newfields[i] = types.NewField(f.Pos, f.Sym, t2)
|
||||||
newfields[i].Embedded = f.Embedded
|
newfields[i].Embedded = f.Embedded
|
||||||
|
if f.IsDDD() {
|
||||||
|
newfields[i].SetIsDDD(true)
|
||||||
|
}
|
||||||
|
if f.Nointerface() {
|
||||||
|
newfields[i].SetNointerface(true)
|
||||||
|
}
|
||||||
if f.Nname != nil && ts.Vars != nil {
|
if f.Nname != nil && ts.Vars != nil {
|
||||||
v := ts.Vars[f.Nname.(*ir.Name)]
|
v := ts.Vars[f.Nname.(*ir.Name)]
|
||||||
if v != nil {
|
if v != nil {
|
||||||
|
Loading…
Reference in New Issue
Block a user