]> Cypherpunks repositories - gostls13.git/commitdiff
cmd/compile: remove unneeded early transforms, with dictionary change
authorDan Scales <danscales@google.com>
Sun, 12 Sep 2021 19:21:48 +0000 (12:21 -0700)
committerDan Scales <danscales@google.com>
Wed, 15 Sep 2021 22:53:42 +0000 (22:53 +0000)
Now that we are computing the dictionary format on the instantiated
functions, we can remove the early transformation code that was needed
to create the implicit CONVIFACE nodes in the generic function.

Change-Id: I1695484e7d59bccbfb757994f3e40e84288759a5
Reviewed-on: https://go-review.googlesource.com/c/go/+/349614
Run-TryBot: Dan Scales <danscales@google.com>
TryBot-Result: Go Bot <gobot@golang.org>
Trust: Dan Scales <danscales@google.com>
Reviewed-by: Keith Randall <khr@golang.org>
src/cmd/compile/internal/noder/expr.go
src/cmd/compile/internal/noder/helpers.go
src/cmd/compile/internal/noder/stmt.go
src/cmd/compile/internal/noder/transform.go
src/cmd/compile/internal/typecheck/subr.go

index 045f028e1aa124c3dddb46a0e7a7e89ede6fb822..3e1960f7a4dc8d522069763fad665f6345ab157f 100644 (file)
@@ -250,44 +250,6 @@ func (g *irgen) selectorExpr(pos src.XPos, typ types2.Type, expr *syntax.Selecto
                // only be fully transformed once it has an instantiated type.
                n := ir.NewSelectorExpr(pos, ir.OXDOT, x, typecheck.Lookup(expr.Sel.Value))
                typed(g.typ(typ), n)
-
-               // Fill in n.Selection for a generic method reference or a bound
-               // interface method, even though we won't use it directly, since it
-               // is useful for analysis. Specifically do not fill in for fields or
-               // other interfaces methods (method call on an interface value), so
-               // n.Selection being non-nil means a method reference for a generic
-               // type or a method reference due to a bound.
-               obj2 := g.info.Selections[expr].Obj()
-               sig := types2.AsSignature(obj2.Type())
-               if sig == nil || sig.Recv() == nil {
-                       return n
-               }
-               index := g.info.Selections[expr].Index()
-               last := index[len(index)-1]
-               // recvType is the receiver of the method being called.  Because of the
-               // way methods are imported, g.obj(obj2) doesn't work across
-               // packages, so we have to lookup the method via the receiver type.
-               recvType := deref2(sig.Recv().Type())
-               if types2.AsInterface(recvType.Underlying()) != nil {
-                       fieldType := n.X.Type()
-                       for _, ix := range index[:len(index)-1] {
-                               fieldType = deref(fieldType).Field(ix).Type
-                       }
-                       if fieldType.Kind() == types.TTYPEPARAM {
-                               n.Selection = fieldType.Bound().AllMethods().Index(last)
-                               //fmt.Printf(">>>>> %v: Bound call %v\n", base.FmtPos(pos), n.Sel)
-                       } else {
-                               assert(fieldType.Kind() == types.TINTER)
-                               //fmt.Printf(">>>>> %v: Interface call %v\n", base.FmtPos(pos), n.Sel)
-                       }
-                       return n
-               }
-
-               recvObj := types2.AsNamed(recvType).Obj()
-               recv := g.pkg(recvObj.Pkg()).Lookup(recvObj.Name()).Def
-               n.Selection = recv.Type().Methods().Index(last)
-               //fmt.Printf(">>>>> %v: Method call %v\n", base.FmtPos(pos), n.Sel)
-
                return n
        }
 
index 9487e76336cea7f8938ebd8ee288ea8751d6e613..f06dd8b0653b56e9693f087b4834c4cd25a4edaa 100644 (file)
@@ -189,17 +189,6 @@ func Call(pos src.XPos, typ *types.Type, fun ir.Node, args []ir.Node, dots bool)
                // A function instantiation (even if fully concrete) shouldn't be
                // transformed yet, because we need to add the dictionary during the
                // transformation.
