diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 40a12bebc9..b23409dc44 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -121,7 +121,8 @@ pub fn new_checker(table &ast.Table, pref &pref.Preferences) &Checker { } } -pub fn (mut c Checker) check(ast_file &ast.File) { +pub fn (mut c Checker) check(ast_file_ &ast.File) { + mut ast_file := ast_file_ c.change_current_file(ast_file) for i, ast_import in ast_file.imports { for sym in ast_import.syms { @@ -212,7 +213,7 @@ pub fn (mut c Checker) check_files(ast_files []&ast.File) { mut has_main_fn := false mut files_from_main_module := []&ast.File{} for i in 0 .. ast_files.len { - file := unsafe { ast_files[i] } + mut file := unsafe { ast_files[i] } c.timers.start('checker_check $file.path') c.check(file) if file.mod.name == 'main' { @@ -5092,6 +5093,13 @@ fn (mut c Checker) for_in_stmt(mut node ast.ForInStmt) { ast.MapInit { c.error('map literal is immutable, it cannot be changed', node.cond.pos) } + ast.SelectorExpr { + root_ident := node.cond.root_ident() or { node.cond.expr as ast.Ident } + if !(root_ident.obj as ast.Var).is_mut { + c.error('field `$node.cond.field_name` is immutable, it cannot be changed', + node.cond.pos) + } + } else {} } } @@ -5199,7 +5207,7 @@ fn (mut c Checker) asm_stmt(mut stmt ast.AsmStmt) { mut aliases := c.asm_ios(stmt.output, mut stmt.scope, true) aliases2 := c.asm_ios(stmt.input, mut stmt.scope, false) aliases << aliases2 - for template in stmt.templates { + for mut template in stmt.templates { if template.is_directive { /* align n[,value] diff --git a/vlib/v/checker/tests/for_in_map_one_variable_err.out b/vlib/v/checker/tests/for_in_map_one_variable_err.out index 0eb7516436..48c26cce49 100644 --- a/vlib/v/checker/tests/for_in_map_one_variable_err.out +++ b/vlib/v/checker/tests/for_in_map_one_variable_err.out @@ -5,4 +5,4 @@ use `_` if you do not need the variable 3 | for k in kvs { | ^ 4 | println('$k') - 5 | } \ No newline at end of file + 5 | } diff --git a/vlib/v/checker/tests/for_in_mut_val_type.out b/vlib/v/checker/tests/for_in_mut_val_type.out index 3a47a75493..935df54beb 100644 --- a/vlib/v/checker/tests/for_in_mut_val_type.out +++ b/vlib/v/checker/tests/for_in_mut_val_type.out @@ -39,4 +39,11 @@ vlib/v/checker/tests/for_in_mut_val_type.vv:20:18: error: map literal is immutab 20 | for _, mut j in {'aa': 1, 'bb': 2} { | ~~~~~~~~~~~~~~~~~~ 21 | j *= 2 - 22 | } \ No newline at end of file + 22 | } +vlib/v/checker/tests/for_in_mut_val_type.vv:30:17: error: field `a` is immutable, it cannot be changed + 28 | + 29 | fn foo(t Test) { + 30 | for mut e in t.a { + | ^ + 31 | e = 0 + 32 | } diff --git a/vlib/v/checker/tests/for_in_mut_val_type.vv b/vlib/v/checker/tests/for_in_mut_val_type.vv index afd714bdf5..a2eeefb447 100644 --- a/vlib/v/checker/tests/for_in_mut_val_type.vv +++ b/vlib/v/checker/tests/for_in_mut_val_type.vv @@ -21,3 +21,13 @@ fn main() { j *= 2 } } + +struct Test { + a []int = [1, 2] +} + +fn foo(t Test) { + for mut e in t.a { + e = 0 + } +} diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index fb1a66a768..16a34fd83e 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5634,7 +5634,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { g.go_back_out(3) return } - sym := g.table.get_final_type_symbol(g.unwrap_generic(struct_init.typ)) + mut sym := g.table.get_final_type_symbol(g.unwrap_generic(struct_init.typ)) is_amp := g.is_amp is_multiline := struct_init.fields.len > 5 g.is_amp = false // reset the flag immediately so that other struct inits in this expr are handled correctly @@ -5721,7 +5721,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { // `inited_fields` is a list of fields that have been init'ed, they are skipped mut nr_fields := 1 if sym.kind == .struct_ { - info := sym.info as ast.Struct + mut info := sym.info as ast.Struct nr_fields = info.fields.len if info.is_union && struct_init.fields.len > 1 { verror('union must not have more than 1 initializer') diff --git a/vlib/v/tests/for_in_mut_reference_selector_val_test.v b/vlib/v/tests/for_in_mut_reference_selector_val_test.v index 7caeb84378..0609447a39 100644 --- a/vlib/v/tests/for_in_mut_reference_selector_val_test.v +++ b/vlib/v/tests/for_in_mut_reference_selector_val_test.v @@ -8,7 +8,7 @@ pub mut: } fn test_for_in_mut_reference_selector_val() { - bb := BB{ + mut bb := BB{ arr: [&AA{ id: 'Test1' }, &AA{ diff --git a/vlib/v/transformer/transformer.v b/vlib/v/transformer/transformer.v index 63ae283e7c..06d2a9bc06 100644 --- a/vlib/v/transformer/transformer.v +++ b/vlib/v/transformer/transformer.v @@ -15,12 +15,12 @@ pub fn new_transformer(pref &pref.Preferences) &Transformer { pub fn (t Transformer) transform_files(ast_files []&ast.File) { for i in 0 .. ast_files.len { - file := unsafe { ast_files[i] } - t.transform(file) + mut file := unsafe { ast_files[i] } + t.transform(mut file) } } -pub fn (t Transformer) transform(ast_file &ast.File) { +pub fn (t Transformer) transform(mut ast_file ast.File) { for mut stmt in ast_file.stmts { t.stmt(mut stmt) }