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) {
|
pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ table.Type, what string) {
|
||||||
if expr is ast.Ident {
|
match expr {
|
||||||
if expr.name !in c.rlocked_names && expr.name !in c.locked_names {
|
ast.Ident {
|
||||||
action := if what == 'argument' { 'passed' } else { 'used' }
|
if typ.has_flag(.shared_f) {
|
||||||
c.error('$expr.name is `shared` and must be `rlock`ed or `lock`ed to be $action as non-mut $what',
|
if expr.name !in c.rlocked_names && expr.name !in c.locked_names {
|
||||||
expr.pos)
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return
|
||||||
}
|
}
|
||||||
} else {
|
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',
|
c.error('you have to create a handle and `rlock` it to use a `shared` element as non-mut $what',
|
||||||
expr.position())
|
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
|
c.inside_println_arg = true
|
||||||
for i, expr in node.exprs {
|
for i, expr in node.exprs {
|
||||||
ftyp := c.expr(expr)
|
ftyp := c.expr(expr)
|
||||||
if ftyp.has_flag(.shared_f) {
|
c.fail_if_unreadable(expr, ftyp, 'interpolation object')
|
||||||
c.fail_if_not_rlocked(expr, 'interpolation object')
|
|
||||||
}
|
|
||||||
node.expr_types << ftyp
|
node.expr_types << ftyp
|
||||||
typ := c.table.unalias_num_type(ftyp)
|
typ := c.table.unalias_num_type(ftyp)
|
||||||
mut fmt := node.fmts[i]
|
mut fmt := node.fmts[i]
|
||||||
|
|
|
@ -1421,9 +1421,7 @@ pub fn (mut c Checker) call_method(mut call_expr ast.CallExpr) table.Type {
|
||||||
pos)
|
pos)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if left_type.has_flag(.shared_f) {
|
c.fail_if_unreadable(call_expr.left, left_type, 'receiver')
|
||||||
c.fail_if_not_rlocked(call_expr.left, 'receiver')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (!left_type_sym.is_builtin() && method.mod != 'builtin') && method.language == .v
|
if (!left_type_sym.is_builtin() && method.mod != 'builtin') && method.language == .v
|
||||||
&& method.no_body {
|
&& 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${
|
c.error('`$call_expr.name` parameter `$param.name` is `$tok`, you need to provide `$tok` e.g. `$tok arg${
|
||||||
i + 1}`', arg.expr.position())
|
i + 1}`', arg.expr.position())
|
||||||
} else {
|
} else {
|
||||||
if got_arg_typ.has_flag(.shared_f) {
|
c.fail_if_unreadable(arg.expr, got_arg_typ, 'argument')
|
||||||
c.fail_if_not_rlocked(arg.expr, '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 {
|
if call_expr.args.len > 0 {
|
||||||
c.error('.str() method calls should have no arguments', call_expr.pos)
|
c.error('.str() method calls should have no arguments', call_expr.pos)
|
||||||
}
|
}
|
||||||
if left_type.has_flag(.shared_f) {
|
c.fail_if_unreadable(call_expr.left, left_type, 'receiver')
|
||||||
c.fail_if_not_rlocked(call_expr.left, 'receiver')
|
|
||||||
}
|
|
||||||
return table.string_type
|
return table.string_type
|
||||||
}
|
}
|
||||||
// call struct field fn 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() {
|
if call_expr.args[0].typ.is_void() {
|
||||||
c.error('`$fn_name` can not print void expressions', call_expr.pos)
|
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_unreadable(call_expr.args[0].expr, call_expr.args[0].typ, 'argument to print')
|
||||||
c.fail_if_not_rlocked(call_expr.args[0].expr, 'argument to print')
|
|
||||||
}
|
|
||||||
c.inside_println_arg = false
|
c.inside_println_arg = false
|
||||||
/*
|
/*
|
||||||
// TODO: optimize `struct T{} fn (t &T) str() string {return 'abc'} mut a := []&T{} a << &T{} println(a[0])`
|
// 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${
|
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())
|
i + 1}`', call_arg.expr.position())
|
||||||
} else {
|
} else {
|
||||||
if typ.has_flag(.shared_f) {
|
c.fail_if_unreadable(call_arg.expr, typ, 'argument')
|
||||||
c.fail_if_not_rlocked(call_arg.expr, 'argument')
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Handle expected interface
|
// 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++
|
12 | a.x++
|
||||||
13 | }
|
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++
|
12 | a.x++
|
||||||
13 | }
|
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 | }
|
||||||
|
|
|
@ -1,7 +1,27 @@
|
||||||
vlib/v/checker/tests/lock_needed.vv:10:2: error: `abc` is `shared` and needs explicit lock for `v.ast.SelectorExpr`
|
vlib/v/checker/tests/lock_needed.vv:10:2: error: `abc` is `shared` and needs explicit lock for `v.ast.SelectorExpr`
|
||||||
8 | x: 5
|
8 | x: 5
|
||||||
9 | }
|
9 | }
|
||||||
10 | abc.x++
|
10 | abc.x++
|
||||||
| ~~~
|
| ~~~
|
||||||
11 | println(abc.x)
|
11 | println(abc.x)
|
||||||
12 | }
|
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++
|
abc.x++
|
||||||
println(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