checker: check for mut val in immutable obj (#8285)
							parent
							
								
									d4f6f5eec4
								
							
						
					
					
						commit
						5ee3fecf60
					
				| 
						 | 
					@ -4,17 +4,38 @@ import os
 | 
				
			||||||
import term
 | 
					import term
 | 
				
			||||||
import time
 | 
					import time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const vexe = os.getenv('VEXE')
 | 
					const (
 | 
				
			||||||
 | 
						vexe = os.getenv('VEXE')
 | 
				
			||||||
const vroot = os.dir(vexe)
 | 
						vroot = os.dir(vexe)
 | 
				
			||||||
 | 
						args_string = os.args[1..].join(' ')
 | 
				
			||||||
const args_string = os.args[1..].join(' ')
 | 
						vargs = args_string.all_before('test-all')
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
const vargs = args_string.all_before('test-all')
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
fn main() {
 | 
					fn main() {
 | 
				
			||||||
	commands := get_all_commands()
 | 
						mut commands := get_all_commands()
 | 
				
			||||||
	commands.summary()
 | 
						// summary
 | 
				
			||||||
 | 
						sw := time.new_stopwatch({})
 | 
				
			||||||
 | 
						for mut cmd in commands {
 | 
				
			||||||
 | 
							cmd.run()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						spent := sw.elapsed().milliseconds()
 | 
				
			||||||
 | 
						oks := commands.filter(it.ecode == 0)
 | 
				
			||||||
 | 
						fails := commands.filter(it.ecode != 0)
 | 
				
			||||||
 | 
						println('')
 | 
				
			||||||
 | 
						println(term.header(term.colorize(term.yellow, term.colorize(term.bold, 'Summary of `v test-all`:')),
 | 
				
			||||||
 | 
							'-'))
 | 
				
			||||||
 | 
						println(term.colorize(term.yellow, 'Total runtime: $spent ms'))
 | 
				
			||||||
 | 
						for ocmd in oks {
 | 
				
			||||||
 | 
							msg := if ocmd.okmsg != '' { ocmd.okmsg } else { ocmd.line }
 | 
				
			||||||
 | 
							println(term.colorize(term.green, '>          OK: $msg '))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for fcmd in fails {
 | 
				
			||||||
 | 
							msg := if fcmd.errmsg != '' { fcmd.errmsg } else { fcmd.line }
 | 
				
			||||||
 | 
							println(term.colorize(term.red, '>      Failed: $msg '))
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if fails.len > 0 {
 | 
				
			||||||
 | 
							exit(1)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
struct Command {
 | 
					struct Command {
 | 
				
			||||||
| 
						 | 
					@ -80,28 +101,3 @@ fn (mut cmd Command) run() {
 | 
				
			||||||
	println(term.colorize(term.yellow, '> Running: "$cmd.line" took: $spent ms.'))
 | 
						println(term.colorize(term.yellow, '> Running: "$cmd.line" took: $spent ms.'))
 | 
				
			||||||
	println('')
 | 
						println('')
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					 | 
				
			||||||
fn (commands []Command) summary() {
 | 
					 | 
				
			||||||
	sw := time.new_stopwatch({})
 | 
					 | 
				
			||||||
	for mut cmd in commands {
 | 
					 | 
				
			||||||
		cmd.run()
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	spent := sw.elapsed().milliseconds()
 | 
					 | 
				
			||||||
	oks := commands.filter(it.ecode == 0)
 | 
					 | 
				
			||||||
	fails := commands.filter(it.ecode != 0)
 | 
					 | 
				
			||||||
	println('')
 | 
					 | 
				
			||||||
	println(term.header(term.colorize(term.yellow, term.colorize(term.bold, 'Summary of `v test-all`:')),
 | 
					 | 
				
			||||||
		'-'))
 | 
					 | 
				
			||||||
	println(term.colorize(term.yellow, 'Total runtime: $spent ms'))
 | 
					 | 
				
			||||||
	for ocmd in oks {
 | 
					 | 
				
			||||||
		msg := if ocmd.okmsg != '' { ocmd.okmsg } else { ocmd.line }
 | 
					 | 
				
			||||||
		println(term.colorize(term.green, '>          OK: $msg '))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	for fcmd in fails {
 | 
					 | 
				
			||||||
		msg := if fcmd.errmsg != '' { fcmd.errmsg } else { fcmd.line }
 | 
					 | 
				
			||||||
		println(term.colorize(term.red, '>      Failed: $msg '))
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
	if fails.len > 0 {
 | 
					 | 
				
			||||||
		exit(1)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3079,6 +3079,26 @@ fn (mut c Checker) stmt(node ast.Stmt) {
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					if node.val_is_mut {
 | 
										if node.val_is_mut {
 | 
				
			||||||
						value_type = value_type.to_ptr()
 | 
											value_type = value_type.to_ptr()
 | 
				
			||||||
 | 
											match node.cond {
 | 
				
			||||||
 | 
												ast.Ident {
 | 
				
			||||||
 | 
													if node.cond.obj is ast.Var {
 | 
				
			||||||
 | 
														obj := node.cond.obj as ast.Var
 | 
				
			||||||
 | 
														if !obj.is_mut {
 | 
				
			||||||
 | 
															c.error('`$obj.name` is immutable, it cannot be changed',
 | 
				
			||||||
 | 
																node.cond.pos)
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												ast.ArrayInit {
 | 
				
			||||||
 | 
													c.error('array literal is immutable, it cannot be changed',
 | 
				
			||||||
 | 
														node.cond.pos)
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												ast.MapInit {
 | 
				
			||||||
 | 
													c.error('map literal is immutable, it cannot be changed',
 | 
				
			||||||
 | 
														node.cond.pos)
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
												else {}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
					node.cond_type = typ
 | 
										node.cond_type = typ
 | 
				
			||||||
					node.kind = sym.kind
 | 
										node.kind = sym.kind
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,42 @@
 | 
				
			||||||
 | 
					vlib/v/checker/tests/for_in_mut_val_type.vv:3:15: error: `a1` is immutable, it cannot be changed
 | 
				
			||||||
 | 
					    1 | fn main() {
 | 
				
			||||||
 | 
					    2 |     a1 := [1, 2, 3]
 | 
				
			||||||
 | 
					    3 |     for mut j in a1 {
 | 
				
			||||||
 | 
					      |                  ~~
 | 
				
			||||||
 | 
					    4 |         j *= 2
 | 
				
			||||||
 | 
					    5 |     }
 | 
				
			||||||
 | 
					vlib/v/checker/tests/for_in_mut_val_type.vv:7:15: error: `a2` is immutable, it cannot be changed
 | 
				
			||||||
 | 
					    5 |     }
 | 
				
			||||||
 | 
					    6 |     a2 := [1, 2, 3]!
 | 
				
			||||||
 | 
					    7 |     for mut j in a2 {
 | 
				
			||||||
 | 
					      |                  ~~
 | 
				
			||||||
 | 
					    8 |         j *= 2
 | 
				
			||||||
 | 
					    9 |     }
 | 
				
			||||||
 | 
					vlib/v/checker/tests/for_in_mut_val_type.vv:11:18: error: `m` is immutable, it cannot be changed
 | 
				
			||||||
 | 
					    9 |     }
 | 
				
			||||||
 | 
					   10 |     m := {'aa': 1, 'bb': 2}
 | 
				
			||||||
 | 
					   11 |     for _, mut j in m {
 | 
				
			||||||
 | 
					      |                     ^
 | 
				
			||||||
 | 
					   12 |         j *= 2
 | 
				
			||||||
 | 
					   13 |     }
 | 
				
			||||||
 | 
					vlib/v/checker/tests/for_in_mut_val_type.vv:14:15: error: array literal is immutable, it cannot be changed
 | 
				
			||||||
 | 
					   12 |         j *= 2
 | 
				
			||||||
 | 
					   13 |     }
 | 
				
			||||||
 | 
					   14 |     for mut j in [1, 2, 3] {
 | 
				
			||||||
 | 
					      |                  ~~~~~~~~~
 | 
				
			||||||
 | 
					   15 |         j *= 2
 | 
				
			||||||
 | 
					   16 |     }
 | 
				
			||||||
 | 
					vlib/v/checker/tests/for_in_mut_val_type.vv:17:15: error: array literal is immutable, it cannot be changed
 | 
				
			||||||
 | 
					   15 |         j *= 2
 | 
				
			||||||
 | 
					   16 |     }
 | 
				
			||||||
 | 
					   17 |     for mut j in [1, 2, 3]! {
 | 
				
			||||||
 | 
					      |                  ~~~~~~~~~~
 | 
				
			||||||
 | 
					   18 |         j *= 2
 | 
				
			||||||
 | 
					   19 |     }
 | 
				
			||||||
 | 
					vlib/v/checker/tests/for_in_mut_val_type.vv:20:19: error: map literal is immutable, it cannot be changed
 | 
				
			||||||
 | 
					   18 |         j *= 2
 | 
				
			||||||
 | 
					   19 |     }
 | 
				
			||||||
 | 
					   20 |     for _, mut j in {'aa': 1, 'bb': 2} {
 | 
				
			||||||
 | 
					      |                      ~~~~
 | 
				
			||||||
 | 
					   21 |         j *= 2
 | 
				
			||||||
 | 
					   22 |     }
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					fn main() {
 | 
				
			||||||
 | 
						a1 := [1, 2, 3]
 | 
				
			||||||
 | 
						for mut j in a1 {
 | 
				
			||||||
 | 
							j *= 2
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						a2 := [1, 2, 3]!
 | 
				
			||||||
 | 
						for mut j in a2 {
 | 
				
			||||||
 | 
							j *= 2
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						m := {'aa': 1, 'bb': 2}
 | 
				
			||||||
 | 
						for _, mut j in m {
 | 
				
			||||||
 | 
							j *= 2
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for mut j in [1, 2, 3] {
 | 
				
			||||||
 | 
							j *= 2
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for mut j in [1, 2, 3]! {
 | 
				
			||||||
 | 
							j *= 2
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, mut j in {'aa': 1, 'bb': 2} {
 | 
				
			||||||
 | 
							j *= 2
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue