Skip to content

Commit c5824c3

Browse files
authored
checker, cgen: allow static (fixed) arrays in in operator (#14121)
1 parent c789ea5 commit c5824c3

File tree

4 files changed

+66
-1
lines changed

4 files changed

+66
-1
lines changed

vlib/v/checker/checker.v

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -662,6 +662,15 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
662662
}
663663
node.left_type = map_info.key_type
664664
}
665+
.array_fixed {
666+
if left_sym.kind !in [.sum_type, .interface_] {
667+
elem_type := right_final.array_fixed_info().elem_type
668+
c.check_expected(left_type, elem_type) or {
669+
c.error('left operand to `$node.op` does not match the fixed array element type: $err.msg()',
670+
left_right_pos)
671+
}
672+
}
673+
}
665674
else {
666675
c.error('`$node.op.str()` can only be used with arrays and maps',
667676
node.pos)

vlib/v/gen/c/infix.v

Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -441,6 +441,54 @@ fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
441441
g.expr(node.right)
442442
}
443443
g.write(')')
444+
} else if right.unaliased_sym.kind == .array_fixed {
445+
if left.sym.kind in [.sum_type, .interface_] {
446+
if node.right is ast.ArrayInit {
447+
if node.right.exprs.len > 0 {
448+
mut infix_exprs := []ast.InfixExpr{}
449+
for i in 0 .. node.right.exprs.len {
450+
infix_exprs << ast.InfixExpr{
451+
op: .key_is
452+
left: node.left
453+
left_type: node.left_type
454+
right: node.right.exprs[i]
455+
right_type: node.right.expr_types[i]
456+
}
457+
}
458+
g.write('(')
459+
g.infix_expr_in_sumtype_interface_array(infix_exprs)
460+
g.write(')')
461+
return
462+
}
463+
}
464+
}
465+
if node.right is ast.ArrayInit {
466+
if node.right.exprs.len > 0 {
467+
// `a in [1,2,3]!` optimization => `a == 1 || a == 2 || a == 3`
468+
// avoids an allocation
469+
g.write('(')
470+
g.infix_expr_in_optimization(node.left, node.right)
471+
g.write(')')
472+
return
473+
}
474+
}
475+
if right.sym.info is ast.Array {
476+
elem_type := right.sym.info.elem_type
477+
elem_type_ := g.unwrap(elem_type)
478+
if elem_type_.sym.kind == .sum_type {
479+
if node.left_type in elem_type_.sym.sumtype_info().variants {
480+
new_node_left := ast.CastExpr{
481+
arg: ast.EmptyExpr{}
482+
typ: elem_type
483+
expr: node.left
484+
expr_type: node.left_type
485+
}
486+
g.gen_array_contains(node.right_type, node.right, new_node_left)
487+
return
488+
}
489+
}
490+
}
491+
g.gen_array_contains(node.right_type, node.right, node.left)
444492
} else if right.unaliased_sym.kind == .string {
445493
g.write('string_contains(')
446494
g.expr(node.right)

vlib/v/gen/js/infix.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,7 +282,7 @@ fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
282282
if node.op == .not_in {
283283
g.write('!')
284284
}
285-
if r_sym.unaliased_sym.kind == .array {
285+
if r_sym.unaliased_sym.kind in [.array, .array_fixed] {
286286
fn_name := g.gen_array_contains_method(node.right_type)
287287
g.write('(${fn_name}(')
288288
g.expr(node.right)

vlib/v/tests/fixed_array_in_op_test.v

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,8 @@
1+
fn test_fixed_array_in_op() {
2+
assert 1 in [1, 2]!
3+
assert `a` in [`a`, `b`]!
4+
assert 'a' in ['a', 'b']!
5+
6+
ch := `"`
7+
assert ch in [`"`, `'`]!
8+
}

0 commit comments

Comments
 (0)