checker: fix mut check bypass with for in loops (#12208)

pull/12207/head^2
05st 2021-10-16 22:41:39 -05:00 committed by GitHub
parent e6b7ab8b9d
commit fd3a10ab43
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
7 changed files with 36 additions and 11 deletions

View File

@ -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]

View File

@ -5,4 +5,4 @@ use `_` if you do not need the variable
3 | for k in kvs {
| ^
4 | println('$k')
5 | }
5 | }

View File

@ -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 | }
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 | }

View File

@ -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
}
}

View File

@ -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')

View File

@ -8,7 +8,7 @@ pub mut:
}
fn test_for_in_mut_reference_selector_val() {
bb := BB{
mut bb := BB{
arr: [&AA{
id: 'Test1'
}, &AA{

View File

@ -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)
}