traefik / yaegi

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

CFG post-order panic: ... incomplete type (on Windows) #1652

Open saurabh-io opened 1 month ago

saurabh-io commented 1 month ago

The following program sample.go triggers an unexpected result

1) Project Structure
C:\projects\go_projects\yaegi_test

yaegi_test
  - hello.go
  - go.mod
  - lib\src\mymodule\mavapi

2) lib\src\mymodule\mavapi\mav_api.go
package mavapi

type ApiError struct {
    XErr string `json:"error,omitempty"`
    Desc string `json:"error_description,omitempty"`
}

type IdpApiResp[T any] struct {
    HttpStatus int      `json:"httpStatus"`
    Body       *T       `json:"body,omitempty"`
    ErrSource  string   `json:"errSource,omitempty"`
    SomeError  ApiError `json:"error,omitempty"`
}

3) hello.go

package main

import (
    "mymodule/mavapi"
    "fmt"
)

func main() {
    fmt.Println("Hello world")
    x := mavapi.IdpApiResp[string]{
        HttpStatus: 0,
        Body:       new(string),
        ErrSource:  "",
        SomeError:  mavapi.ApiError{},
    }
    fmt.Println(x)
}

4) Run from windows command line
cd C:\projects\go_projects\yaegi_test>
set GOPATH=C:\projects\go_projects\yaegi_test\lib
yaegi hello.go

Expected result

C:\projects\go_projects\yaegi_test>go run hello.go
Hello world
{0 0xc00008a030  { }}

Got

C:\projects\go_projects\yaegi_test>yaegi hello.go

panic: C:\projects\go_projects\yaegi_test\lib\src\yyyy\someapi\mav_api.go:18:13: incomplete type ApiError [recovered]
        panic: hello.go:10:7: CFG post-order panic: C:\projects\go_projects\yaegi_test\lib\src\yyy\someapi\mav_api.go:18:13: incomplete type ApiError

goroutine 1 [running]:
github.com/traefik/yaegi/interp.(*Interpreter).cfg.func2.1()
        C:/Users/xxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/cfg.go:601 +0x74
panic({0x14ba5c0?, 0xc0000a4cd8?})
        C:/go/src/runtime/panic.go:770 +0x132
github.com/traefik/yaegi/interp.(*itype).refType(0xc000319400?, 0x16c3a68?)
        C:/Users/xxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/type.go:2047 +0x172c
github.com/traefik/yaegi/interp.(*itype).TypeOf(...)
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/type.go:2196
github.com/traefik/yaegi/interp.isInterface(0xc000319400)
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/type.go:2410 +0x37
github.com/traefik/yaegi/interp.(*itype).equals(0xc0003103c0, 0xc000319400)
        C:/Users/xxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/type.go:1527 +0x45
github.com/traefik/yaegi/interp.(*itype).assignableTo(0xc0003103c0, 0xc000319400)
        C:/Users/xxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/type.go:1453 +0x25
github.com/traefik/yaegi/interp.typecheck.assignment({0xc0000cf0c0?}, 0xc0002ee280, 0x9?, {0x14f9c8c, 0xe})
        C:/Users/xxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/typecheck.go:57 +0x1bd
github.com/traefik/yaegi/interp.typecheck.structLitExpr({0xc0000cf0c8?}, {0xc0000b5bc8, 0x4, 0x10?}, 0xc000319180)
        C:/Users/xxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/typecheck.go:399 +0x1df
github.com/traefik/yaegi/interp.(*Interpreter).cfg.func2(0xc0002eca00)
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/cfg.go:1392 +0x1512
github.com/traefik/yaegi/interp.(*node).Walk(0xc0002eca00, 0xc0000cf980, 0xc0000cf928)
        C:/Users/xxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:294 +0x9e
github.com/traefik/yaegi/interp.(*node).Walk(0xc0002ec780, 0xc0000cf980, 0xc0000cf928)
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:291 +0x6b
github.com/traefik/yaegi/interp.(*node).Walk(0xc0001f3e00, 0xc0000cf980, 0xc0000cf928)
        C:/Users/xxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:291 +0x6b
github.com/traefik/yaegi/interp.(*node).Walk(0xc0001f3680, 0xc0000cf980, 0xc0000cf928)
        C:/Users/xxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:291 +0x6b
github.com/traefik/yaegi/interp.(*node).Walk(0xc0001f2dc0, 0xc0000cf980, 0xc0000cf928)
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:291 +0x6b
github.com/traefik/yaegi/interp.(*Interpreter).cfg(0xc000112908, 0xc0001f2dc0, 0xc0001343f0, {0xc0000b3710, 0x4}, {0xc0000b3710, 0x4})
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/cfg.go:62 +0x29a
github.com/traefik/yaegi/interp.(*Interpreter).CompileAST(0xc000112908, {0x16b5e08?, 0xc0000ab860?})
        C:/Users/xxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/program.go:97 +0x14d
