yaegi
yaegi copied to clipboard
Generic usage
The following program sample.go triggers an unexpected result
package main
import (
"fmt"
"testing"
"github.com/traefik/yaegi/interp"
)
func TestYaegi(t *testing.T) {
const src = `package main
func Sum(a, b int) int {
return a + b
}
func SumG[T ~int](a, b T) T {
return a + b
}
`
{
i := interp.New(interp.Options{})
_, err := i.Eval(src)
if err != nil {
t.Fatal(err)
}
// normal function
v, err := i.Eval("main.Sum")
if err != nil {
t.Fatal(err)
}
bar := v.Interface().(func(int, int) int)
r := bar(1, 1)
println(r)
// generic function
{
v, err := i.Eval("main.SumG[int]")
if err != nil {
t.Fatal(err)
}
fmt.Printf("v: %+v\n", v) // v: <invalid reflect.Value>
bar := v.Interface().(func(int, int) int)
r := bar(1, 1)
println(r)
}
}
}
Expected result
go test -v .
Got
--- FAIL: TestYaegi (0.00s)
panic: reflect: call of reflect.Value.Interface on zero Value [recovered]
panic: reflect: call of reflect.Value.Interface on zero Value
goroutine 21 [running]:
testing.tRunner.func1.2({0xdabfa0, 0xc00012cd08})
/home/jd/.go/current/src/testing/testing.go:1526 +0x24e
testing.tRunner.func1()
/home/jd/.go/current/src/testing/testing.go:1529 +0x39f
panic({0xdabfa0, 0xc00012cd08})
/home/jd/.go/current/src/runtime/panic.go:884 +0x213
reflect.valueInterface({0x0?, 0x0?, 0xea7241?}, 0x7?)
/home/jd/.go/current/src/reflect/value.go:1485 +0x10e
reflect.Value.Interface(...)
/home/jd/.go/current/src/reflect/value.go:1480
github.com/donnol/jdmgr/data/script/yaegi.TestYaegi(0xc000208b60)
/home/jd/Project/jd/jdmgr/data/script/yaegi/script_test.go:48 +0x2b3
testing.tRunner(0xc000208b60, 0xf17708)
/home/jd/.go/current/src/testing/testing.go:1576 +0x10b
created by testing.(*T).Run
/home/jd/.go/current/src/testing/testing.go:1629 +0x3ea
FAIL github.com/donnol/jdmgr/data/script/yaegi 0.007s
Yaegi Version
v0.15.1
Additional Notes
package main
import (
"fmt"
"testing"
"github.com/traefik/yaegi/interp"
)
func TestYaegi(t *testing.T) {
const src = `package main
func Sum(a, b int) int {
return a + b
}
func SumG[T ~int](a, b T) T {
return a + b
}
`
{
i := interp.New(interp.Options{})
_, err := i.Eval(src)
if err != nil {
t.Fatal(err)
}
// normal function
v, err := i.Eval("main.Sum")
if err != nil {
t.Fatal(err)
}
bar := v.Interface().(func(int, int) int)
r := bar(1, 1)
println(r)
// generic function
{
v, err := i.Eval("main.SumG[int]")
if err != nil {
t.Fatal(err)
}
fmt.Printf("v: %+v\n", v) // v: <invalid reflect.Value>
bar := v.Interface().(func(int, int) int)
r := bar(1, 1)
println(r)
}
}
}
failed with:
--- FAIL: TestYaegi (0.00s)
panic: reflect: call of reflect.Value.Interface on zero Value [recovered]
panic: reflect: call of reflect.Value.Interface on zero Value
goroutine 21 [running]:
testing.tRunner.func1.2({0xdabfa0, 0xc00012cd08})
/home/jd/.go/current/src/testing/testing.go:1526 +0x24e
testing.tRunner.func1()
/home/jd/.go/current/src/testing/testing.go:1529 +0x39f
panic({0xdabfa0, 0xc00012cd08})
/home/jd/.go/current/src/runtime/panic.go:884 +0x213
reflect.valueInterface({0x0?, 0x0?, 0xea7241?}, 0x7?)
/home/jd/.go/current/src/reflect/value.go:1485 +0x10e
reflect.Value.Interface(...)
/home/jd/.go/current/src/reflect/value.go:1480
github.com/donnol/jdmgr/data/script/yaegi.TestYaegi(0xc000208b60)
/home/jd/Project/jd/jdmgr/data/script/yaegi/script_test.go:48 +0x2b3
testing.tRunner(0xc000208b60, 0xf17708)
/home/jd/.go/current/src/testing/testing.go:1576 +0x10b
created by testing.(*T).Run
/home/jd/.go/current/src/testing/testing.go:1629 +0x3ea
FAIL github.com/donnol/jdmgr/data/script/yaegi 0.007s
After some try, I found it works like below:
...
{
v, err := i.Eval("main.SumG(1, 2)")
if err != nil {
t.Fatal(err)
}
r := v.Interface().(int)
println(r)
}
...
But, how can I do to work like the normal function?
I also have the same problem, and I really hope to get the answer from the master.