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

Third-party imported type method is not callable from fast.Interp.Eval [gomacro repl works] #142

Closed
Skird opened this issue Feb 6, 2023 · 4 comments
Assignees
Labels

Comments

@Skird
Copy link

Skird commented Feb 6, 2023

Hi, thanks for cool package!
I was playing around with it and got the following strange problem.

Small example here

package main

import (
	"fmt"
	"github.com/cosmos72/gomacro/fast"
	"github.com/holiman/uint256"
)

func main() {
	code := `
import (
	"github.com/holiman/uint256"
)
func Foo(x *uint256.Int) int {
	return x.Sign()
}
`
	interp := fast.New()
	interp.Eval(code)
	foo := interp.ValueOf("Foo").Interface().(func(*uint256.Int) int)

	y := uint256.NewInt(123)
	fmt.Println(foo(y))
}

It seems I'm successfully importing the library but when I'm trying to use any of uint256.Int methods I get an error.

// debug: running "go get github.com/holiman/uint256" ...
go: added github.com/holiman/uint256 v1.2.1
// debug: running "go mod tidy" ...
// debug: compiling plugin "/home/divashchenko/go/src/gomacro.imports/gomacro_pid_106507/import_1" ...
panic: repl.go:6:9: type *github.com/holiman/uint256.Int has no field or method "Sign": x.Sign [recovered]
        panic: repl.go:6:9: not a package: "x" in x.Sign <*ast.SelectorExpr>

goroutine 1 [running]:
github.com/cosmos72/gomacro/base/output.(*Stringer).Errorf(...)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/base/output/output.go:96
github.com/cosmos72/gomacro/fast.(*Comp).compileType2(0xc0001cc540, {0x1a58910?, 0xc0004c04b0?}, 0x0)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/type.go:248 +0x1447
github.com/cosmos72/gomacro/fast.(*Comp).Type(...)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/type.go:148
github.com/cosmos72/gomacro/fast.(*Comp).Expr1OrType.func1()
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/expr.go:206 +0x65
panic({0x177dea0, 0xc000276bd0})
        /usr/lib/go-1.19/src/runtime/panic.go:884 +0x212
