checker: protect against assigning to a typeless variable (#11094)

pull/11099/head
Daniel Däschle 2021-08-07 17:09:07 +02:00 committed by GitHub
parent 1d3786ff1e
commit 9af65d8830
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 28 additions and 8 deletions

View File

@ -3834,6 +3834,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
left_type = c.expr(left)
c.expected_type = c.unwrap_generic(left_type)
// `map = {}`
if left_type != 0 {
sym := c.table.get_type_symbol(left_type)
if sym.kind == .map && node.right[i] is ast.StructInit {
c.warn('assigning a struct literal to a map is deprecated - use `map{}` instead',
@ -3841,6 +3842,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
node.right[i] = ast.MapInit{}
}
}
}
if node.right_types.len < node.left.len { // first type or multi return types added above
old_inside_ref_lit := c.inside_ref_lit
if left is ast.Ident {
@ -4038,14 +4040,16 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
// right type was a generic `T`
continue
}
left_sym := c.table.get_type_symbol(left_type_unwrapped)
right_sym := c.table.get_type_symbol(right_type_unwrapped)
if c.pref.translated {
// TODO fix this in C2V instead, for example cast enums to int before using `|` on them.
// TODO replace all c.pref.translated checks with `$if !translated` for performance
continue
}
if left_type_unwrapped == 0 {
continue
}
left_sym := c.table.get_type_symbol(left_type_unwrapped)
right_sym := c.table.get_type_symbol(right_type_unwrapped)
if left_sym.kind == .array && !c.inside_unsafe && node.op in [.assign, .decl_assign]
&& right_sym.kind == .array && (left is ast.Ident && !left.is_blank_ident())
&& right is ast.Ident {

View File

@ -0,0 +1,12 @@
vlib/v/checker/tests/assign_to_typeless_variable_err.vv:2:10: error: invalid empty map initilization syntax, use e.g. map[string]int{} instead
1 | fn main() {
2 | val := {}
| ~~
3 | val = 1
4 | }
vlib/v/checker/tests/assign_to_typeless_variable_err.vv:3:3: error: `val` is immutable, declare it with `mut` to make it mutable
1 | fn main() {
2 | val := {}
3 | val = 1
| ~~~
4 | }

View File

@ -0,0 +1,4 @@
fn main() {
val := {}
val = 1
}