cgen: fix .sort(), and .sorted() method calls, when array aliases are used as receivers (fix #20075) (#20081)

This commit is contained in:
shove 2023-12-04 18:04:43 +08:00 committed by GitHub
parent 4a37403a30
commit 5ee963837a
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 34 additions and 5 deletions

View file

@ -1649,7 +1649,7 @@ fn (mut c Checker) cast_to_fixed_array_ret(typ ast.Type, sym ast.TypeSymbol) ast
return typ 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 { 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) mut sym := c.table.sym_by_idx(type_idx)
if sym.kind == .alias { if sym.kind == .alias {

View file

@ -590,9 +590,21 @@ fn (mut g Gen) gen_array_sorted(node ast.CallExpr) {
info := sym.info as ast.Array info := sym.info as ast.Array
depth := g.get_array_depth(info.elem_type) depth := g.get_array_depth(info.elem_type)
g.write('${atype} ${past.tmp_var} = array_clone_to_depth(ADDR(${atype},') deref_field := if node.receiver_type.nr_muls() > node.left_type.nr_muls()
g.expr(node.left) && node.left_type.is_ptr() {
g.writeln('), ${depth});') 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 { unsafe {
node.left = ast.Expr(ast.Ident{ 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) { 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`') // eprintln('> qsort: pointer $node.left_type | deref_field: `$deref_field`')
g.empty_line = true g.empty_line = true
g.write('qsort(') g.write('qsort(')

View file

@ -73,3 +73,15 @@ fn test_string_eq_method_with_interface() {
} }
assert false 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]
}