Skip to content

Commit ad49544

Browse files
authored
fix(checker): array type in conditional op (#865)
Correctly handle mixed array types (e.g. `[]int` vs `[][]int`) in ternary expressions by falling back to generic array type when element types differ. Signed-off-by: Ville Vesilehto <[email protected]>
1 parent 5ac4a1a commit ad49544

File tree

3 files changed

+44
-0
lines changed

3 files changed

+44
-0
lines changed

checker/checker.go

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1277,6 +1277,13 @@ func (v *Checker) conditionalNode(node *ast.ConditionalNode) Nature {
12771277
return v.config.NtCache.NatureOf(nil)
12781278
}
12791279
if t1.AssignableTo(t2) {
1280+
if t1.IsArray() && t2.IsArray() {
1281+
e1 := t1.Elem(&v.config.NtCache)
1282+
e2 := t2.Elem(&v.config.NtCache)
1283+
if !e1.AssignableTo(e2) || !e2.AssignableTo(e1) {
1284+
return v.config.NtCache.FromType(arrayType)
1285+
}
1286+
}
12801287
return t1
12811288
}
12821289
return Nature{}

checker/checker_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,7 @@ func TestCheck(t *testing.T) {
134134
{"Bool ?? Bool"},
135135
{"let foo = 1; foo == 1"},
136136
{"(Embed).EmbedPointerEmbedInt > 0"},
137+
{"(true ? [1] : [[1]])[0][0] == 1"},
137138
}
138139

139140
c := new(checker.Checker)

test/issues/819/issue_test.go

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,36 @@
1+
package issue_test
2+
3+
import (
4+
"testing"
5+
6+
"github.com/expr-lang/expr"
7+
"github.com/expr-lang/expr/internal/testify/require"
8+
)
9+
10+
func TestIssue819(t *testing.T) {
11+
t.Run("case 1", func(t *testing.T) {
12+
program, err := expr.Compile(`
13+
let a = [1];
14+
let b = type(a[0]) == 'array' ? a : [a];
15+
b[0][0]
16+
`)
17+
require.NoError(t, err)
18+
19+
out, err := expr.Run(program, nil)
20+
require.NoError(t, err)
21+
require.Equal(t, 1, out)
22+
})
23+
24+
t.Run("case 2", func(t *testing.T) {
25+
program, err := expr.Compile(`
26+
let range = [1,1000];
27+
let arr = false ? range : [range];
28+
map(arr, {len(#)})
29+
`)
30+
require.NoError(t, err)
31+
32+
out, err := expr.Run(program, nil)
33+
require.NoError(t, err)
34+
require.Equal(t, []interface{}{2}, out)
35+
})
36+
}

0 commit comments

Comments
 (0)