traefik / yaegi

Yaegi is Another Elegant Go Interpreter
https://pkg.go.dev/github.com/traefik/yaegi
Apache License 2.0
6.78k stars 341 forks source link

When I tried to modify the code in the example, I got a panic, because bar.NewFoo returns a *struct { A string }, not a *bar.Foo #1616

Closed Softwarekang closed 3 months ago

Softwarekang commented 4 months ago

The following program sample.go triggers an unexpected result

package main

import (
    `fmt`
    "testing"

    `github.com/traefik/yaegi/example/getfunc/_gopath/src/github.com/foo/bar`
    "github.com/traefik/yaegi/interp"
    "github.com/traefik/yaegi/stdlib"
)

func TestGetFunc(t *testing.T) {
    i := interp.New(interp.Options{GoPath: "./_gopath/"})
    if err := i.Use(stdlib.Symbols); err != nil {
        t.Fatal(err)
    }

    if _, err := i.Eval(`import "github.com/foo/bar"`); err != nil {
        t.Fatal(err)
    }

    val, err := i.Eval(`bar.NewFoo`)
    if err != nil {
        t.Fatal(err)
    }

    // this is ok
    fmt.Println(val.Call(nil)[0].Interface().(*struct {
        A string
    }).A)

    // this will panic
    fmt.Println(val.Call(nil)[0].Interface().(*bar.Foo).A)
}

Expected result

$ go run ./sample.go
// output
test
test

Got

=== RUN   TestGetFunc
test
--- FAIL: TestGetFunc (0.00s)
panic: interface conversion: interface {} is *struct { A string }, not *bar.Foo [recovered]
    panic: interface conversion: interface {} is *struct { A string }, not *bar.Foo

goroutine 6 [running]:
testing.tRunner.func1.2({0x10183d200, 0x14000336ab0})
    /usr/local/go/src/testing/testing.go:1545 +0x1c8
testing.tRunner.func1()
    /usr/local/go/src/testing/testing.go:1548 +0x360
panic({0x10183d200?, 0x14000336ab0?})
    /usr/local/go/src/runtime/panic.go:914 +0x218
github.com/traefik/yaegi/example/getfunc.TestGetFunc(0x14000151040)
    /Users/10029528/project/github/yaegi/example/getfunc/getfunc_test.go:31 +0x268
testing.tRunner(0x14000151040, 0x10191c3b0)
    /usr/local/go/src/testing/testing.go:1595 +0xe8
created by testing.(*T).Run in goroutine 1
    /usr/local/go/src/testing/testing.go:1648 +0x33c

Yaegi Version

9aa161f2da6ef119d62d939ba113af8cad5c54b2

Additional Notes

No response

Softwarekang commented 3 months ago

"I've resolved the issue using the Convert method, but perhaps yaegi could handle this more efficiently." values := val.Call(nil) barValue := values[0].Convert(reflect.TypeOf(&bar.Foo{})) fmt.Println(barValue.Interface().(*bar.Foo).A)