From bc7a844a64dee290855b603297918e72d3cb0ecc Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Mon, 9 Dec 2024 15:34:18 -0300 Subject: [PATCH] v: allow option array element comparison `==` and `!=` (fix #23108) (#23113) --- vlib/v/checker/infix.v | 6 +++--- vlib/v/gen/c/infix.v | 16 +++++++++++++++- vlib/v/tests/options/option_indexexpr_eq_test.v | 7 +++++++ 3 files changed, 25 insertions(+), 4 deletions(-) create mode 100644 vlib/v/tests/options/option_indexexpr_eq_test.v diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 8e63a122d..fbbde3a3e 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -897,9 +897,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { right_is_option := right_type.has_flag(.option) if left_is_option || right_is_option { opt_infix_pos := if left_is_option { left_pos } else { right_pos } - if (node.left !in [ast.Ident, ast.SelectorExpr, ast.ComptimeSelector] - || node.op in [.eq, .ne, .lt, .gt, .le, .ge]) && right_sym.kind != .none - && !c.inside_sql { + if (node.left !in [ast.Ident, ast.IndexExpr, ast.SelectorExpr, ast.ComptimeSelector] + || (node.op in [.eq, .ne] && !right_is_option) + || node.op in [.lt, .gt, .le, .ge]) && right_sym.kind != .none && !c.inside_sql { c.error('unwrapped Option cannot be used in an infix expression', opt_infix_pos) } } diff --git a/vlib/v/gen/c/infix.v b/vlib/v/gen/c/infix.v index 50a05be6d..9a50f45c6 100644 --- a/vlib/v/gen/c/infix.v +++ b/vlib/v/gen/c/infix.v @@ -112,7 +112,9 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) { g.gen_plain_infix_expr(node) return } - is_none_check := left_type.has_flag(.option) && node.right is ast.None + left_is_option := left_type.has_flag(.option) + right_is_option := right_type.has_flag(.option) + is_none_check := left_is_option && node.right is ast.None if is_none_check { g.gen_is_none_check(node) } else if (left.typ.is_ptr() && right.typ.is_int()) @@ -367,6 +369,18 @@ fn (mut g Gen) infix_expr_eq_op(node ast.InfixExpr) { signed_type: left.unaliased signed_expr: node.left ) + } else if left_is_option && right_is_option { + old_inside_opt_or_res := g.inside_opt_or_res + g.inside_opt_or_res = true + if node.op == .eq { + g.write('!') + } + g.write('memcmp(') + g.expr(node.left) + g.write('.data, ') + g.expr(node.right) + g.write('.data, sizeof(${g.base_type(left_type)}))') + g.inside_opt_or_res = old_inside_opt_or_res } else { g.gen_plain_infix_expr(node) } diff --git a/vlib/v/tests/options/option_indexexpr_eq_test.v b/vlib/v/tests/options/option_indexexpr_eq_test.v new file mode 100644 index 000000000..b5ebf53ac --- /dev/null +++ b/vlib/v/tests/options/option_indexexpr_eq_test.v @@ -0,0 +1,7 @@ +fn test_main() { + x := []?int{len: 5, init: 1} + assert x[0] == x[1] + + y := []?int{len: 4, init: 2} + assert !(x[0] == y[1]) +} -- 2.39.5