Skip to content

Commit ab8a9a4

Browse files
committed
v3: preserve array callback pointer origins
1 parent a6d5fa5 commit ab8a9a4

2 files changed

Lines changed: 126 additions & 18 deletions

File tree

vlib/v3/tests/review_transform_regressions_test.v

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5574,6 +5574,45 @@ fn main() {
55745574
assert !main_body.contains('array__free(&(__map_source_'), main_body
55755575
}
55765576

5577+
fn test_array_map_keeps_temporary_source_through_local_result_alias() {
5578+
v3_bin := build_v3_review_transform_ownership()
5579+
source := 'struct Item {
5580+
text string
5581+
}
5582+
5583+
fn make_items() []Item {
5584+
return [Item{
5585+
text: "source"
5586+
}]
5587+
}
5588+
5589+
fn main() {
5590+
external := Item{
5591+
text: "external"
5592+
}
5593+
flag := true
5594+
values := make_items().map(match flag {
5595+
true {
5596+
p := &it
5597+
q := p
5598+
q
5599+
}
5600+
else {
5601+
&external
5602+
}
5603+
})
5604+
println(values[0].text)
5605+
}
5606+
'
5607+
c_source := gen_c_from_source_with_flags(v3_bin, 'array_map_local_pointer_alias_c',
5608+
'-ownership', source)
5609+
main_body := c_fn_body(c_source, 'int main(int argc, char** argv) {')
5610+
compact_main := main_body.replace(' ', '').replace('\t', '').replace('\n', '')
5611+
assert !compact_main.contains('array__free(&(__map_source_'), main_body
5612+
out := run_good_with_flags(v3_bin, 'array_map_local_pointer_alias', '-ownership', source)
5613+
assert out == 'source'
5614+
}
5615+
55775616
fn test_array_map_keeps_temporary_source_through_inherited_struct_update_field() {
55785617
v3_bin := build_v3_review_transform_ownership()
55795618
source := 'struct Item {
@@ -5653,6 +5692,25 @@ fn main() {
56535692
assert out == 'external'
56545693
}
56555694

5695+
fn test_array_sort_mixed_pointer_depth_comparator_arguments() {
5696+
v3_bin := build_v3_review_transform()
5697+
source := 'struct Thing {
5698+
value int
5699+
}
5700+
5701+
fn main() {
5702+
mut items := [&Thing{value: 3}, &Thing{value: 1}, &Thing{value: 2}]
5703+
compare := fn (a &Thing, b &&Thing) int {
5704+
return a.value - (*b).value
5705+
}
5706+
items.sort_with_compare(compare)
5707+
println(int_str(items[0].value) + "," + int_str(items[1].value) + "," + int_str(items[2].value))
5708+
}
5709+
'
5710+
out := run_good(v3_bin, 'array_sort_mixed_pointer_depth_comparator', source)
5711+
assert out == '1,2,3'
5712+
}
5713+
56565714
fn test_array_map_drops_source_for_unrelated_pointer_result() {
56575715
v3_bin := build_v3_review_transform_ownership()
56585716
source := 'struct Item {

vlib/v3/transform/array.v

Lines changed: 68 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -2806,9 +2806,7 @@ fn (mut t Transformer) array_map_expr_result_retains_element_address(id flat.Nod
28062806
&& t.array_map_expr_result_retains_element_address(t.a.child(&node, 0), name)
28072807
}
28082808
.block, .match_branch {
2809-
return node.children_count > 0
2810-
&& t.array_map_expr_result_retains_element_address(t.a.child(&node,
2811-
node.children_count - 1), name)
2809+
return t.array_map_block_result_retains_element_address(node, name)
28122810
}
28132811
.if_expr, .match_stmt {
28142812
for i in 1 .. node.children_count {
@@ -2867,6 +2865,55 @@ fn (mut t Transformer) array_map_expr_result_retains_element_address(id flat.Nod
28672865
}
28682866
}
28692867

2868+
fn (mut t Transformer) array_map_block_result_retains_element_address(node flat.Node, name string) bool {
2869+
if node.children_count == 0 {
2870+
return false
2871+
}
2872+
mut seen := map[string]bool{}
2873+
return t.array_map_block_value_retains_element_address(node, int(node.children_count) - 1,
2874+
t.a.child(&node, node.children_count - 1), name, mut seen)
2875+
}
2876+
2877+
fn (mut t Transformer) array_map_block_value_retains_element_address(node flat.Node, before_idx int, id flat.NodeId, name string, mut seen map[string]bool) bool {
2878+
mut result_id := id
2879+
mut result := t.a.nodes[int(result_id)]
2880+
for result.kind in [.paren, .cast_expr, .as_expr, .dump_expr, .expr_stmt, .field_init] {
2881+
if result.children_count == 0 {
2882+
break
2883+
}
2884+
result_id = t.a.child(&result, 0)
2885+
result = t.a.nodes[int(result_id)]
2886+
}
2887+
if result.kind != .ident || result.value.len == 0 {
2888+
return t.array_map_expr_result_retains_element_address(result_id, name)
2889+
}
2890+
if result.value in seen {
2891+
return false
2892+
}
2893+
seen[result.value] = true
2894+
for offset in 1 .. before_idx + 1 {
2895+
stmt_idx := before_idx - offset
2896+
stmt := t.a.child_node(&node, stmt_idx)
2897+
if stmt.kind == .decl_assign && stmt.children_count == 2 {
2898+
lhs := t.a.child_node(stmt, 0)
2899+
if lhs.kind == .ident && lhs.value == result.value {
2900+
return t.array_map_block_value_retains_element_address(node, stmt_idx,
2901+
t.a.child(stmt, 1), name, mut seen)
2902+
}
2903+
}
2904+
if stmt.kind == .assign {
2905+
for i := 0; i + 1 < int(stmt.children_count); i += 2 {
2906+
lhs := t.a.child_node(stmt, i)
2907+
if lhs.kind == .ident && lhs.value == result.value {
2908+
return t.array_map_block_value_retains_element_address(node, stmt_idx,
2909+
t.a.child(stmt, i + 1), name, mut seen)
2910+
}
2911+
}
2912+
}
2913+
}
2914+
return false
2915+
}
2916+
28702917
fn (mut t Transformer) array_map_index_result_retains_element_address(node flat.Node, name string) bool {
28712918
if node.children_count == 0 {
28722919
return false
@@ -3716,7 +3763,7 @@ fn (mut t Transformer) array_sort_less_expr(base flat.NodeId, elem_type string,
37163763
if int(cmp_id) >= 0 {
37173764
cmp_node := t.a.nodes[int(cmp_id)]
37183765
if cmp_node.kind == .lambda_expr && cmp_node.children_count >= 3 {
3719-
if cmp := t.array_sort_lambda_expr(cmp_node, cur, prev, elem_type) {
3766+
if cmp := t.array_sort_lambda_expr(cmp_node, cur, prev, elem_type, elem_type) {
37203767
return cmp
37213768
}
37223769
}
@@ -3801,13 +3848,15 @@ fn (mut t Transformer) array_sort_compare_less_expr(base flat.NodeId, elem_type
38013848
cur := t.make_index(base, t.make_ident(idx_name), elem_type)
38023849
prev := t.make_index(base, t.make_infix(.minus, t.make_ident(idx_name), t.make_int_literal(1)),
38033850
elem_type)
3804-
cmp_elem_type := t.array_sort_compare_arg_type(cmp, elem_type)
3805-
cur_arg := if cmp_elem_type == elem_type { cur } else { t.make_prefix(.amp, cur) }
3806-
prev_arg := if cmp_elem_type == elem_type { prev } else { t.make_prefix(.amp, prev) }
3851+
cmp_cur_type, cmp_prev_type := t.array_sort_compare_arg_types(cmp, elem_type)
3852+
cur_arg := if cmp_cur_type == elem_type { cur } else { t.make_prefix(.amp, cur) }
3853+
prev_arg := if cmp_prev_type == elem_type { prev } else { t.make_prefix(.amp, prev) }
38073854
if int(cmp) >= 0 {
38083855
cmp_node := t.a.nodes[int(cmp)]
38093856
if cmp_node.kind == .lambda_expr && cmp_node.children_count >= 3 {
3810-
if call_value := t.array_sort_lambda_expr(cmp_node, cur_arg, prev_arg, cmp_elem_type) {
3857+
if call_value := t.array_sort_lambda_expr(cmp_node, cur_arg, prev_arg, cmp_cur_type,
3858+
cmp_prev_type)
3859+
{
38113860
return t.make_infix(.lt, call_value, t.make_int_literal(0))
38123861
}
38133862
}
@@ -3816,10 +3865,10 @@ fn (mut t Transformer) array_sort_compare_less_expr(base flat.NodeId, elem_type
38163865
return t.make_infix(.lt, call, t.make_int_literal(0))
38173866
}
38183867

3819-
fn (t &Transformer) array_sort_compare_arg_type(cmp flat.NodeId, elem_type string) string {
3868+
fn (t &Transformer) array_sort_compare_arg_types(cmp flat.NodeId, elem_type string) (string, string) {
38203869
default_type := '&${elem_type}'
38213870
if !elem_type.starts_with('&') || isnil(t.tc) || int(cmp) < 0 {
3822-
return default_type
3871+
return default_type, default_type
38233872
}
38243873
cmp_node := t.a.nodes[int(cmp)]
38253874
raw_type := if cmp_node.kind == .ident {
@@ -3828,17 +3877,18 @@ fn (t &Transformer) array_sort_compare_arg_type(cmp flat.NodeId, elem_type strin
38283877
t.raw_checker_node_type(cmp)
38293878
}
38303879
if raw_type.len == 0 {
3831-
return default_type
3880+
return default_type, default_type
38323881
}
38333882
cmp_type := types.unalias_type(t.tc.parse_type(raw_type))
3834-
if cmp_type is types.FnType && cmp_type.params.len >= 2
3835-
&& cmp_type.params[0].name() == elem_type && cmp_type.params[1].name() == elem_type {
3836-
return elem_type
3883+
if cmp_type is types.FnType && cmp_type.params.len >= 2 {
3884+
first_type := if cmp_type.params[0].name() == elem_type { elem_type } else { default_type }
3885+
second_type := if cmp_type.params[1].name() == elem_type { elem_type } else { default_type }
3886+
return first_type, second_type
38373887
}
3838-
return default_type
3888+
return default_type, default_type
38393889
}
38403890

3841-
fn (mut t Transformer) array_sort_lambda_expr(node flat.Node, a_expr flat.NodeId, b_expr flat.NodeId, elem_type string) ?flat.NodeId {
3891+
fn (mut t Transformer) array_sort_lambda_expr(node flat.Node, a_expr flat.NodeId, b_expr flat.NodeId, a_type string, b_type string) ?flat.NodeId {
38423892
if node.kind != .lambda_expr || node.children_count < 3 {
38433893
return none
38443894
}
@@ -3851,8 +3901,8 @@ fn (mut t Transformer) array_sort_lambda_expr(node flat.Node, a_expr flat.NodeId
38513901
body_id := t.a.child(&node, node.children_count - 1)
38523902
old_a := t.var_type(first.value)
38533903
old_b := t.var_type(second.value)
3854-
t.set_var_type(first.value, elem_type)
3855-
t.set_var_type(second.value, elem_type)
3904+
t.set_var_type(first.value, a_type)
3905+
t.set_var_type(second.value, b_type)
38563906
raw_cmp := t.substitute_array_sort_vars_named(body_id, first.value, second.value, a_expr,
38573907
b_expr)
38583908
cmp := t.transform_expr(raw_cmp)

0 commit comments

Comments
 (0)