diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 60aecb9bc7..b9299fbcc4 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -64,6 +64,7 @@ mut: inside_sql bool // to handle sql table fields pseudo variables cur_orm_ts table.TypeSymbol error_details []string + for_in_mut_val_name string vmod_file_content string // needed for @VMOD_FILE, contents of the file, *NOT its path** vweb_gen_types []table.Type // vweb route checks prevent_sum_type_unwrapping_once bool // needed for assign new values to sum type, stopping unwrapping then @@ -2493,7 +2494,7 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { assign_stmt.pos) } left_is_ptr := left_type.is_ptr() || left_sym.is_pointer() - if left_is_ptr { + if left_is_ptr && c.for_in_mut_val_name != left.str() { if !c.inside_unsafe && assign_stmt.op !in [.assign, .decl_assign] { // ptr op= c.warn('pointer arithmetic is only allowed in `unsafe` blocks', assign_stmt.pos) @@ -2996,7 +2997,13 @@ fn (mut c Checker) stmt(node ast.Stmt) { } } c.check_loop_label(node.label, node.pos) + if node.val_is_mut { + c.for_in_mut_val_name = node.val_var + } c.stmts(node.stmts) + if node.val_is_mut { + c.for_in_mut_val_name = '' + } c.loop_label = prev_loop_label c.in_for_count-- } diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index 44d6ed8223..db5f5cf0ae 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -112,6 +112,7 @@ mut: strs_to_free0 []string // strings.Builder // strs_to_free []string // strings.Builder inside_call bool + for_in_mul_val_name string has_main bool inside_const bool comp_for_method string // $for method in T.methods {} @@ -1379,7 +1380,13 @@ fn (mut g Gen) for_in(it ast.ForInStmt) { s := g.table.type_to_str(it.cond_type) g.error('for in: unhandled symbol `$it.cond` of type `$s`', it.pos) } + if it.val_is_mut { + g.for_in_mul_val_name = it.val_var + } g.stmts(it.stmts) + if it.val_is_mut { + g.for_in_mul_val_name = '' + } if it.label.len > 0 { g.writeln('\t${it.label}__continue: {}') } @@ -2002,6 +2009,9 @@ fn (mut g Gen) gen_assign_stmt(assign_stmt ast.AssignStmt) { g.prevent_sum_type_unwrapping_once = true } if !is_fixed_array_copy || is_decl { + if !is_decl && left is ast.Ident && g.for_in_mul_val_name == (left as ast.Ident).name { + g.write('*') + } g.expr(left) } } diff --git a/vlib/v/tests/for_in_mut_val_test.v b/vlib/v/tests/for_in_mut_val_test.v new file mode 100644 index 0000000000..bf94b4dac3 --- /dev/null +++ b/vlib/v/tests/for_in_mut_val_test.v @@ -0,0 +1,12 @@ +fn foo(mut arr []int) { + for _, mut j in arr { + j *= 2 + } +} + +fn test_for_in_mut_val() { + mut arr := [1, 2, 3] + foo(mut arr) + println(arr) + assert arr == [2, 4, 6] +}