diff options
| author | Dan Scales <danscales@google.com> | 2021-08-31 08:01:44 -0700 |
|---|---|---|
| committer | Dan Scales <danscales@google.com> | 2021-09-07 23:27:08 +0000 |
| commit | 3fff213ac24dc3b9b92c8a1f5f18ec0c97bac4c0 (patch) | |
| tree | b0ce065aa21e6ae2ba79a747067ddcc549c1922a /src/cmd/compile/internal/noder/transform.go | |
| parent | b606739be6758615658188c8a6453256eaeccf35 (diff) | |
| download | go-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.go | 53 |
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 |
