checker: require `shared a` to be `rlocked` to read `a[i]` or `a.e` (#9266)
parent
def53fd73f
commit
dbbf96702b
|
@ -348,14 +348,27 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn (mut c Checker) fail_if_not_rlocked(expr ast.Expr, what string) {
|
||||
if expr is ast.Ident {
|
||||
pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ table.Type, what string) {
|
||||
match expr {
|
||||
ast.Ident {
|
||||
if typ.has_flag(.shared_f) {
|
||||
if expr.name !in c.rlocked_names && expr.name !in c.locked_names {
|
||||
action := if what == 'argument' { 'passed' } else { 'used' }
|
||||
c.error('$expr.name is `shared` and must be `rlock`ed or `lock`ed to be $action as non-mut $what',
|
||||
expr.pos)
|
||||
}
|
||||
} else {
|
||||
}
|
||||
return
|
||||
}
|
||||
ast.SelectorExpr {
|
||||
c.fail_if_unreadable(expr.expr, expr.expr_type, what)
|
||||
}
|
||||
ast.IndexExpr {
|
||||
c.fail_if_unreadable(expr.left, expr.left_type, what)
|
||||
}
|
||||
else {}
|
||||
}
|
||||
if typ.has_flag(.shared_f) {
|
||||
c.error('you have to create a handle and `rlock` it to use a `shared` element as non-mut $what',
|
||||
expr.position())
|
||||
}
|
||||
|
@ -366,9 +379,7 @@ pub fn (mut c Checker) string_inter_lit(mut node ast.StringInterLiteral) table.T
|
|||
c.inside_println_arg = true
|
||||
for i, expr in node.exprs {
|
||||
ftyp := c.expr(expr)
|
||||
if ftyp.has_flag(.shared_f) {
|
||||
c.fail_if_not_rlocked(expr, 'interpolation object')
|
||||
}
|
||||
c.fail_if_unreadable(expr, ftyp, 'interpolation object')
|
||||
node.expr_types << ftyp
|
||||
typ := c.table.unalias_num_type(ftyp)
|
||||
mut fmt := node.fmts[i]
|
||||
|
|
|
@ -1421,9 +1421,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
pos)
|
||||
}
|
||||
} else {
|
||||
if left_type.has_flag(.shared_f) {
|
||||
c.fail_if_not_rlocked(call_expr.left, 'receiver')
|
||||
}
|
||||
c.fail_if_unreadable(call_expr.left, left_type, 'receiver')
|
||||
}
|
||||
if (!left_type_sym.is_builtin() && method.mod != 'builtin') && method.language == .v
|
||||
&& method.no_body {
|
||||
|
@ -1517,9 +1515,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
c.error('`$call_expr.name` parameter `$param.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${
|
||||
i + 1}`', arg.expr.position())
|
||||
} else {
|
||||
if got_arg_typ.has_flag(.shared_f) {
|
||||
c.fail_if_not_rlocked(arg.expr, 'argument')
|
||||
}
|
||||
c.fail_if_unreadable(arg.expr, got_arg_typ, 'argument')
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -1584,9 +1580,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
|||
if call_expr.args.len > 0 {
|
||||
c.error('.str() method calls should have no arguments', call_expr.pos)
|
||||
}
|
||||
if left_type.has_flag(.shared_f) {
|
||||
c.fail_if_not_rlocked(call_expr.left, 'receiver')
|
||||
}
|
||||
c.fail_if_unreadable(call_expr.left, left_type, 'receiver')
|
||||
return table.string_type
|
||||
}
|
||||
// call struct field fn type
|
||||
|
@ -1903,9 +1897,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
if call_expr.args[0].typ.is_void() {
|
||||
c.error('`$fn_name` can not print void expressions', call_expr.pos)
|
||||
}
|
||||
if call_expr.args[0].typ.has_flag(.shared_f) {
|
||||
c.fail_if_not_rlocked(call_expr.args[0].expr, 'argument to print')
|
||||
}
|
||||
c.fail_if_unreadable(call_expr.args[0].expr, call_expr.args[0].typ, 'argument to print')
|
||||
c.inside_println_arg = false
|
||||
/*
|
||||
// TODO: optimize `struct T{} fn (t &T) str() string {return 'abc'} mut a := []&T{} a << &T{} println(a[0])`
|
||||
|
@ -1983,9 +1975,7 @@ pub fn (mut c Checker) call_fn(mut call_expr ast.CallExpr) table.Type {
|
|||
c.error('`$call_expr.name` parameter `$arg.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${
|
||||
i + 1}`', call_arg.expr.position())
|
||||
} else {
|
||||
if typ.has_flag(.shared_f) {
|
||||
c.fail_if_not_rlocked(call_arg.expr, 'argument')
|
||||
}
|
||||
c.fail_if_unreadable(call_arg.expr, typ, 'argument')
|
||||
}
|
||||
}
|
||||
// Handle expected interface
|
||||
|
|
|
@ -5,3 +5,9 @@ vlib/v/checker/tests/lock_already_locked.vv:11:3: error: nested `lock`/`rlock` n
|
|||
| ~~~~~
|
||||
12 | a.x++
|
||||
13 | }
|
||||
vlib/v/checker/tests/lock_already_locked.vv:15:10: error: a is `shared` and must be `rlock`ed or `lock`ed to be used as non-mut argument to print
|
||||
13 | }
|
||||
14 | }
|
||||
15 | println(a.x)
|
||||
| ^
|
||||
16 | }
|
||||
|
|
|
@ -5,3 +5,9 @@ vlib/v/checker/tests/lock_already_rlocked.vv:11:3: error: nested `lock`/`rlock`
|
|||
| ~~~~
|
||||
12 | a.x++
|
||||
13 | }
|
||||
vlib/v/checker/tests/lock_already_rlocked.vv:15:10: error: a is `shared` and must be `rlock`ed or `lock`ed to be used as non-mut argument to print
|
||||
13 | }
|
||||
14 | }
|
||||
15 | println(a.x)
|
||||
| ^
|
||||
16 | }
|
||||
|
|
|
@ -5,3 +5,23 @@ vlib/v/checker/tests/lock_needed.vv:10:2: error: `abc` is `shared` and needs exp
|
|||
| ~~~
|
||||
11 | println(abc.x)
|
||||
12 | }
|
||||
vlib/v/checker/tests/lock_needed.vv:11:10: error: abc is `shared` and must be `rlock`ed or `lock`ed to be used as non-mut argument to print
|
||||
9 | }
|
||||
10 | abc.x++
|
||||
11 | println(abc.x)
|
||||
| ~~~
|
||||
12 | }
|
||||
13 |
|
||||
vlib/v/checker/tests/lock_needed.vv:25:12: error: you have to create a handle and `rlock` it to use a `shared` element as non-mut argument to print
|
||||
23 | }
|
||||
24 | }
|
||||
25 | println(a.st.x)
|
||||
| ~~
|
||||
26 | }
|
||||
27 |
|
||||
vlib/v/checker/tests/lock_needed.vv:30:10: error: a is `shared` and must be `rlock`ed or `lock`ed to be used as non-mut argument to print
|
||||
28 | fn g() {
|
||||
29 | shared a := []f64{len: 10, init: 7.5}
|
||||
30 | println(a[3])
|
||||
| ^
|
||||
31 | }
|
||||
|
|
|
@ -10,3 +10,22 @@ fn main() {
|
|||
abc.x++
|
||||
println(abc.x)
|
||||
}
|
||||
|
||||
struct Abc {
|
||||
mut:
|
||||
st shared St
|
||||
}
|
||||
|
||||
fn f() {
|
||||
mut a := Abc{
|
||||
st: St{
|
||||
x: 9
|
||||
}
|
||||
}
|
||||
println(a.st.x)
|
||||
}
|
||||
|
||||
fn g() {
|
||||
shared a := []f64{len: 10, init: 7.5}
|
||||
println(a[3])
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue