fix: improving handling of functions returning interfaces

This commit is contained in:
Marc Vertes
2020-05-03 17:46:03 +02:00
committed by GitHub
parent 7d56fb067e
commit e4acba031d
7 changed files with 77 additions and 2 deletions

11
_test/fun15.go Normal file
View File

@@ -0,0 +1,11 @@
package main
func f1(a int) interface{} { return a + 1 }
func main() {
c := f1(3)
println(c.(int))
}
// Output:
// 4

13
_test/fun16.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f1(a int) int { return a + 1 }
func f2(a int) interface{} { return f1(a) }
func main() {
c := f2(3)
println(c.(int))
}
// Output:
// 4

13
_test/fun17.go Normal file
View File

@@ -0,0 +1,13 @@
package main
func f1(a int) interface{} { return a + 1 }
func f2(a int) interface{} { return f1(a) }
func main() {
c := f2(3)
println(c.(int))
}
// Output:
// 4

12
_test/fun18.go Normal file
View File

@@ -0,0 +1,12 @@
package main
var m = map[string]int{"foo": 1, "bar": 2}
func f(s string) interface{} { return m[s] }
func main() {
println(f("foo").(int))
}
// Output:
// 1

11
_test/map26.go Normal file
View File

@@ -0,0 +1,11 @@
package main
var m = map[string]int{"foo": 1, "bar": 2}
func main() {
var a interface{} = m["foo"]
println(a.(int))
}
// Output:
// 1

View File

@@ -684,7 +684,19 @@ func call(n *node) {
// Function call from a return statement: forward return values (always at frame start).
for i := range rtypes {
j := i
rvalues[i] = func(f *frame) reflect.Value { return f.data[j] }
ret := n.child[0].typ.ret[i]
callret := n.anc.val.(*node).typ.ret[i]
if callret.cat == interfaceT && ret.cat != interfaceT {
// Wrap the returned value in a valueInterface in caller frame.
rvalues[i] = func(f *frame) reflect.Value {
v := reflect.New(ret.rtype).Elem()
f.data[j].Set(reflect.ValueOf(valueInterface{n, v}))
return v
}
} else {
// Set the return value location in return value of caller frame.
rvalues[i] = func(f *frame) reflect.Value { return f.data[j] }
}
}
default:
// Multiple return values frame index are indexed from the node frame index.

View File

@@ -253,10 +253,13 @@ func nodeType(interp *Interpreter, sc *scope, n *node) (*itype, error) {
}
// If the node is to be assigned or returned, the node type is the destination type.
dt := t
if a := n.anc; a.kind == defineStmt && len(a.child) > a.nleft+a.nright {
switch a := n.anc; {
case a.kind == defineStmt && len(a.child) > a.nleft+a.nright:
if dt, err = nodeType(interp, sc, a.child[a.nleft]); err != nil {
return nil, err
}
case a.kind == returnStmt:
dt = sc.def.typ.ret[childPos(n)]
}
if isInterface(dt) {
dt.val = t