From 5ee963837a2abbf02e3e8f1c47b8f960c9812d2f Mon Sep 17 00:00:00 2001 From: shove Date: Mon, 4 Dec 2023 18:04:43 +0800 Subject: [PATCH] cgen: fix .sort(), and .sorted() method calls, when array aliases are used as receivers (fix #20075) (#20081) --- vlib/v/checker/fn.v | 2 +- vlib/v/gen/c/array.v | 25 +++++++++++++++++++++---- vlib/v/tests/array_methods_test.v | 12 ++++++++++++ 3 files changed, 34 insertions(+), 5 deletions(-) diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index 6d18f2e5dc..993fce0322 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1649,7 +1649,7 @@ fn (mut c Checker) cast_to_fixed_array_ret(typ ast.Type, sym ast.TypeSymbol) ast return typ } -// checks if a type from another module is is expected and visible(`is_pub`) +// checks if a type from another module is as expected and visible(`is_pub`) fn (mut c Checker) check_type_and_visibility(name string, type_idx int, expected_kind &ast.Kind, pos &token.Pos) bool { mut sym := c.table.sym_by_idx(type_idx) if sym.kind == .alias { diff --git a/vlib/v/gen/c/array.v b/vlib/v/gen/c/array.v index abd36a5a83..817b9b53e0 100644 --- a/vlib/v/gen/c/array.v +++ b/vlib/v/gen/c/array.v @@ -590,9 +590,21 @@ fn (mut g Gen) gen_array_sorted(node ast.CallExpr) { info := sym.info as ast.Array depth := g.get_array_depth(info.elem_type) - g.write('${atype} ${past.tmp_var} = array_clone_to_depth(ADDR(${atype},') - g.expr(node.left) - g.writeln('), ${depth});') + deref_field := if node.receiver_type.nr_muls() > node.left_type.nr_muls() + && node.left_type.is_ptr() { + true + } else { + false + } + if !deref_field { + g.write('${atype} ${past.tmp_var} = array_clone_to_depth(ADDR(${atype},') + g.expr(node.left) + g.writeln('), ${depth});') + } else { + g.write('${atype} ${past.tmp_var} = array_clone_to_depth(') + g.expr(node.left) + g.writeln(', ${depth});') + } unsafe { node.left = ast.Expr(ast.Ident{ @@ -708,7 +720,12 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) { } fn (mut g Gen) gen_array_sort_call(node ast.CallExpr, compare_fn string) { - mut deref_field := g.dot_or_ptr(node.left_type) + deref_field := if node.receiver_type.nr_muls() > node.left_type.nr_muls() + && node.left_type.is_ptr() { + g.dot_or_ptr(node.left_type.deref()) + } else { + g.dot_or_ptr(node.left_type) + } // eprintln('> qsort: pointer $node.left_type | deref_field: `$deref_field`') g.empty_line = true g.write('qsort(') diff --git a/vlib/v/tests/array_methods_test.v b/vlib/v/tests/array_methods_test.v index 6f9ad4cd44..f46b2c8e4f 100644 --- a/vlib/v/tests/array_methods_test.v +++ b/vlib/v/tests/array_methods_test.v @@ -73,3 +73,15 @@ fn test_string_eq_method_with_interface() { } assert false } + +// test deref when alias as receiver of methods +type Array = []int + +pub fn (mut arr Array) alias_as_receiver_deref() []int { + return arr.sorted(b < a) +} + +fn test_alias_as_receiver_deref() { + mut arr := Array([1, 2, 3]) + assert arr.alias_as_receiver_deref() == [3, 2, 1] +}