checker, cgen: allow static (fixed) arrays in `in` operator (#14121)
parent
c789ea5a15
commit
c5824c36f2
|
@ -662,6 +662,15 @@ pub fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
|
||||||
}
|
}
|
||||||
node.left_type = map_info.key_type
|
node.left_type = map_info.key_type
|
||||||
}
|
}
|
||||||
|
.array_fixed {
|
||||||
|
if left_sym.kind !in [.sum_type, .interface_] {
|
||||||
|
elem_type := right_final.array_fixed_info().elem_type
|
||||||
|
c.check_expected(left_type, elem_type) or {
|
||||||
|
c.error('left operand to `$node.op` does not match the fixed array element type: $err.msg()',
|
||||||
|
left_right_pos)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
else {
|
else {
|
||||||
c.error('`$node.op.str()` can only be used with arrays and maps',
|
c.error('`$node.op.str()` can only be used with arrays and maps',
|
||||||
node.pos)
|
node.pos)
|
||||||
|
|
|
@ -441,6 +441,54 @@ fn (mut g Gen) infix_expr_in_op(node ast.InfixExpr) {
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
}
|
}
|
||||||
g.write(')')
|
g.write(')')
|
||||||
|
} else if right.unaliased_sym.kind == .array_fixed {
|
||||||
|
if left.sym.kind in [.sum_type, .interface_] {
|
||||||
|
if node.right is ast.ArrayInit {
|
||||||
|
if node.right.exprs.len > 0 {
|
||||||
|
mut infix_exprs := []ast.InfixExpr{}
|
||||||
|
for i in 0 .. node.right.exprs.len {
|
||||||
|
infix_exprs << ast.InfixExpr{
|
||||||
|
op: .key_is
|
||||||
|
left: node.left
|
||||||
|
left_type: node.left_type
|
||||||
|
right: node.right.exprs[i]
|
||||||
|
right_type: node.right.expr_types[i]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.write('(')
|
||||||
|
g.infix_expr_in_sumtype_interface_array(infix_exprs)
|
||||||
|
g.write(')')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if node.right is ast.ArrayInit {
|
||||||
|
if node.right.exprs.len > 0 {
|
||||||
|
// `a in [1,2,3]!` optimization => `a == 1 || a == 2 || a == 3`
|
||||||
|
// avoids an allocation
|
||||||
|
g.write('(')
|
||||||
|
g.infix_expr_in_optimization(node.left, node.right)
|
||||||
|
g.write(')')
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if right.sym.info is ast.Array {
|
||||||
|
elem_type := right.sym.info.elem_type
|
||||||
|
elem_type_ := g.unwrap(elem_type)
|
||||||
|
if elem_type_.sym.kind == .sum_type {
|
||||||
|
if node.left_type in elem_type_.sym.sumtype_info().variants {
|
||||||
|
new_node_left := ast.CastExpr{
|
||||||
|
arg: ast.EmptyExpr{}
|
||||||
|
typ: elem_type
|
||||||
|
expr: node.left
|
||||||
|
expr_type: node.left_type
|
||||||
|
}
|
||||||
|
g.gen_array_contains(node.right_type, node.right, new_node_left)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
g.gen_array_contains(node.right_type, node.right, node.left)
|
||||||
} else if right.unaliased_sym.kind == .string {
|
} else if right.unaliased_sym.kind == .string {
|
||||||
g.write('string_contains(')
|
g.write('string_contains(')
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
|
|
|
@ -282,7 +282,7 @@ fn (mut g JsGen) infix_in_not_in_op(node ast.InfixExpr) {
|
||||||
if node.op == .not_in {
|
if node.op == .not_in {
|
||||||
g.write('!')
|
g.write('!')
|
||||||
}
|
}
|
||||||
if r_sym.unaliased_sym.kind == .array {
|
if r_sym.unaliased_sym.kind in [.array, .array_fixed] {
|
||||||
fn_name := g.gen_array_contains_method(node.right_type)
|
fn_name := g.gen_array_contains_method(node.right_type)
|
||||||
g.write('(${fn_name}(')
|
g.write('(${fn_name}(')
|
||||||
g.expr(node.right)
|
g.expr(node.right)
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
fn test_fixed_array_in_op() {
|
||||||
|
assert 1 in [1, 2]!
|
||||||
|
assert `a` in [`a`, `b`]!
|
||||||
|
assert 'a' in ['a', 'b']!
|
||||||
|
|
||||||
|
ch := `"`
|
||||||
|
assert ch in [`"`, `'`]!
|
||||||
|
}
|
Loading…
Reference in New Issue