traefik / yaegi

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

Type system is off for anonymous function fields #1553

Open karelorigin opened 1 year ago

karelorigin commented 1 year ago

The following program sample.go triggers an unexpected result

package main

import (
    "fmt"
)

type T struct {
    Func func(*T)
}

func Assert(w interface{}) error {
    switch v := w.(type) {
    case *T:
        fmt.Println("was of type T:", v)
    default:
        return fmt.Errorf("was of type unknown: %v", v)
    }

    return nil
}

func run() error {
    return Assert(&T{})
}

func main() {
    if err := run(); err != nil {
        fmt.Println("A fatal error occured:", err)
    }
}

Expected result

$ env GO111MODULE=off go run anon-func-issue.go 
was of type T: &{<nil>}

Got

$ ~/go/bin/yaegi anon-func-issue.go 
A fatal error occured: was of type unknown: &{<nil>}

Yaegi Version

v0.15.1

Additional Notes

I believe Yaegi internally creates its own type equivalents, so that may have something to do with it.

mvertes commented 1 year ago

I tested it with yaegi-0.15.1 and the result is correct. I can not reproduce this issue.

karelorigin commented 1 year ago

Seems like my Yaegi binary was still on v0.15.0, sorry about that. Though I initially discovered came across a panic in similar code (from tip), so I figured this was reproducing that issue, but it may be something else entirely.

karelorigin commented 1 year ago

I can't seem to create an easily reproducible sample for some reason. Though this is where the panic occurs:

https://github.com/traefik/yaegi/blob/68a430f969c811146f53e0f039025a7fb0d29342/interp/run.go#L3021-L3024

and this is the message that accompanies it:

panic: reflect.Set: value of type *struct { Embedded struct { Type int }; Func func(*unsafe2.dummy) (bool, error) } is not assignable to type *struct { Embedded struct { Type int }; Func func(*unsafe2.dummy) (bool, error) }

The Func field function signature is something like: func(*T) (bool, error) and the panic disappears when I change it from a concrete type to an interface, such as : func(interface{}) (bool, error).

Hopefully that helps.