Skip to content

Commit c8286b1

Browse files
committed
v3: fix array map origins and comparator types
1 parent 9937a49 commit c8286b1

3 files changed

Lines changed: 82 additions & 3 deletions

File tree

vlib/v/tests/builtin_arrays/sorting_compare_fn_with_mut_reference_test.v

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,16 @@ fn test_sort_compare_local_fn_with_pointer_values() {
6060
assert items.map(it.a) == [1, 2, 3]
6161
}
6262

63+
fn get_thing_comparator() fn (&Thing, &Thing) int {
64+
return compare_thing_values
65+
}
66+
67+
fn test_sort_compare_call_fn_with_pointer_values() {
68+
mut items := [&Thing{a: 3}, &Thing{a: 1}, &Thing{a: 2}]
69+
items.sort_with_compare(get_thing_comparator())
70+
assert items.map(it.a) == [1, 2, 3]
71+
}
72+
6373
struct ThingComparators {
6474
@[required]
6575
compare fn (&Thing, &Thing) int

vlib/v3/tests/review_transform_regressions_test.v

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5592,6 +5592,37 @@ fn main() {
55925592
assert out == '4\n42'
55935593
}
55945594

5595+
fn test_array_map_drops_source_for_unselected_literal_element_pointer() {
5596+
v3_bin := build_v3_review_transform_ownership()
5597+
source := 'struct Item {
5598+
text string
5599+
}
5600+
5601+
fn make_items() []Item {
5602+
return [Item{
5603+
text: "source"
5604+
}]
5605+
}
5606+
5607+
fn main() {
5608+
external := Item{
5609+
text: "external"
5610+
}
5611+
selected := make_items().map([&it, &external][1])
5612+
println(selected[0].text)
5613+
}
5614+
'
5615+
c_source := gen_c_from_source_with_flags(v3_bin, 'array_map_selected_external_pointer_c',
5616+
'-ownership', source)
5617+
main_body := c_fn_body(c_source, 'int main(int argc, char** argv) {')
5618+
source_drop_pos := main_body.index('array__free(&(') or { -1 }
5619+
result_move_pos := main_body.index('Array selected = ') or { -1 }
5620+
assert source_drop_pos >= 0 && source_drop_pos < result_move_pos, main_body
5621+
out := run_good_with_flags(v3_bin, 'array_map_selected_external_pointer', '-ownership',
5622+
source)
5623+
assert out == 'external'
5624+
}
5625+
55955626
fn test_array_filter_and_map_reclaim_branch_selected_bound_methods() {
55965627
v3_bin := build_v3_review_transform()
55975628
source := '@[heap]

vlib/v3/transform/array.v

Lines changed: 41 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2832,8 +2832,7 @@ fn (mut t Transformer) array_map_expr_result_retains_element_address(id flat.Nod
28322832
node.value, name)
28332833
}
28342834
.index {
2835-
return node.children_count > 0
2836-
&& t.array_map_expr_result_retains_element_address(t.a.child(&node, 0), name)
2835+
return t.array_map_index_result_retains_element_address(node, name)
28372836
}
28382837
.call {
28392838
call_type := t.checker_expr_type_name(id) or { t.node_type(id) }
@@ -2861,6 +2860,25 @@ fn (mut t Transformer) array_map_expr_result_retains_element_address(id flat.Nod
28612860
}
28622861
}
28632862

2863+
fn (mut t Transformer) array_map_index_result_retains_element_address(node flat.Node, name string) bool {
2864+
if node.children_count == 0 {
2865+
return false
2866+
}
2867+
base_id := t.a.child(&node, 0)
2868+
if node.children_count > 1 {
2869+
base := t.a.nodes[int(base_id)]
2870+
index := t.a.child_node(&node, 1)
2871+
if base.kind == .array_literal && index.kind == .int_literal {
2872+
selected := index.value.int()
2873+
if selected >= 0 && selected < int(base.children_count) {
2874+
return t.array_map_expr_result_retains_element_address(t.a.child(&base, selected),
2875+
name)
2876+
}
2877+
}
2878+
}
2879+
return t.array_map_expr_result_retains_element_address(base_id, name)
2880+
}
2881+
28642882
fn (mut t Transformer) array_map_selector_result_retains_element_address(base_id flat.NodeId, field_name string, elem_name string) bool {
28652883
if int(base_id) < 0 || int(base_id) >= t.a.nodes.len {
28662884
return false
@@ -3583,11 +3601,31 @@ fn (mut t Transformer) stable_array_compare_fn(cmp_id flat.NodeId, elem_type str
35833601
if int(cmp_id) >= 0 && t.a.nodes[int(cmp_id)].kind == .lambda_expr {
35843602
return cmp_id
35853603
}
3604+
cmp_type := t.array_compare_fn_type(cmp_id, elem_type)
35863605
cmp := t.transform_expr(cmp_id)
3587-
cmp_type := 'fn (&${elem_type}, &${elem_type}) int'
35883606
return t.stable_transformed_expr_for_reuse(cmp, cmp_type, 'sort_cmp')
35893607
}
35903608

3609+
fn (t &Transformer) array_compare_fn_type(cmp_id flat.NodeId, elem_type string) string {
3610+
default_type := 'fn (&${elem_type}, &${elem_type}) int'
3611+
if isnil(t.tc) || int(cmp_id) < 0 || int(cmp_id) >= t.a.nodes.len {
3612+
return default_type
3613+
}
3614+
cmp_node := t.a.nodes[int(cmp_id)]
3615+
raw_type := if cmp_node.kind == .ident {
3616+
t.raw_var_type(cmp_node.value)
3617+
} else {
3618+
t.raw_checker_node_type(cmp_id)
3619+
}
3620+
if raw_type.len == 0 {
3621+
return default_type
3622+
}
3623+
if types.unalias_type(t.tc.parse_type(raw_type)) is types.FnType {
3624+
return raw_type
3625+
}
3626+
return default_type
3627+
}
3628+
35913629
// make_array_default_sort_stmt builds make array default sort stmt data for transform.
35923630
fn (mut t Transformer) make_array_default_sort_stmt(base flat.NodeId, elem_type string, src flat.Node, cmp_id flat.NodeId) flat.NodeId {
35933631
if int(cmp_id) < 0 {

0 commit comments

Comments
 (0)