File tree

2 files changed

+54
-4
lines changed

2 files changed

+54
-4
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
package issue_test
2+
3+
import (
4+
"testing"
5+
6+
".com/expr-lang/expr"
7+
".com/expr-lang/expr/internal/testify/require"
8+
)
9+
10+
type Foo interface {
11+
Add(a int, b *int) int
12+
}
13+
14+
type FooImpl struct {
15+
}
16+
17+
func (*FooImpl) Add(a int, b *int) int {
18+
return 0
19+
}
20+
21+
type Env struct {
22+
Foo Foo `expr:"foo"`
23+
}
24+
25+
func (Env) Any(x any) any {
26+
return x
27+
}
28+
29+
func TestNoInterfaceMethodWithNil(t *testing.T) {
30+
program, err := expr.Compile(`foo.Add(1, nil)`)
31+
require.NoError(t, err)
32+
33+
_, err = expr.Run(program, Env{Foo: &FooImpl{}})
34+
require.NoError(t, err)
35+
}
36+
37+
func TestNoInterfaceMethodWithNil_with_env(t *testing.T) {
38+
program, err := expr.Compile(`foo.Add(1, nil)`, expr.Env(Env{}))
39+
require.NoError(t, err)
40+
41+
_, err = expr.Run(program, Env{Foo: &FooImpl{}})
42+
require.NoError(t, err)
43+
}
44+
45+
func TestNoInterfaceMethodWithNil_with_any(t *testing.T) {
46+
program, err := expr.Compile(`Any(nil)`, expr.Env(Env{}))
47+
require.NoError(t, err)
48+
49+
out, err := expr.Run(program, Env{Foo: &FooImpl{}})
50+
require.NoError(t, err)
51+
require.Equal(t, nil, out)
52+
}
Original file line numberDiff line numberDiff line change
@@ -334,10 +334,8 @@ func (vm *VM) Run(program *Program, env any) (_ any, err error) {
334334
in := make([]reflect.Value, size)
335335
for i := int(size) - 1; i >= 0; i-- {
336336
param := vm.pop()
337-
if param == nil && reflect.TypeOf(param) == nil {
338-
// In case of nil value and nil type use this hack,
339-
// otherwise reflect.Call will panic on zero value.
340-
in[i] = reflect.ValueOf(&param).Elem()
337+
if param == nil {
338+
in[i] = reflect.Zero(fn.Type().In(i))
341339
} else {
342340
in[i] = reflect.ValueOf(param)
343341
}

0 commit comments

Comments
 (0)