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

Channel send on "binary" channel panics or errors (at compile-time) #1635

Open theclapp opened 1 month ago

theclapp commented 1 month ago

The following test case in interp/interp_eval_test.go triggers an unexpected result

func TestChannelSend(t *testing.T) {
    ch := make(chan string, 1)
    var i *interp.Interpreter

    setup := func() {
        i = interp.New(interp.Options{})
        i.Use(interp.Exports{
            "pkg/pkg": {
                "Ch": reflect.ValueOf(&ch).Elem(),
            },
        })
        i.ImportUsed()
    }

    t.Run("send in closure", func(t *testing.T) {
        setup()
        var err error
        require.NotPanics(t, func() {
            _, err = i.Eval(`package main
import . "pkg"
func main() {
    f := func() {
        Ch <- "foo"
    }
    _ = f
}`)
        })
        require.NoError(t, err)
    })

    t.Run("send by itself", func(t *testing.T) {
        setup()
        var err error
        require.NotPanics(t, func() {
            _, err = i.Eval(`package main
import . "pkg"
func main() {
    Ch <- "foo"
}`)
        })
        require.NoError(t, err)
        require.Equal(t, 1, len(ch))
        st := <-ch
        assert.Equal(t, "foo", st)
    })
}

Expected result

All tests pass without panicking

Got

"send in closure" panics at compile-time (of the Eval), "send by itself" errors in Eval.

% go test ./interp -run TestChannelSend
--- FAIL: TestChannelSend (0.00s)
    --- FAIL: TestChannelSend/send_in_closure (0.00s)
        interp_eval_test.go:2184:
                Error Trace:    /src/github.com/traefik/yaegi/interp/interp_eval_test.go:2184
                Error:          func (assert.PanicTestFunc)(0x1122f640) should not panic
                                        Panic value:    4:7: CFG post-order panic: runtime error: invalid memory address or nil pointer dereference
                                        Panic stack:    goroutine 7 [running]:
                                runtime/debug.Stack()
                                        /usr/local/go/src/runtime/debug/stack.go:24 +0x5e
                                github.com/stretchr/testify/assert.didPanic.func1()
                                        /pkg/mod/github.com/stretchr/testify@v1.9.0/assert/assertions.go:1196 +0x6b
                                panic({0x1158bb40?, 0xc000012b70?})
                                        /usr/local/go/src/runtime/panic.go:770 +0x132
                                github.com/traefik/yaegi/interp.(*Interpreter).cfg.func2.1()
                                        /src/github.com/traefik/yaegi/interp/cfg.go:611 +0x74
                                panic({0x114cf0e0?, 0x11b3c2d0?})
                                        /usr/local/go/src/runtime/panic.go:770 +0x132
                                github.com/traefik/yaegi/interp.(*itype).refType(0x0?, 0x11b696c8?)
                                        /src/github.com/traefik/yaegi/interp/type.go:2065 +0x7a
                                github.com/traefik/yaegi/interp.(*itype).TypeOf(...)
                                        /src/github.com/traefik/yaegi/interp/type.go:2223
                                github.com/traefik/yaegi/interp.genDestValue(0x0, 0xc00029ca00)
                                        /src/github.com/traefik/yaegi/interp/value.go:157 +0x25
                                github.com/traefik/yaegi/interp.send(0xc00029c780)
                                        /src/github.com/traefik/yaegi/interp/run.go:3687 +0xae
                                github.com/traefik/yaegi/interp.setExec.func1(0xc00029c780)
                                        /src/github.com/traefik/yaegi/interp/cfg.go:2874 +0x202
                                github.com/traefik/yaegi/interp.setExec(0xc00029c780)
                                        /src/github.com/traefik/yaegi/interp/cfg.go:2877 +0xf2
                                github.com/traefik/yaegi/interp.genRun.func1(0xc00029c280)
                                        /src/github.com/traefik/yaegi/interp/cfg.go:2381 +0x90
                                github.com/traefik/yaegi/interp.(*node).Walk(0xc00029c280, 0xc00029b1f8, 0x0)
                                        /src/github.com/traefik/yaegi/interp/interp.go:282 +0x2e
                                github.com/traefik/yaegi/interp.(*node).Walk(0xc000293e00, 0xc00029b1f8, 0x0)
                                        /src/github.com/traefik/yaegi/interp/interp.go:286 +0x6b
                                github.com/traefik/yaegi/interp.genRun(0xc000293e00)
                                        /src/github.com/traefik/yaegi/interp/cfg.go:2372 +0xc5
                                github.com/traefik/yaegi/interp.(*Interpreter).cfg.func2(0xc000293e00)
                                        /src/github.com/traefik/yaegi/interp/cfg.go:1553 +0x2ba7
                                github.com/traefik/yaegi/interp.(*node).Walk(0xc000293e00, 0xc00029bc18, 0xc00029bbc0)
                                        /src/github.com/traefik/yaegi/interp/interp.go:289 +0x9e
                                github.com/traefik/yaegi/interp.(*node).Walk(0xc000293b80, 0xc00029bc18, 0xc00029bbc0)
                                        /src/github.com/traefik/yaegi/interp/interp.go:286 +0x6b
                                github.com/traefik/yaegi/interp.(*node).Walk(0xc000293a40, 0xc00029bc18, 0xc00029bbc0)
                                        /src/github.com/traefik/yaegi/interp/interp.go:286 +0x6b
                                github.com/traefik/yaegi/interp.(*node).Walk(0xc0002932c0, 0xc00029bc18, 0xc00029bbc0)
                                        /src/github.com/traefik/yaegi/interp/interp.go:286 +0x6b
                                github.com/traefik/yaegi/interp.(*node).Walk(0xc000292b40, 0xc00029bc18, 0xc00029bbc0)
                                        /src/github.com/traefik/yaegi/interp/interp.go:286 +0x6b
                                github.com/traefik/yaegi/interp.(*Interpreter).cfg(0xc0000fad88, 0xc000292b40, 0xc0000f6480, {0xc000258208, 0x4}, {0xc000258208, 0x4})
                                        /src/github.com/traefik/yaegi/interp/cfg.go:69 +0x29a
                                github.com/traefik/yaegi/interp.(*Interpreter).CompileAST(0xc0000fad88, {0x115c6ef0?, 0xc0001cb4a0?})
                                        /src/github.com/traefik/yaegi/interp/program.go:97 +0x14d
                                github.com/traefik/yaegi/interp.(*Interpreter).compileSrc(0xc0000fad88, {0x1127f268?, 0xc00008ed98?}, {0x0?, 0x1093a6a0?}, 0xf?)
                                        /src/github.com/traefik/yaegi/interp/program.go:64 +0xaa
                                github.com/traefik/yaegi/interp.(*Interpreter).eval(0xc0000fad88, {0x1127f268?, 0xc00008ede0?}, {0x0?, 0xc0000cba00?},0x38?)
                                        /src/github.com/traefik/yaegi/interp/interp.go:554 +0x25
                                github.com/traefik/yaegi/interp.(*Interpreter).Eval(...)
                                        /src/github.com/traefik/yaegi/interp/interp.go:496
                                github.com/traefik/yaegi/interp_test.TestChannelSend.func2.1()
                                        /src/github.com/traefik/yaegi/interp/interp_eval_test.go:2185 +0x39
                                github.com/stretchr/testify/assert.didPanic(0x11b417a0?)
                                        /pkg/mod/github.com/stretchr/testify@v1.9.0/assert/assertions.go:1201 +0x82
                                github.com/stretchr/testify/assert.NotPanics({0x115c3ab8, 0xc0000cba00}, 0xc000012a38, {0x0, 0x0, 0x0})
                                        /pkg/mod/github.com/stretchr/testify@v1.9.0/assert/assertions.go:1272 +0x7e
                                github.com/stretchr/testify/require.NotPanics({0x115c7710, 0xc0000cba00}, 0xc000012a38, {0x0, 0x0, 0x0})
                                        /pkg/mod/github.com/stretchr/testify@v1.9.0/require/require.go:1605 +0xa6
                                github.com/traefik/yaegi/interp_test.TestChannelSend.func2(0xc0000cba00)
                                        /src/github.com/traefik/yaegi/interp/interp_eval_test.go:2184 +0xa7
                                testing.tRunner(0xc0000cba00, 0xc0000129d8)
                                        /usr/local/go/src/testing/testing.go:1689 +0xfb
                                created by testing.(*T).Run in goroutine 6
                                        /usr/local/go/src/testing/testing.go:1742 +0x390
                Test:           TestChannelSend/send_in_closure
    --- FAIL: TestChannelSend/send_by_itself (0.00s)
        interp_eval_test.go:2207:
                Error Trace:    /src/github.com/traefik/yaegi/interp/interp_eval_test.go:2207
                Error:          Received unexpected error:
                                runtime error: invalid memory address or nil pointer dereference
                Test:           TestChannelSend/send_by_itself
FAIL
FAIL    github.com/traefik/yaegi/interp 0.378s
FAIL

Yaegi Version

381e045

Additional Notes

No response