]> Cypherpunks repositories - gostls13.git/commitdiff
[dev.typeparams] cmd/compile: do transformCall with non-shape type of call
authorDan Scales <danscales@google.com>
Thu, 5 Aug 2021 22:59:39 +0000 (15:59 -0700)
committerDan Scales <danscales@google.com>
Fri, 6 Aug 2021 19:13:56 +0000 (19:13 +0000)
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>
src/cmd/compile/internal/noder/expr.go
src/cmd/compile/internal/noder/stencil.go
src/cmd/compile/internal/noder/transform.go
src/cmd/compile/internal/typecheck/subr.go

index 6e2b1a839bee6c4162c9815d3e732c04658e37b7..3e3c352a32f69533ced634c035148391985498be 100644 (file)
@@ -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)
index 7cc37f1154e35d1753ef7a3e553c154f9185366f..b37f76dcee4115c2c6a87a136716e271a1068a5a 100644 (file)
@@ -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 {
index 9c791d8a7bb6de19964057bc0c8441dc90230971..61af92b62a761a39386052efd6b6e8300d57f591 100644 (file)
@@ -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)
index 53c39333705281a30842fda8495955f6f17925ff..e840df56dc2ea9ac4d434384f3860a0ddf546981 100644 (file)
@@ -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 {