github.com/cosmos72/gomacro/base/output.(*Stringer).Errorf(...)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/base/output/output.go:96
github.com/cosmos72/gomacro/fast.(*Comp).SelectorExpr(0xc0001cc540, 0xc0004c04b0)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/selector.go:74 +0x914
github.com/cosmos72/gomacro/fast.(*Comp).expr(0xc0001cc540, {0x1a58910?, 0xc0004c04b0?}, 0x1645220?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/expr.go:150 +0x145
github.com/cosmos72/gomacro/fast.(*Comp).expr1(0xc0001cc540, {0x1a58910?, 0xc0004c04b0?}, 0x82?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/expr.go:101 +0x174
github.com/cosmos72/gomacro/fast.(*Comp).Expr1(...)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/expr.go:73
github.com/cosmos72/gomacro/fast.(*Comp).Expr1OrType(0x1645220?, {0x1a58910?, 0xc0004c04b0?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/expr.go:209 +0x21f
github.com/cosmos72/gomacro/fast.(*Comp).CallExpr(0x100c000276b70?, 0xc0003b3a80)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/call.go:64 +0x47
github.com/cosmos72/gomacro/fast.(*Comp).expr(0xc0001cc540, {0x1a58370?, 0xc0003b3a80?}, 0x7fea512365b8?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/expr.go:134 +0x345
github.com/cosmos72/gomacro/fast.(*Comp).expr1(0xc0001cc540, {0x1a58370?, 0xc0003b3a80?}, 0x1?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/expr.go:101 +0x174
github.com/cosmos72/gomacro/fast.(*Comp).exprs(0x203000?, {0xc0003b7630, 0x1, 0x21e2920?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/expr.go:63 +0x99
github.com/cosmos72/gomacro/fast.(*Comp).Return(0x1a588b0?, 0xc0004b8920)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/statement.go:614 +0xe6
github.com/cosmos72/gomacro/fast.(*Comp).Stmt(0xc0001cc540, {0x1a588b0?, 0xc0004b8920?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/statement.go:102 +0x486
github.com/cosmos72/gomacro/fast.(*Comp).DeclFunc(0xc0001cc3c0, 0xc0004c4330)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/function.go:91 +0x768
github.com/cosmos72/gomacro/fast.(*Comp).Decl(0xc0001cc3c0?, {0x1a58580, 0xc0004c4330?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/declaration.go:41 +0xb3
github.com/cosmos72/gomacro/fast.(*Comp).compileNode(0xc0001cc3c0, {0x1a56218?, 0xc0004c4330?}, 0x3)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/compile.go:449 +0x1fe
github.com/cosmos72/gomacro/fast.(*Comp).compileDecl(0xc0001cc3c0?, 0xc0003b3b00?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/compile.go:415 +0x1f0
github.com/cosmos72/gomacro/fast.(*Comp).Compile(0xc0001cc3c0, {0x1a5d180, 0xc0004c0420})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/compile.go:375 +0x4b0
github.com/cosmos72/gomacro/fast.(*Interp).CompileAst(0xc0003b7520?, {0x1a5d180?, 0xc0004c0420?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/repl.go:95 +0x12b
github.com/cosmos72/gomacro/fast.(*Interp).Compile(0x1802f29?, {0x1848ae6?, 0x1802f29?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/repl.go:75 +0x35
github.com/cosmos72/gomacro/fast.(*Interp).Eval(0x8dc79c?, {0x1848ae6?, 0x8df1d9?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/interpreter.go:261 +0x25
main.main()
        /home/divashchenko/workspace/tmp/goplay/main.go:19 +0x33

I also tried using interp.DeclType to introduce uint256.Int type from host to interpreter, with same result. However, if I create uint256.NewInt(123) in interpreter and use methods in host code it works.

I tried the same approach with another simple library github.com/bits-and-blooms/bitset and it worked.

That makes me think that problem is connected with type aliases (as it's declared as type Int [4]uint64).

Is this case not supported? Is there any workaround for that?

@Skird
Copy link
Author

Skird commented Feb 7, 2023

One more interesting example from attempted workaround

package main

import (
	"fmt"
	"github.com/cosmos72/gomacro/fast"
	"github.com/holiman/uint256"
)

func main() {
	code := `
import (
	"github.com/holiman/uint256"
)

sign := uint256.Int.Sign

func Foo(x *uint256.Int) int {
	return sign(x)
}
`
	interp := fast.New()
	interp.Eval(code)

	foo := interp.ValueOf("Foo").Interface().(func(int2 *uint256.Int) int)

	z := uint256.NewInt(123)
	fmt.Println(foo(z))
}

Fails with

// debug: running "go get github.com/holiman/uint256" ...
go: added github.com/holiman/uint256 v1.2.1
// debug: running "go mod tidy" ...
// debug: compiling plugin "/home/divashchenko/go/src/gomacro.imports/gomacro_pid_37124/import_1" ...
panic: reflect.Value.Addr of unaddressable value

goroutine 1 [running]:
reflect.Value.Addr({0x17fe4e0?, 0xc0002cb2c0?, 0x1?})
        /usr/lib/go-1.19/src/reflect/value.go:271 +0x65
github.com/cosmos72/gomacro/xreflect.Value.Addr(...)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/xreflect/value.go:114
github.com/cosmos72/gomacro/fast.(*Comp).compileMethodAsFunc.func6({0xc0005965d0?, 0x1, 0x1})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/selector.go:909 +0xbc
github.com/cosmos72/gomacro/xreflect.MakeFunc.func1({0xc0005965b8, 0x1, 0x1?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/xreflect/wrap.go:39 +0xaa
reflect.Value.call({0x1658c20?, 0xc0002fbf70?, 0x7f3bfc913a68?}, {0x18027ed, 0x4}, {0xc0005965a0, 0x1, 0x1658c20?})
        /usr/lib/go-1.19/src/reflect/value.go:584 +0x8c5
reflect.Value.Call({0x1658c20?, 0xc0002fbf70?, 0xc0002b7830?}, {0xc0005965a0?, 0x100000000000475?, 0xc000197760?})
        /usr/lib/go-1.19/src/reflect/value.go:368 +0xbc
github.com/cosmos72/gomacro/xreflect.Value.Call({{0x1658c20?, 0xc0002fbf70?, 0x0?}}, {0xc000596588, 0x1, 0x92ddd2?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/xreflect/value.go:127 +0x113
github.com/cosmos72/gomacro/fast.callxr({{0x1658c20?, 0xc0002fbf70?, 0xc0002cb2c0?}}, {0xc000596588, 0x1, 0x1})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/call.go:453 +0x8e
github.com/cosmos72/gomacro/fast.(*Comp).callnret1.func2(0x17fe4e0?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/callnret1.go:58 +0xee
github.com/cosmos72/gomacro/fast.(*Comp).varSetExpr.func3(0xc0001da320)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/var_set.go:2344 +0x2f
github.com/cosmos72/gomacro/fast.exec.func1(0xc0001da320?)
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/code.go:171 +0x236
github.com/cosmos72/gomacro/fast.(*Comp).funcGeneric.func2.1({0xc000596540, 0x1, 0x0?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/fast/function.go:438 +0xf0
github.com/cosmos72/gomacro/xreflect.MakeFunc.func1({0xc000596528, 0x1, 0x1?})
        /home/divashchenko/go/pkg/mod/github.com/cosmos72/gomacro@v0.0.0-20230110102113-12bd30aad33f/xreflect/wrap.go:39 +0xaa
main.main()
        /home/divashchenko/workspace/tmp/goplay/main.go:33 +0x7e

It seems that in fast/selector.go:843 it falls into wrong branch (with comment // method declared by interpreted code, manually retrieve it.). In following snippet

var x uint256.Int
interp := fast.New()
typ := interp.TypeOf(x)
fmt.Println(typ.ReflectType().NumMethod())

something strange happens with typ.ReflectType(), it has NumMethods() == 0.
Tried to dig into it a bit more with no luck, but I hope it hepls :)

@cosmos72
Copy link
Owner

cosmos72 commented Jan 7, 2024

Sorry for the very late answer.

Yes, it's definitely strange because running the same code directly from gomacro repl works:

import "github.com/holiman/uint256"

func Foo(x *uint256.Int) int {
	return x.Sign()
}

y := uint256.NewInt(123)
Foo(y)

produces the following output:

// debug: running "go get github.com/holiman/uint256" ...
go: added github.com/holiman/uint256 v1.2.4
// debug: running "go mod tidy" ...
// debug: compiling plugin "/home/max/go/src/gomacro.imports/gomacro_pid_17289/import_1" ...
1       // int

@cosmos72 cosmos72 self-assigned this Jan 7, 2024
@cosmos72 cosmos72 added the bug label Jan 7, 2024
@cosmos72 cosmos72 changed the title Thrid-party imported type methods are not callable Thrid-party imported type method is not callable from fast.Interp.Eval [gomacro repl works] Jan 7, 2024
@cosmos72 cosmos72 changed the title Thrid-party imported type method is not callable from fast.Interp.Eval [gomacro repl works] Third-party imported type method is not callable from fast.Interp.Eval [gomacro repl works] Jan 7, 2024
@cosmos72
Copy link
Owner

cosmos72 commented Jan 7, 2024

I am debugging this issue, and it's specific to methods attached to non-struct types.

Package github.com/holiman/uint256 defines type Int as follows:

type Int [4]uint64

then defines methods with pointer receiver *Int, as for example

func (z *Int) Sign() int {
  // ...
}

Which is perfectly legal, but less tested in gomacro than methods attached to structs.

Continuing the analysis...

cosmos72 added a commit that referenced this issue Jan 7, 2024
…y types, named slice types, and all other named non-struct types

if generics v2 are disabled
@cosmos72
Copy link
Owner

cosmos72 commented Jan 7, 2024

Fixed in commit 960f329

It was a bug in method lookup: it checked for types that cannot have methods and failed early in such case,
but the logic for the early failure was bugged and worked by chance only if experimental generics were enabled.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

2 participants