Skip to content

Incorrect stack trace line numbering on runtime error with imported types #1717

Description

@SolarLune

The following program sample.go triggers an unexpected result

package main

import (
	"reflect"

	"github.com/traefik/yaegi/interp"
)

type TestInterface interface {
	AFunc()
}

type Test struct{}

func (t *Test) AFunc() {}

func main() {

	exe := interp.New(interp.Options{})

	exe.Use(interp.Exports{
		"exe/exe": map[string]reflect.Value{
			"TestInterface": reflect.ValueOf((*TestInterface)(nil)),
			"Test":          reflect.ValueOf((*Test)(nil)),
		},
	})

	exe.Eval(`
	package main 

	import "exe"

	type Test struct {}
	
	func (t Test) AFunc() {}

	func main() {
		println("main!")
		t()
	}

	func t() {

		println("t")
		var a exe.TestInterface
		a.AFunc() // This is the problematic line, but it's not pointed to

		var b exe.TestInterface = &exe.Test{}
		b.AFunc()
		println("a")
	}
		`)

}

Expected result

main!
t
19:3: panic: main.t(...)
11:3: panic: main.main(...)

Got

main!
t
17:3: panic: main.t(...)
11:3: panic: main.main(...)

Yaegi Version

fcb76d1

Additional Notes

This is a bug that appears when getting a runtime error (for example, a nil-pointer exception) and Yaegi outputs a stack trace as to the bug's location.

Instead of it being the line of the offending statement, it's the beginning of the function that contains the offending statement. I believe this has to do with the runCfg() function in interp/run.go here:

https://github.com/traefik/yaegi/blob/master/interp/run.go#L205

Firstly, I believe the first line, var exec bltn, is never assigned to throughout the function, which makes getting its ownership incorrect. In addition, originalExecNode() is not working properly either, as I think the line that determines original execution (?), here:

https://github.com/traefik/yaegi/blob/master/interp/run.go#L159

seems to test if the built-in function being executed (bltn) is the same type as the offending function, rather than if it's the same function exactly...? Like, it's comparing pointers for the function values themselves, which point to one of a series of functions, so, another line with the same kind of function in the source would trigger this "get original node" code, I think.

I started working on resolving this, but I need some help figuring out exactly what to do, since I'm not super familiar with
AST tree traversal and interpreters.

EDIT: Updated the example with a better one.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions