Skip to content

Commit 0354d1b

Browse files
committed
Only emit OpEqual{Int,String} for simple types
Fixes #461
1 parent d27e5a3 commit 0354d1b

File tree

2 files changed

+97
-2
lines changed

2 files changed

+97
-2
lines changed

compiler/compiler.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -360,16 +360,20 @@ func (c *compiler) BinaryNode(node *ast.BinaryNode) {
360360
l := kind(node.Left)
361361
r := kind(node.Right)
362362

363+
leftIsSimple := isSimpleType(node.Left)
364+
rightIsSimple := isSimpleType(node.Right)
365+
leftAndRightAreSimple := leftIsSimple && rightIsSimple
366+
363367
switch node.Operator {
364368
case "==":
365369
c.compile(node.Left)
366370
c.derefInNeeded(node.Left)
367371
c.compile(node.Right)
368372
c.derefInNeeded(node.Left)
369373

370-
if l == r && l == reflect.Int {
374+
if l == r && l == reflect.Int && leftAndRightAreSimple {
371375
c.emit(OpEqualInt)
372-
} else if l == r && l == reflect.String {
376+
} else if l == r && l == reflect.String && leftAndRightAreSimple {
373377
c.emit(OpEqualString)
374378
} else {
375379
c.emit(OpEqual)
@@ -534,6 +538,17 @@ func (c *compiler) BinaryNode(node *ast.BinaryNode) {
534538
}
535539
}
536540

541+
func isSimpleType(node ast.Node) bool {
542+
if node == nil {
543+
return false
544+
}
545+
t := node.Type()
546+
if t == nil {
547+
return false
548+
}
549+
return t.PkgPath() == ""
550+
}
551+
537552
func (c *compiler) ChainNode(node *ast.ChainNode) {
538553
c.chains = append(c.chains, []int{})
539554
c.compile(node.Node)

expr_test.go

Lines changed: 80 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2022,3 +2022,83 @@ func TestIssue453(t *testing.T) {
20222022
_, err := expr.Compile(`foo()`, expr.Env(env))
20232023
require.Error(t, err)
20242024
}
2025+
2026+
func TestIssue461(t *testing.T) {
2027+
type EnvStr string
2028+
type EnvField struct {
2029+
S EnvStr
2030+
Str string
2031+
}
2032+
type Env struct {
2033+
S EnvStr
2034+
Str string
2035+
EnvField EnvField
2036+
}
2037+
var tests = []struct {
2038+
input string
2039+
env Env
2040+
want bool
2041+
}{
2042+
{
2043+
input: "Str == S",
2044+
env: Env{S: "string", Str: "string"},
2045+
want: false,
2046+
},
2047+
{
2048+
input: "Str == Str",
2049+
env: Env{Str: "string"},
2050+
want: true,
2051+
},
2052+
{
2053+
input: "S == S",
2054+
env: Env{Str: "string"},
2055+
want: true,
2056+
},
2057+
{
2058+
input: `Str == "string"`,
2059+
env: Env{Str: "string"},
2060+
want: true,
2061+
},
2062+
{
2063+
input: `S == "string"`,
2064+
env: Env{Str: "string"},
2065+
want: false,
2066+
},
2067+
{
2068+
input: "EnvField.Str == EnvField.S",
2069+
env: Env{EnvField: EnvField{S: "string", Str: "string"}},
2070+
want: false,
2071+
},
2072+
{
2073+
input: "EnvField.Str == EnvField.Str",
2074+
env: Env{EnvField: EnvField{Str: "string"}},
2075+
want: true,
2076+
},
2077+
{
2078+
input: "EnvField.S == EnvField.S",
2079+
env: Env{EnvField: EnvField{Str: "string"}},
2080+
want: true,
2081+
},
2082+
{
2083+
input: `EnvField.Str == "string"`,
2084+
env: Env{EnvField: EnvField{Str: "string"}},
2085+
want: true,
2086+
},
2087+
{
2088+
input: `EnvField.S == "string"`,
2089+
env: Env{EnvField: EnvField{Str: "string"}},
2090+
want: false,
2091+
},
2092+
}
2093+
2094+
for _, tt := range tests {
2095+
t.Run(tt.input, func(t *testing.T) {
2096+
program, err := expr.Compile(tt.input, expr.Env(tt.env), expr.AsBool())
2097+
2098+
out, err := expr.Run(program, tt.env)
2099+
require.NoError(t, err)
2100+
2101+
require.Equal(t, tt.want, out)
2102+
})
2103+
}
2104+
}

0 commit comments

Comments
 (0)