aboutsummaryrefslogtreecommitdiff
path: root/src/cmd/compile/internal/noder/transform.go
diff options
context:
space:
mode:
authorDan Scales <danscales@google.com>2021-08-31 08:01:44 -0700
committerDan Scales <danscales@google.com>2021-09-07 23:27:08 +0000
commit3fff213ac24dc3b9b92c8a1f5f18ec0c97bac4c0 (patch)
treeb0ce065aa21e6ae2ba79a747067ddcc549c1922a /src/cmd/compile/internal/noder/transform.go
parentb606739be6758615658188c8a6453256eaeccf35 (diff)
downloadgo-3fff213ac24dc3b9b92c8a1f5f18ec0c97bac4c0.tar.xz
cmd/compile: add CONVIFACE nodes needed in generic code due to assignments
Added new function earlyTransformAssign() to add needed CONVIFACE nodes due to assignments in generic functions. Fixes #48049 Change-Id: I7cd9cee6ecf34ed2ef0743d1b17645b9f520fa00 Reviewed-on: https://go-review.googlesource.com/c/go/+/347914 Trust: Dan Scales <danscales@google.com> Run-TryBot: Dan Scales <danscales@google.com> TryBot-Result: Go Bot <gobot@golang.org> Reviewed-by: Keith Randall <khr@golang.org>
Diffstat (limited to 'src/cmd/compile/internal/noder/transform.go')
-rw-r--r--src/cmd/compile/internal/noder/transform.go53
1 files changed, 53 insertions, 0 deletions
diff --git a/src/cmd/compile/internal/noder/transform.go b/src/cmd/compile/internal/noder/transform.go
index 180891b5b5..b278f3db09 100644
--- a/src/cmd/compile/internal/noder/transform.go
+++ b/src/cmd/compile/internal/noder/transform.go
@@ -365,6 +365,59 @@ 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