Skip to content

cannot fetch Value from *interface #466

@a-peyrard

Description

@a-peyrard

First of all, thanks for you amazing library!

I'm facing some error when I'm using some dynamic unmarshalling of protobuf messages in the program context, the unmarshalled types are interface{} | *interface{} | *<STRUCT CONCRETE TYPE>.
When I'm trying to access a field of the struct, I'm getting the error: cannot fetch Value from *interface{}.

Here is a concrete example where I'm reproducing the error:

func TestExpr_fetch_from_interface(t *testing.T) {
	type FooBar struct {
		Value string
	}
	foobar := &FooBar{"waldo"}
	var foobarAny any = foobar
	var foobarPtrAny any = &foobarAny

	res, err := expr.Eval("foo.Value", map[string]any{
		"foo": foobarPtrAny,
	})
	assert.NoError(t, err)
	assert.Equal(t, "waldo", res)
}

And the error is:

=== RUN   TestExpr_fetch_from_interface
    expr_test.go:1218: 
        	Error Trace:	/opt/dev/go/expr/expr_test.go:1218
        	Error:      	Received unexpected error:
        	            	cannot fetch Value from *interface {} (1:5)
        	            	 | foo.Value
        	            	 | ....^
        	Test:       	TestExpr_fetch_from_interface
    expr_test.go:1219: 
        	Error Trace:	/opt/dev/go/expr/expr_test.go:1219
        	Error:      	Not equal: 
        	            	expected: string("waldo")
        	            	actual  : <nil>(<nil>)
        	Test:       	TestExpr_fetch_from_interface
--- FAIL: TestExpr_fetch_from_interface (0.00s)

This was working fine with v1.12.5 but this not working anymore with v1.15.3.

The error is triggered in the Fetch method, here: https://github.com/antonmedv/expr/blob/5916dc2b68d01606f6c23e1b54da5ee3cd3dc79a/vm/runtime/runtime.go#L76

I'm wondering a simple fix could be to use a deref function like that:

func deref(kind reflect.Kind, value reflect.Value) (reflect.Kind, reflect.Value) {
	for kind == reflect.Ptr || kind == reflect.Interface {
		value = value.Elem()
		kind = value.Kind()
	}
	return kind, value
}

And use it instead of the if block here: https://github.com/antonmedv/expr/blob/5916dc2b68d01606f6c23e1b54da5ee3cd3dc79a/vm/runtime/runtime.go#L28-L34

Thanks for your help.

Happy to submit a PR with the fix if the deref solution is a valid option, or to implement any other idea for the fix.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions