Skip to content

Commit

Permalink
checker: disallow indexing mut struct, passed as a fn parameter (#19992)
Browse files Browse the repository at this point in the history
  • Loading branch information
shove70 committed Nov 27, 2023
1 parent 8ba04d3 commit b9a7de5
Show file tree
Hide file tree
Showing 5 changed files with 57 additions and 22 deletions.
10 changes: 9 additions & 1 deletion vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -4352,18 +4352,26 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
}
}

if (typ.is_ptr() && !typ.has_flag(.shared_f) && !node.left.is_auto_deref_var())
if (typ.is_ptr() && !typ.has_flag(.shared_f) && (!node.left.is_auto_deref_var()
|| (typ_sym.kind == .struct_ && typ_sym.name != 'array')))
|| typ.is_pointer() {
mut is_ok := false
mut is_mut_struct := false
if mut node.left is ast.Ident {
if mut node.left.obj is ast.Var {
// `mut param []T` function parameter
is_ok = node.left.obj.is_mut && node.left.obj.is_arg && !typ.deref().is_ptr()
&& typ_sym.kind != .struct_
// `mut param Struct`
is_mut_struct = node.left.obj.is_mut && node.left.obj.is_arg
&& typ_sym.kind == .struct_
}
}
if !is_ok && node.index is ast.RangeExpr {
s := c.table.type_to_str(typ)
c.error('type `${s}` does not support slicing', node.pos)
} else if is_mut_struct {
c.error('type `mut ${typ_sym.name}` does not support slicing', node.pos)
} else if !c.inside_unsafe && !is_ok && !c.pref.translated && !c.file.is_translated {
c.warn('pointer indexing is only allowed in `unsafe` blocks', node.pos)
}
Expand Down
34 changes: 34 additions & 0 deletions vlib/v/checker/tests/index_sumtype_interface_struct_params_err.out
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
vlib/v/checker/tests/index_sumtype_interface_struct_params_err.vv:12:9: warning: pointer indexing is only allowed in `unsafe` blocks
10 |
11 | _ = st1[0]
12 | _ = st2[0]
| ~~~
13 | _ = st3[0]
14 | }
vlib/v/checker/tests/index_sumtype_interface_struct_params_err.vv:8:9: error: type `Foo` does not support indexing
6 |
7 | fn sum_type_or_interface_as_parameters(mut foo Foo, mut bar Bar, mut st1 Struct, st2 &Struct, st3 Struct) {
8 | _ = foo[0]
| ~~~
9 | _ = bar[0]
10 |
vlib/v/checker/tests/index_sumtype_interface_struct_params_err.vv:9:9: error: type `Bar` does not support indexing
7 | fn sum_type_or_interface_as_parameters(mut foo Foo, mut bar Bar, mut st1 Struct, st2 &Struct, st3 Struct) {
8 | _ = foo[0]
9 | _ = bar[0]
| ~~~
10 |
11 | _ = st1[0]
vlib/v/checker/tests/index_sumtype_interface_struct_params_err.vv:11:9: error: type `mut Struct` does not support slicing
9 | _ = bar[0]
10 |
11 | _ = st1[0]
| ~~~
12 | _ = st2[0]
13 | _ = st3[0]
vlib/v/checker/tests/index_sumtype_interface_struct_params_err.vv:13:9: error: type `Struct` does not support indexing
11 | _ = st1[0]
12 | _ = st2[0]
13 | _ = st3[0]
| ~~~
14 | }
14 changes: 14 additions & 0 deletions vlib/v/checker/tests/index_sumtype_interface_struct_params_err.vv
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
type Foo = int | map[int]int

interface Bar {}

struct Struct {}

fn sum_type_or_interface_as_parameters(mut foo Foo, mut bar Bar, mut st1 Struct, st2 &Struct, st3 Struct) {
_ = foo[0]
_ = bar[0]

_ = st1[0]
_ = st2[0]
_ = st3[0]
}
13 changes: 0 additions & 13 deletions vlib/v/checker/tests/index_sumtype_or_interface_params_err.out

This file was deleted.

8 changes: 0 additions & 8 deletions vlib/v/checker/tests/index_sumtype_or_interface_params_err.vv

This file was deleted.

0 comments on commit b9a7de5

Please sign in to comment.