From 0dc8fc154b9dbd64a91543357cd92962b49cc4f1 Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 20 Jun 2024 17:41:41 +0800 Subject: [PATCH] parser, checker: fix sorting compare fn with mut reference parameter --- vlib/v/checker/infix.v | 6 +++ vlib/v/parser/fn.v | 16 +++++--- ...rting_compare_fn_with_mut_reference_test.v | 40 +++++++++++++++++++ 3 files changed, 56 insertions(+), 6 deletions(-) create mode 100644 vlib/v/tests/sorting_compare_fn_with_mut_reference_test.v diff --git a/vlib/v/checker/infix.v b/vlib/v/checker/infix.v index 45ddbb73aa8579..36bbab2c580433 100644 --- a/vlib/v/checker/infix.v +++ b/vlib/v/checker/infix.v @@ -203,6 +203,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { .array { if left_sym.kind !in [.sum_type, .interface_] { elem_type := right_final_sym.array_info().elem_type + if node.left.is_auto_deref_var() { + left_type = left_type.deref() + } c.check_expected(left_type, elem_type) or { c.error('left operand to `${node.op}` does not match the array element type: ${err.msg()}', left_right_pos) @@ -214,6 +217,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type { } } else { elem_type := right_final_sym.array_info().elem_type + if node.left.is_auto_deref_var() { + left_type = left_type.deref() + } c.check_expected(left_type, elem_type) or { c.error('left operand to `${node.op}` does not match the array element type: ${err.msg()}', left_right_pos) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 2a353d365c1743..15aeeaeaa6ba28 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -943,11 +943,11 @@ fn (mut p Parser) fn_params() ([]ast.Param, bool, bool) { p.error_with_pos('generic object cannot be `atomic`or `shared`', pos) return []ast.Param{}, false, false } - // if arg_type.is_ptr() { - // p.error('cannot mut') - // } - // arg_type = arg_type.ref() - param_type = param_type.set_nr_muls(1) + if param_type.is_int_valptr() || param_type.has_flag(.option) { + param_type = param_type.set_nr_muls(1) + } else { + param_type = param_type.ref() + } if is_shared { param_type = param_type.set_flag(.shared_f) } @@ -1063,7 +1063,11 @@ fn (mut p Parser) fn_params() ([]ast.Param, bool, bool) { pos) return []ast.Param{}, false, false } - typ = typ.set_nr_muls(1) + if typ.is_int_valptr() || typ.has_flag(.option) { + typ = typ.set_nr_muls(1) + } else { + typ = typ.ref() + } if is_shared { typ = typ.set_flag(.shared_f) } diff --git a/vlib/v/tests/sorting_compare_fn_with_mut_reference_test.v b/vlib/v/tests/sorting_compare_fn_with_mut_reference_test.v new file mode 100644 index 00000000000000..b6362c3ce7124a --- /dev/null +++ b/vlib/v/tests/sorting_compare_fn_with_mut_reference_test.v @@ -0,0 +1,40 @@ +struct Thing { +mut: + a int = 2 + b int = 4 + av int +} + +fn (mut t Thing) average() int { + t.av = (t.a + t.b) / 2 + return t.av +} + +struct Things { +mut: + items []&Thing +} + +fn (mut t Things) sort() { + t.items.sort_with_compare(fn (mut a &Thing, mut b &Thing) int { + if a.average() > b.average() { + return 1 + } else if a.average() < b.average() { + return -1 + } + return 0 + }) +} + +fn test_sort_compare_fn_with_mut_ref_param() { + mut t := Things{} + t.items << &Thing{2, 4, 0} + t.items << &Thing{5, 7, 0} + t.items << &Thing{1, 2, 0} + t.sort() + println(t) + assert t.items.len == 3 + assert t.items[0] == &Thing{1, 2, 1} + assert t.items[1] == &Thing{2, 4, 3} + assert t.items[2] == &Thing{5, 7, 6} +}