fix: improve setting results in multiple output functions

This commit is contained in:
Marc Vertes
2020-05-05 22:34:03 +02:00
committed by GitHub
parent 7fab75fbe4
commit b9720d15e1
4 changed files with 53 additions and 8 deletions

17
_test/fun19.go Normal file
View File

@@ -0,0 +1,17 @@
package main
import (
"fmt"
)
func foo() ([]string, error) {
return nil, fmt.Errorf("bar")
}
func main() {
a, b := foo()
fmt.Println(a, b)
}
// Output:
// [] bar

19
_test/fun20.go Normal file
View File

@@ -0,0 +1,19 @@
package main
import "fmt"
var myerr error = fmt.Errorf("bar")
func ferr() error { return myerr }
func foo() ([]string, error) {
return nil, ferr()
}
func main() {
a, b := foo()
fmt.Println(a, b)
}
// Output:
// [] bar

View File

@@ -823,9 +823,13 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
}
} else {
n.typ = &itype{cat: valueT, rtype: typ.Out(0)}
n.findex = sc.add(n.typ)
for i := 1; i < typ.NumOut(); i++ {
sc.add(&itype{cat: valueT, rtype: typ.Out(i)})
if n.anc.kind == returnStmt {
n.findex = childPos(n)
} else {
n.findex = sc.add(n.typ)
for i := 1; i < typ.NumOut(); i++ {
sc.add(&itype{cat: valueT, rtype: typ.Out(i)})
}
}
}
}
@@ -836,9 +840,13 @@ func (interp *Interpreter) cfg(root *node, pkgID string) ([]*node, error) {
}
if typ := n.child[0].typ; len(typ.ret) > 0 {
n.typ = typ.ret[0]
n.findex = sc.add(n.typ)
for _, t := range typ.ret[1:] {
sc.add(t)
if n.anc.kind == returnStmt {
n.findex = childPos(n)
} else {
n.findex = sc.add(n.typ)
for _, t := range typ.ret[1:] {
sc.add(t)
}
}
} else {
n.findex = -1

View File

@@ -687,7 +687,7 @@ func call(n *node) {
case returnStmt:
// Function call from a return statement: forward return values (always at frame start).
for i := range rtypes {
j := i
j := n.findex + i
ret := n.child[0].typ.ret[i]
callret := n.anc.val.(*node).typ.ret[i]
if callret.cat == interfaceT && ret.cat != interfaceT {
@@ -983,6 +983,7 @@ func callBin(n *node) {
case aReturn:
// The function call is part of a return statement, store output results
// directly in the frame location of outputs of the current function.
b := childPos(n)
n.exec = func(f *frame) bltn {
in := make([]reflect.Value, l)
for i, v := range values {
@@ -990,7 +991,7 @@ func callBin(n *node) {
}
out := value(f).Call(in)
for i, v := range out {
f.data[i].Set(v)
f.data[b+i].Set(v)
}
return tnext
}