-               //
-               // However, if we have a function type (even though it is
-               // parameterized), then we can add in any needed CONVIFACE nodes via
-               // typecheckaste(). We need to call transformArgs() to deal first
-               // with the f(g(()) case where g returns multiple return values. We
-               // can't do anything if fun is a type param (which is probably
-               // described by a structural constraint)
-               if fun.Type().Kind() == types.TFUNC {
-                       transformArgs(n)
-                       typecheckaste(ir.OCALL, fun, n.IsDDD, fun.Type().Params(), n.Args, true)
-               }
                return typed(typ, n)
        }
 
index 146761c23f79aceeacc48e8f26aa58cbea1bd9e2..1c366296fc849a122d2e3c5f80a63d07e8e04596 100644 (file)
@@ -101,8 +101,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
                        n.Def = initDefn(n, names)
 
                        if delay {
-                               earlyTransformAssign(n, lhs, rhs)
-                               n.X, n.Y = lhs[0], rhs[0]
                                n.SetTypecheck(3)
                                return n
                        }
@@ -117,7 +115,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
                n := ir.NewAssignListStmt(g.pos(stmt), ir.OAS2, lhs, rhs)
                n.Def = initDefn(n, names)
                if delay {
-                       earlyTransformAssign(n, lhs, rhs)
                        n.SetTypecheck(3)
                        return n
                }
@@ -135,12 +132,6 @@ func (g *irgen) stmt(stmt syntax.Stmt) ir.Node {
                        if e.Type().HasTParam() {
                                // Delay transforming the return statement if any of the
                                // return values have a type param.
-                               if !ir.HasNamedResults(ir.CurFunc) {
-                                       transformArgs(n)
-                                       // But add CONVIFACE nodes where needed if
-                                       // any of the return values have interface type.
-                                       typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), n.Results, true)
-                               }
                                n.SetTypecheck(3)
                                return n
                        }
index 8173bfc747f20ce59f8f36a858d0a0b1eb035e8b..91374054b6662d3a53e6bb9cb448ea3b066093f7 100644 (file)
@@ -157,7 +157,7 @@ func transformCall(n *ir.CallExpr) {
                n.SetOp(ir.OCALLFUNC)
        }
 
-       typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args, false)
+       typecheckaste(ir.OCALL, n.X, n.IsDDD, t.Params(), n.Args)
        if l.Op() == ir.ODOTMETH && len(deref(n.X.Type().Recv().Type).RParams()) == 0 {
                typecheck.FixMethodCall(n)
        }
@@ -365,59 +365,6 @@ assignOK:
        }
 }
 
-// Version of transformAssign that can run on generic code that adds CONVIFACE calls
-// as needed (and rewrites multi-value calls).
-func earlyTransformAssign(stmt ir.Node, lhs, rhs []ir.Node) {
-       cr := len(rhs)
-       if len(rhs) == 1 {
-               if rtyp := rhs[0].Type(); rtyp != nil && rtyp.IsFuncArgStruct() {
-                       cr = rtyp.NumFields()
-               }
-       }
-
-       // x,y,z = f()
-       _, isCallExpr := rhs[0].(*ir.CallExpr)
-       if isCallExpr && cr > len(rhs) {
-               stmt := stmt.(*ir.AssignListStmt)
-               stmt.SetOp(ir.OAS2FUNC)
-               r := rhs[0].(*ir.CallExpr)
-               rtyp := r.Type()
-
-               mismatched := false
-               failed := false
-               for i := range lhs {
-                       result := rtyp.Field(i).Type
-
-                       if lhs[i].Type() == nil || result == nil {
-                               failed = true
-                       } else if lhs[i] != ir.BlankNode && !types.Identical(lhs[i].Type(), result) {
-                               mismatched = true
-                       }
-               }
-               if mismatched && !failed {
-                       typecheck.RewriteMultiValueCall(stmt, r)
-               }
-               return
-       }
-
-       // x, ok = y
-       if len(lhs) != len(rhs) {
-               assert(len(lhs) == 2 && len(rhs) == 1)
-               // TODO(danscales): deal with case where x or ok is an interface
-               // type. We want to add CONVIFACE now, but that is tricky, because
-               // the rhs may be AS2MAPR, AS2RECV, etc. which has two result values,
-               // and that is not rewritten until the order phase (o.stmt, as2ok).
-               return
-       }
-
-       // Check for interface conversion on each assignment
-       for i, r := range rhs {
-               if lhs[i].Type() != nil && lhs[i].Type().IsInterface() {
-                       rhs[i] = assignconvfn(r, lhs[i].Type())
-               }
-       }
-}
-
 // Corresponds to typecheck.typecheckargs.  Really just deals with multi-value calls.
 func transformArgs(n ir.InitNode) {
        var list []ir.Node
@@ -457,11 +404,11 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node {
                return n
        }
 
-       if types.Identical(n.Type(), t) {
+       if types.IdenticalStrict(n.Type(), t) {
                return n
        }
 
-       op, why := typecheck.Assignop(n.Type(), t)
+       op, why := Assignop(n.Type(), t)
        if op == ir.OXXX {
                base.Fatalf("found illegal assignment %+v -> %+v; %s", n.Type(), t, why)
        }
@@ -472,11 +419,26 @@ func assignconvfn(n ir.Node, t *types.Type) ir.Node {
        return r
 }
 
+func Assignop(src, dst *types.Type) (ir.Op, string) {
+       if src == dst {
+               return ir.OCONVNOP, ""
+       }
+       if src == nil || dst == nil || src.Kind() == types.TFORW || dst.Kind() == types.TFORW || src.Underlying() == nil || dst.Underlying() == nil {
+               return ir.OXXX, ""
+       }
+
+       // 1. src type is identical to dst.
+       if types.IdenticalStrict(src, dst) {
+               return ir.OCONVNOP, ""
+       }
+       return typecheck.Assignop1(src, dst)
+}
+
 // Corresponds to typecheck.typecheckaste, but we add an extra flag convifaceOnly
 // only. If convifaceOnly is true, we only do interface conversion. We use this to do
 // early insertion of CONVIFACE nodes during noder2, when the function or args may
 // have typeparams.
-func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes, convifaceOnly bool) {
+func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl ir.Nodes) {
        var t *types.Type
        var i int
 
@@ -495,7 +457,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i
                        if isddd {
                                n = nl[i]
                                ir.SetPos(n)
-                               if n.Type() != nil && (!convifaceOnly || t.IsInterface()) {
+                               if n.Type() != nil {
                                        nl[i] = assignconvfn(n, t)
                                }
                                return
@@ -505,7 +467,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i
                        for ; i < len(nl); i++ {
                                n = nl[i]
                                ir.SetPos(n)
-                               if n.Type() != nil && (!convifaceOnly || t.IsInterface()) {
+                               if n.Type() != nil {
                                        nl[i] = assignconvfn(n, t.Elem())
                                }
                        }
@@ -514,7 +476,7 @@ func typecheckaste(op ir.Op, call ir.Node, isddd bool, tstruct *types.Type, nl i
 
                n = nl[i]
                ir.SetPos(n)
-               if n.Type() != nil && (!convifaceOnly || t.IsInterface()) {
+               if n.Type() != nil {
                        nl[i] = assignconvfn(n, t)
                }
                i++
@@ -536,7 +498,7 @@ func transformReturn(rs *ir.ReturnStmt) {
                return
        }
 
-       typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl, false)
+       typecheckaste(ir.ORETURN, nil, false, ir.CurFunc.Type().Results(), nl)
 }
 
 // transformSelect transforms a select node, creating an assignment list as needed
index 64d30eeb5ae316c1e46b458af65dc8affd732dde..d4af4e172e65581a64807ffb2eb0046a2e985620 100644 (file)
@@ -352,7 +352,10 @@ func Assignop(src, dst *types.Type) (ir.Op, string) {
        if types.Identical(src, dst) {
                return ir.OCONVNOP, ""
        }
+       return Assignop1(src, dst)
+}
 
+func Assignop1(src, dst *types.Type) (ir.Op, string) {
        // 2. src and dst have identical underlying types and
        //   a. either src or dst is not a named type, or
        //   b. both are empty interface types, or