yaegi icon indicating copy to clipboard operation
yaegi copied to clipboard

Generic usage

Open donnol opened this issue 2 years ago • 2 comments

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

donnol avatar Nov 21 '23 03:11 donnol

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?

donnol avatar Nov 22 '23 01:11 donnol

I also have the same problem, and I really hope to get the answer from the master.

sixhuan avatar Dec 27 '23 09:12 sixhuan