mirror of
https://github.com/golang/go.git
synced 2025-12-08 06:10:04 +00:00
[dev.typeparams] cmd/compile: call transformArgs before early typecheckaste in noder
In the cases where we do an early call to typecheckaste() in noder to expose CONVIFACE nodes, we need a preceding call to transformArgs(). This is needed to allow typecheckaste() to run correctly, in the case of f(g()), where g has multiple return values. I also cleaned up the code a bit and commented the code in Call(), and we do the call to typecheckaste() in several more cases. In stencil.go:stencil(), I moved the transformCall earlier for the OCALLMETH/ODOTMETH case, just as I did in my previous CL for OCALL/OFUNCINST. By doing this, transformArgs no longer needs to deal with the extra dictionary args. Therefore, I was able to simply transformArgs() to look like typecheckargs() again, and make use of RewriteMultiValue directly. Updates #47514 Change-Id: I49eb82ac05707e50c2e2fb03e39458a70491d406 Reviewed-on: https://go-review.googlesource.com/c/go/+/340531 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>
This commit is contained in:
parent
ca3c6985cd
commit
9f4d6a8359
5 changed files with 55 additions and 91 deletions
|
|
@ -365,7 +365,7 @@ assignOK:
|
|||
}
|
||||
}
|
||||
|
||||
// Corresponds to, but slightly more general than, typecheck.typecheckargs.
|
||||
// Corresponds to typecheck.typecheckargs. Really just deals with multi-value calls.
|
||||
func transformArgs(n ir.InitNode) {
|
||||
var list []ir.Node
|
||||
switch n := n.(type) {
|
||||
|
|
@ -379,76 +379,22 @@ func transformArgs(n ir.InitNode) {
|
|||
case *ir.ReturnStmt:
|
||||
list = n.Results
|
||||
}
|
||||
|
||||
// Look to see if we have any multi-return functions as arguments.
|
||||
extra := 0
|
||||
for _, arg := range list {
|
||||
t := arg.Type()
|
||||
if t.IsFuncArgStruct() {
|
||||
num := t.Fields().Len()
|
||||
if num <= 1 {
|
||||
base.Fatalf("multi-return type with only %d parts", num)
|
||||
}
|
||||
extra += num - 1
|
||||
}
|
||||
}
|
||||
// If not, nothing to do.
|
||||
if extra == 0 {
|
||||
if len(list) != 1 {
|
||||
return
|
||||
}
|
||||
|
||||
// Rewrite f(..., g(), ...) into t1, ..., tN = g(); f(..., t1, ..., tN, ...).
|
||||
t := list[0].Type()
|
||||
if t == nil || !t.IsFuncArgStruct() {
|
||||
return
|
||||
}
|
||||
|
||||
// Save n as n.Orig for fmt.go.
|
||||
if ir.Orig(n) == n {
|
||||
n.(ir.OrigNode).SetOrig(ir.SepCopy(n))
|
||||
}
|
||||
|
||||
// If we're outside of function context, then this call will
|
||||
// be executed during the generated init function. However,
|
||||
// init.go hasn't yet created it. Instead, associate the
|
||||
// temporary variables with InitTodoFunc for now, and init.go
|
||||
// will reassociate them later when it's appropriate.
|
||||
static := ir.CurFunc == nil
|
||||
if static {
|
||||
ir.CurFunc = typecheck.InitTodoFunc
|
||||
}
|
||||
|
||||
// Expand multi-return function calls.
|
||||
// The spec only allows a multi-return function as an argument
|
||||
// if it is the only argument. This code must handle calls to
|
||||
// stenciled generic functions which have extra arguments
|
||||
// (like the dictionary) so it must handle a slightly more general
|
||||
// cases, like f(n, g()) where g is multi-return.
|
||||
newList := make([]ir.Node, 0, len(list)+extra)
|
||||
for _, arg := range list {
|
||||
t := arg.Type()
|
||||
if t.IsFuncArgStruct() {
|
||||
as := ir.NewAssignListStmt(base.Pos, ir.OAS2, nil, []ir.Node{arg})
|
||||
for _, f := range t.FieldSlice() {
|
||||
t := typecheck.Temp(f.Type)
|
||||
as.PtrInit().Append(ir.NewDecl(base.Pos, ir.ODCL, t))
|
||||
as.Lhs.Append(t)
|
||||
newList = append(newList, t)
|
||||
}
|
||||
transformAssign(as, as.Lhs, as.Rhs)
|
||||
as.SetTypecheck(1)
|
||||
n.PtrInit().Append(as)
|
||||
} else {
|
||||
newList = append(newList, arg)
|
||||
}
|
||||
}
|
||||
|
||||
if static {
|
||||
ir.CurFunc = nil
|
||||
}
|
||||
|
||||
switch n := n.(type) {
|
||||
case *ir.CallExpr:
|
||||
n.Args = newList
|
||||
case *ir.ReturnStmt:
|
||||
n.Results = newList
|
||||
}
|
||||
// Rewrite f(g()) into t1, t2, ... = g(); f(t1, t2, ...).
|
||||
typecheck.RewriteMultiValueCall(n, list[0])
|
||||
}
|
||||
|
||||
// assignconvfn converts node n for assignment to type t. Corresponds to
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue