Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

calling a method in an embedded interface field #1515

Closed
mvertes opened this issue Feb 23, 2023 · 0 comments · Fixed by #1516
Closed

calling a method in an embedded interface field #1515

mvertes opened this issue Feb 23, 2023 · 0 comments · Fixed by #1516
Labels
area/core bug Something isn't working
Milestone

Comments

@mvertes
Copy link
Member

mvertes commented Feb 23, 2023

The following program sample.go triggers an unexpected result

package main

type I1 interface {
    I2
    Wrap() *S3
}

type I2 interface {
    F()
}

type S2 struct {
    I2
}

func newS2(i2 I2) I1 {
    return &S2{i2}
}

type S3 struct {
    base *S2
}

func (s *S2) Wrap() *S3 {
    i2 := s
    return &S3{i2}
}

type T struct {
    name string
}

func (t *T) F() { println("in F", t.name) }

func main() {
    t := &T{"test"}
    s2 := newS2(t)
    s3 := s2.Wrap()
    s3.base.F()
}

Expected result

$ go run ./sample.go
in F test

Got

$ yaegi ./sample.go
./sample.go:36:8: panic
run: reflect: call of reflect.Value.Call on ptr Value
goroutine 1 [running]:
runtime/debug.Stack()
	runtime/debug/stack.go:24 +0x64
github.com/traefik/yaegi/interp.(*Interpreter).Execute.func1()
	github.com/traefik/yaegi/interp/program.go:146 +0x74
panic({0x1014c15c0, 0x140001a5230})
	runtime/panic.go:884 +0x204
github.com/traefik/yaegi/interp.runCfg.func1()
	github.com/traefik/yaegi/interp/run.go:205 +0x11c
panic({0x1014c15c0, 0x140001a5230})
	runtime/panic.go:884 +0x204
reflect.flag.mustBe(...)
	reflect/value.go:221
reflect.Value.Call({0x101582aa0?, 0x140001b5aa0?, 0x140004578a8?}, {0x101acdb30?, 0x14000457858?, 0x100aa9dc8?})
	reflect/value.go:366 +0xf0
github.com/traefik/yaegi/interp.callBin.func2({0x101582aa0?, 0x140001b5aa0?, 0x140004578c8?}, {0x101acdb30?, 0x10150e5a0?, 0x140001b5aa0?})
	github.com/traefik/yaegi/interp/run.go:1506 +0x28
github.com/traefik/yaegi/interp.callBin.func11(0x140001e09a0)
	github.com/traefik/yaegi/interp/run.go:1683 +0x13c
github.com/traefik/yaegi/interp.runCfg(0x1400044db80, 0x140001e09a0, 0x0?, 0x0?)
	github.com/traefik/yaegi/interp/run.go:213 +0x21c
github.com/traefik/yaegi/interp.(*Interpreter).run(0x14000201680, 0x1400044cf00, 0x140001e0790?)
	github.com/traefik/yaegi/interp/run.go:119 +0x3a8
github.com/traefik/yaegi/interp.(*Interpreter).Execute(0x14000201680, 0x14000460a20)
	github.com/traefik/yaegi/interp/program.go:172 +0x1cc
github.com/traefik/yaegi/interp.(*Interpreter).eval(0x14000201680, {0x14000440340?, 0x183?}, {0x16f41b648?, 0x14000440000?}, 0x83?)
	github.com/traefik/yaegi/interp/interp.go:564 +0x64
github.com/traefik/yaegi/interp.(*Interpreter).EvalPath(0x14000201680, {0x16f41b648, 0x1e})
	github.com/traefik/yaegi/interp/interp.go:513 +0xa4
main.runFile(0x16f41b648?, {0x16f41b648, 0x1e}, 0x0)
	github.com/traefik/yaegi/cmd/yaegi/run.go:153 +0xe8
main.run({0x140001b4010?, 0x1, 0x1})
	github.com/traefik/yaegi/cmd/yaegi/run.go:116 +0xb2c
main.main()
	github.com/traefik/yaegi/cmd/yaegi/yaegi.go:144 +0x300

Yaegi Version

v0.15.0

Additional Notes

This issue is related to #1172

@mvertes mvertes added bug Something isn't working area/core labels Feb 23, 2023
mvertes added a commit to mvertes/yaegi that referenced this issue Feb 23, 2023
For methods defined on interfaces (vs concrete methods), the resolution
of the method is necessarily delayed at the run time and can not be
completed at compile time.

The selectorExpr processing has been changed to correctly identify
calls on interface methods which were confused as fields rather
than methods (due to the fact that in a interface definition, methods
are fields of the interface).

Then at runtime, method lookup has been fixed to correctly recurse in
nested valueInterface wrappers and to find embedded interface fields
in case of struct or pointer to structs.

Fixes traefik#1515.
@traefiker traefiker added this to the v0.15.x milestone Mar 6, 2023
traefiker pushed a commit that referenced this issue Mar 6, 2023
For methods defined on interfaces (vs concrete methods), the resolution of the method is necessarily delayed at the run time and can not be completed at compile time.

The selectorExpr processing has been changed to correctly identify calls on interface methods which were confused as fields rather than methods (due to the fact that in a interface definition, methods are fields of the interface).

Then at runtime, method lookup has been fixed to correctly recurse in nested valueInterface wrappers and to find embedded interface fields in case of struct or pointer to struct.

Finally, remove receiver processing in `call()`.The receiver is already processed at method resolution and in genFunctionWrapper. Removing redundant processing in call fixes handling of variadic method, simplifies the code and makes it faster.

With those fixes, it is now possible to load and run `go.uber.org/zap` in yaegi. In turn, it makes possible for yaegi to run plugins dependent on zap, such as coraza-waf.

Fixes #1515, 
Fixes #1172,
Fixes #1275,
Fixes #1485.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
area/core bug Something isn't working
Projects
None yet
Development

Successfully merging a pull request may close this issue.

2 participants