checker: protect against assigning to a typeless variable (#11094)
parent
1d3786ff1e
commit
9af65d8830
|
@ -3834,11 +3834,13 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||||
left_type = c.expr(left)
|
left_type = c.expr(left)
|
||||||
c.expected_type = c.unwrap_generic(left_type)
|
c.expected_type = c.unwrap_generic(left_type)
|
||||||
// `map = {}`
|
// `map = {}`
|
||||||
sym := c.table.get_type_symbol(left_type)
|
if left_type != 0 {
|
||||||
if sym.kind == .map && node.right[i] is ast.StructInit {
|
sym := c.table.get_type_symbol(left_type)
|
||||||
c.warn('assigning a struct literal to a map is deprecated - use `map{}` instead',
|
if sym.kind == .map && node.right[i] is ast.StructInit {
|
||||||
node.right[i].position())
|
c.warn('assigning a struct literal to a map is deprecated - use `map{}` instead',
|
||||||
node.right[i] = ast.MapInit{}
|
node.right[i].position())
|
||||||
|
node.right[i] = ast.MapInit{}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if node.right_types.len < node.left.len { // first type or multi return types added above
|
if node.right_types.len < node.left.len { // first type or multi return types added above
|
||||||
|
@ -4038,14 +4040,16 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||||
// right type was a generic `T`
|
// right type was a generic `T`
|
||||||
continue
|
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 {
|
if c.pref.translated {
|
||||||
// TODO fix this in C2V instead, for example cast enums to int before using `|` on them.
|
// 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
|
// TODO replace all c.pref.translated checks with `$if !translated` for performance
|
||||||
continue
|
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]
|
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_sym.kind == .array && (left is ast.Ident && !left.is_blank_ident())
|
||||||
&& right is ast.Ident {
|
&& right is ast.Ident {
|
||||||
|
|
|
@ -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 | }
|
|
@ -0,0 +1,4 @@
|
||||||
|
fn main() {
|
||||||
|
val := {}
|
||||||
|
val = 1
|
||||||
|
}
|
Loading…
Reference in New Issue