mirror of
https://github.com/vlang/v.git
synced 2023-08-10 21:13:21 +03:00
checker: check unsafe map index operation (#17000)
This commit is contained in:
parent
6bf6a40e0c
commit
21807f94a2
@ -109,9 +109,11 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
|||||||
if left in [ast.Ident, ast.SelectorExpr] {
|
if left in [ast.Ident, ast.SelectorExpr] {
|
||||||
c.prevent_sum_type_unwrapping_once = true
|
c.prevent_sum_type_unwrapping_once = true
|
||||||
}
|
}
|
||||||
c.inside_left_assign = true
|
if left is ast.IndexExpr {
|
||||||
|
c.is_index_assign = true
|
||||||
|
}
|
||||||
left_type = c.expr(left)
|
left_type = c.expr(left)
|
||||||
c.inside_left_assign = false
|
c.is_index_assign = false
|
||||||
c.expected_type = c.unwrap_generic(left_type)
|
c.expected_type = c.unwrap_generic(left_type)
|
||||||
}
|
}
|
||||||
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
|
||||||
|
@ -111,7 +111,7 @@ mut:
|
|||||||
inside_println_arg bool
|
inside_println_arg bool
|
||||||
inside_decl_rhs bool
|
inside_decl_rhs bool
|
||||||
inside_if_guard bool // true inside the guard condition of `if x := opt() {}`
|
inside_if_guard bool // true inside the guard condition of `if x := opt() {}`
|
||||||
inside_left_assign bool
|
is_index_assign bool
|
||||||
comptime_call_pos int // needed for correctly checking use before decl for templates
|
comptime_call_pos int // needed for correctly checking use before decl for templates
|
||||||
goto_labels map[string]ast.GotoLabel // to check for unused goto labels
|
goto_labels map[string]ast.GotoLabel // to check for unused goto labels
|
||||||
}
|
}
|
||||||
@ -3816,7 +3816,7 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
|
|||||||
node.pos)
|
node.pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
if !c.inside_unsafe && !c.is_builtin_mod && !c.inside_if_guard && !c.inside_left_assign
|
if !c.inside_unsafe && !c.is_builtin_mod && !c.inside_if_guard && !c.is_index_assign
|
||||||
&& typ_sym.kind == .map && node.or_expr.stmts.len == 0 {
|
&& typ_sym.kind == .map && node.or_expr.stmts.len == 0 {
|
||||||
elem_type := c.table.value_type(typ)
|
elem_type := c.table.value_type(typ)
|
||||||
if elem_type.is_real_pointer() {
|
if elem_type.is_real_pointer() {
|
||||||
|
14
vlib/v/checker/tests/map_index_reference_value.out
Normal file
14
vlib/v/checker/tests/map_index_reference_value.out
Normal file
@ -0,0 +1,14 @@
|
|||||||
|
vlib/v/checker/tests/map_index_reference_value.vv:7:3: notice: accessing a pointer map value requires an `or{}` block outside `unsafe`
|
||||||
|
5 | fn main() {
|
||||||
|
6 | mut m := map[string]&Foo{}
|
||||||
|
7 | m['bar'].bar = 'bar'
|
||||||
|
| ~~~~~~~
|
||||||
|
8 | // m['bar'] << 'baz' // etc
|
||||||
|
9 | }
|
||||||
|
vlib/v/checker/tests/map_index_reference_value.vv:7:11: error: field `bar` of struct `&Foo` is immutable
|
||||||
|
5 | fn main() {
|
||||||
|
6 | mut m := map[string]&Foo{}
|
||||||
|
7 | m['bar'].bar = 'bar'
|
||||||
|
| ~~~
|
||||||
|
8 | // m['bar'] << 'baz' // etc
|
||||||
|
9 | }
|
9
vlib/v/checker/tests/map_index_reference_value.vv
Normal file
9
vlib/v/checker/tests/map_index_reference_value.vv
Normal file
@ -0,0 +1,9 @@
|
|||||||
|
struct Foo {
|
||||||
|
bar string
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut m := map[string]&Foo{}
|
||||||
|
m['bar'].bar = 'bar'
|
||||||
|
// m['bar'] << 'baz' // etc
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user