github.com/traefik/yaegi/interp.(*Interpreter).compileSrc(0xc000112908, {0xc00008a500?, 0x100?}, {0xc0000b2088?, 0xc0000a2400?}, 0x0?)
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/program.go:64 +0xaa
github.com/traefik/yaegi/interp.(*Interpreter).eval(0xc000112908, {0xc00008a500?, 0x100?}, {0xc0000b2088?, 0xc0000a2400?}, 0x0?)
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:556 +0x25
github.com/traefik/yaegi/interp.(*Interpreter).EvalPath(0xc000112908, {0xc0000b2088, 0x8})
        C:/Users/xxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:514 +0xa6
main.runFile(0xc000112908, {0xc0000b2088, 0x8}, 0x0)
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/cmd/yaegi/run.go:153 +0xd7
main.run({0xc0000ae3b0, 0x1, 0x1})
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/cmd/yaegi/run.go:116 +0xb65
main.main()
        C:/Users/xxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/cmd/yaegi/yaegi.go:144 +0x2d7

C:\projects\go_projects\yaegi_test>

Yaegi Version

v0.16.1, v0.15.1

Additional Notes

C:\projects\go_projects\yaegi_test>go version go version go1.22.4 windows/amd64

Have only tested this on windows.

saurabh-io commented 1 month ago

An additional finding. If move the ApiError struct definition after the IdpApiResp definition, I get a similar but different error. `package someapi

type IdpApiResp[T any] struct { HttpStatus int json:"httpStatus" Body *T json:"body,omitempty" ErrSource string json:"errSource,omitempty" SomeError ApiError json:"error,omitempty" }

type ApiError struct { XErr string json:"error,omitempty" Desc string json:"error_description,omitempty" } `

yaegi hello.go

`C:\projects\go_projects\yaegi_test>yaegi hello.go panic: C:\projects\go_projects\yaegi_test\lib\src\byyy\someapi\mav_api.go:3:24: incomplete type IdpApiResp[string] [recovered] panic: hello.go:10:7: CFG post-order panic: C:\projects\go_projects\yaegi_test\lib\src\byyy\someapi\mav_api.go:3:24: incomplete type IdpApiResp[string]

goroutine 1 [running]: github.com/traefik/yaegi/interp.(Interpreter).cfg.func2.1() C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/cfg.go:601 +0x74 panic({0x14ba5c0?, 0xc000008c00?}) C:/go/src/runtime/panic.go:770 +0x132 github.com/traefik/yaegi/interp.(itype).frameType(0x0?) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/type.go:2202 +0x1bb github.com/traefik/yaegi/interp.(scope).add(0xc000146480, 0xc000079948?) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/scope.go:210 +0x72 github.com/traefik/yaegi/interp.(Interpreter).cfg.func2(0xc000334b40) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/cfg.go:1408 +0x1565 github.com/traefik/yaegi/interp.(node).Walk(0xc000334b40, 0xc000127980, 0xc000127928) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:294 +0x9e github.com/traefik/yaegi/interp.(node).Walk(0xc0003348c0, 0xc000127980, 0xc000127928) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:291 +0x6b github.com/traefik/yaegi/interp.(node).Walk(0xc000334000, 0xc000127980, 0xc000127928) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:291 +0x6b github.com/traefik/yaegi/interp.(node).Walk(0xc00023b7c0, 0xc000127980, 0xc000127928) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:291 +0x6b github.com/traefik/yaegi/interp.(node).Walk(0xc00023af00, 0xc000127980, 0xc000127928) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:291 +0x6b github.com/traefik/yaegi/interp.(Interpreter).cfg(0xc000162908, 0xc00023af00, 0xc000146480, {0xc00000b770, 0x4}, {0xc00000b770, 0x4}) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/cfg.go:62 +0x29a github.com/traefik/yaegi/interp.(Interpreter).CompileAST(0xc000162908, {0x16b5e08?, 0xc00010d9a0?}) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/program.go:97 +0x14d github.com/traefik/yaegi/interp.(Interpreter).compileSrc(0xc000162908, {0xc0001445a0?, 0x102?}, {0xc00000a0e8?, 0xc000074400?}, 0xa0?) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/program.go:64 +0xaa github.com/traefik/yaegi/interp.(Interpreter).eval(0xc000162908, {0xc0001445a0?, 0x102?}, {0xc00000a0e8?, 0xc000074400?}, 0x60?) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:556 +0x25 github.com/traefik/yaegi/interp.(Interpreter).EvalPath(0xc000162908, {0xc00000a0e8, 0x8}) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/interp/interp.go:514 +0xa6 main.runFile(0xc000162908, {0xc00000a0e8, 0x8}, 0x0) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/cmd/yaegi/run.go:153 +0xd7 main.run({0xc0000783d0, 0x1, 0x1}) C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/cmd/yaegi/run.go:116 +0xb65 main.main() C:/Users/xxxxxxxx/go/pkg/mod/github.com/traefik/yaegi@v0.15.1/cmd/yaegi/yaegi.go:144 +0x2d7

C:\projects\go_projects\yaegi_test>`