Skip to content

Commit 112fc95

Browse files
authored
parser, checker: fix sorting compare fn with mut reference parameter (fix #21662) (#21706)
1 parent be9d2b6 commit 112fc95

File tree

4 files changed

+58
-7
lines changed

4 files changed

+58
-7
lines changed

vlib/v/ast/str.v

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -210,7 +210,8 @@ fn (t &Table) stringify_fn_after_name(node &FnDecl, mut f strings.Builder, cur_m
210210
mut s := t.type_to_str(param.typ.clear_flag(.shared_f))
211211
if param.is_mut {
212212
if s.starts_with('&') && ((!param_sym.is_number() && param_sym.kind != .bool)
213-
|| node.language != .v) {
213+
|| node.language != .v
214+
|| (param.typ.is_ptr() && t.sym(param.typ).kind == .struct_)) {
214215
s = s[1..]
215216
}
216217
}

vlib/v/checker/infix.v

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -203,6 +203,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
203203
.array {
204204
if left_sym.kind !in [.sum_type, .interface_] {
205205
elem_type := right_final_sym.array_info().elem_type
206+
if node.left.is_auto_deref_var() {
207+
left_type = left_type.deref()
208+
}
206209
c.check_expected(left_type, elem_type) or {
207210
c.error('left operand to `${node.op}` does not match the array element type: ${err.msg()}',
208211
left_right_pos)
@@ -214,6 +217,9 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
214217
}
215218
} else {
216219
elem_type := right_final_sym.array_info().elem_type
220+
if node.left.is_auto_deref_var() {
221+
left_type = left_type.deref()
222+
}
217223
c.check_expected(left_type, elem_type) or {
218224
c.error('left operand to `${node.op}` does not match the array element type: ${err.msg()}',
219225
left_right_pos)

vlib/v/parser/fn.v

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -943,11 +943,11 @@ fn (mut p Parser) fn_params() ([]ast.Param, bool, bool) {
943943
p.error_with_pos('generic object cannot be `atomic`or `shared`', pos)
944944
return []ast.Param{}, false, false
945945
}
946-
// if arg_type.is_ptr() {
947-
// p.error('cannot mut')
948-
// }
949-
// arg_type = arg_type.ref()
950-
param_type = param_type.set_nr_muls(1)
946+
if param_type.is_ptr() && p.table.sym(param_type).kind == .struct_ {
947+
param_type = param_type.ref()
948+
} else {
949+
param_type = param_type.set_nr_muls(1)
950+
}
951951
if is_shared {
952952
param_type = param_type.set_flag(.shared_f)
953953
}
@@ -1063,7 +1063,11 @@ fn (mut p Parser) fn_params() ([]ast.Param, bool, bool) {
10631063
pos)
10641064
return []ast.Param{}, false, false
10651065
}
1066-
typ = typ.set_nr_muls(1)
1066+
if typ.is_ptr() && p.table.sym(typ).kind == .struct_ {
1067+
typ = typ.ref()
1068+
} else {
1069+
typ = typ.set_nr_muls(1)
1070+
}
10671071
if is_shared {
10681072
typ = typ.set_flag(.shared_f)
10691073
}
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
struct Thing {
2+
mut:
3+
a int = 2
4+
b int = 4
5+
av int
6+
}
7+
8+
fn (mut t Thing) average() int {
9+
t.av = (t.a + t.b) / 2
10+
return t.av
11+
}
12+
13+
struct Things {
14+
mut:
15+
items []&Thing
16+
}
17+
18+
fn (mut t Things) sort() {
19+
t.items.sort_with_compare(fn (mut a &Thing, mut b &Thing) int {
20+
if a.average() > b.average() {
21+
return 1
22+
} else if a.average() < b.average() {
23+
return -1
24+
}
25+
return 0
26+
})
27+
}
28+
29+
fn test_sort_compare_fn_with_mut_ref_param() {
30+
mut t := Things{}
31+
t.items << &Thing{2, 4, 0}
32+
t.items << &Thing{5, 7, 0}
33+
t.items << &Thing{1, 2, 0}
34+
t.sort()
35+
println(t)
36+
assert t.items.len == 3
37+
assert t.items[0] == &Thing{1, 2, 1}
38+
assert t.items[1] == &Thing{2, 4, 3}
39+
assert t.items[2] == &Thing{5, 7, 6}
40+
}

0 commit comments

Comments
 (0)