From 5e33d11e1051734b2495021aa64ed9f47fbae87e Mon Sep 17 00:00:00 2001 From: Dan Scales Date: Thu, 5 Aug 2021 15:59:39 -0700 Subject: [PATCH] [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 Run-TryBot: Dan Scales Reviewed-by: Keith Randall --- src/cmd/compile/internal/noder/expr.go | 8 ++++++-- src/cmd/compile/internal/noder/stencil.go | 11 ++++++++--- src/cmd/compile/internal/noder/transform.go | 3 ++- src/cmd/compile/internal/typecheck/subr.go | 6 ++++++ 4 files changed, 22 insertions(+), 6 deletions(-) diff --git a/src/cmd/compile/internal/noder/expr.go b/src/cmd/compile/internal/noder/expr.go index 6e2b1a839be..3e3c352a32f 100644 --- a/src/cmd/compile/internal/noder/expr.go +++ b/src/cmd/compile/internal/noder/expr.go @@ -125,13 +125,17 @@ func (g *irgen) expr0(typ types2.Type, expr syntax.Expr) ir.Node { } if fun.Op() == ir.OFUNCINST { // 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 + newt := g.substType(fun.Type(), fun.Type().TParams(), targs) + typed(newt, fun) } else { // Create a function instantiation here, given there // are only inferred type args (e.g. min(5,6), where // 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. inst := ir.NewInstExpr(pos, ir.OFUNCINST, fun, targs) newt := g.substType(fun.Type(), fun.Type().TParams(), targs) diff --git a/src/cmd/compile/internal/noder/stencil.go b/src/cmd/compile/internal/noder/stencil.go index 7cc37f1154e..b37f76dcee4 100644 --- a/src/cmd/compile/internal/noder/stencil.go +++ b/src/cmd/compile/internal/noder/stencil.go @@ -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) } } + + // 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 // new stenciled function call.X = st.Nname @@ -132,9 +140,6 @@ func (g *irgen) stencil() { // Add dictionary to argument list. call.Args.Prepend(dictValue) - // Transform the Call now, which changes OCALL - // to OCALLFUNC and does typecheckaste/assignconvfn. - transformCall(call) 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 { diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go index 9c791d8a7bb..61af92b62a7 100644 --- a/src/cmd/compile/internal/noder/transform.go +++ b/src/cmd/compile/internal/noder/transform.go @@ -130,7 +130,8 @@ func transformConvCall(n *ir.CallExpr) ir.Node { } // 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) { // n.Type() can be nil for calls with no return value assert(n.Typecheck() == 1) diff --git a/src/cmd/compile/internal/typecheck/subr.go b/src/cmd/compile/internal/typecheck/subr.go index 53c39333705..e840df56dc2 100644 --- a/src/cmd/compile/internal/typecheck/subr.go +++ b/src/cmd/compile/internal/typecheck/subr.go @@ -1278,6 +1278,12 @@ func (ts *Tsubster) tstruct(t *types.Type, force bool) *types.Type { // the type param, not the instantiated type). newfields[i] = types.NewField(f.Pos, f.Sym, t2) 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 { v := ts.Vars[f.Nname.(*ir.Name)] if v != nil {