1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

checker: check shared parameter assigning (fix #18525) (#18534)

This commit is contained in:
yuyi 2023-06-24 19:18:11 +08:00 committed by GitHub
parent 5f0ad64155
commit 3e3b289583
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 53 additions and 10 deletions

View File

@ -164,6 +164,12 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
mut right := if i < node.right.len { node.right[i] } else { node.right[0] }
mut right_type := node.right_types[i]
if mut right is ast.Ident {
// resolve shared right vairable
if right_type.has_flag(.shared_f) {
if c.fail_if_unreadable(right, right_type, 'right-hand side of assignment') {
return
}
}
right_sym := c.table.sym(right_type)
if right_sym.info is ast.Struct {
if right_sym.info.generic_types.len > 0 {

View File

@ -4664,7 +4664,8 @@ fn (mut c Checker) ensure_type_exists(typ ast.Type, pos token.Pos) ? {
}
}
fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string) {
// return true if a violation of a shared variable access rule is detected
fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string) bool {
mut pos := token.Pos{}
match expr {
ast.Ident {
@ -4673,9 +4674,10 @@ fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string)
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 true
}
}
return
return false
}
ast.SelectorExpr {
pos = expr.pos
@ -4685,31 +4687,42 @@ fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string)
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 true
}
return
return false
} else {
c.fail_if_unreadable(expr.expr, expr.expr_type, what)
if c.fail_if_unreadable(expr.expr, expr.expr_type, what) {
return true
}
}
}
ast.CallExpr {
pos = expr.pos
if expr.is_method {
c.fail_if_unreadable(expr.left, expr.left_type, what)
if c.fail_if_unreadable(expr.left, expr.left_type, what) {
return true
}
}
return
return false
}
ast.LockExpr {
// TODO: check expressions inside the lock by appending to c.(r)locked_names
return
return false
}
ast.IndexExpr {
pos = expr.left.pos().extend(expr.pos)
c.fail_if_unreadable(expr.left, expr.left_type, what)
if c.fail_if_unreadable(expr.left, expr.left_type, what) {
return true
}
}
ast.InfixExpr {
pos = expr.left.pos().extend(expr.pos)
c.fail_if_unreadable(expr.left, expr.left_type, what)
c.fail_if_unreadable(expr.right, expr.right_type, what)
if c.fail_if_unreadable(expr.left, expr.left_type, what) {
return true
}
if c.fail_if_unreadable(expr.right, expr.right_type, what) {
return true
}
}
else {
pos = expr.pos()
@ -4718,7 +4731,9 @@ fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ ast.Type, what string)
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}',
pos)
return true
}
return false
}
fn (mut c Checker) fail_if_stack_struct_action_outside_unsafe(mut ident ast.Ident, failed_action string) {

View File

@ -0,0 +1,13 @@
vlib/v/checker/tests/shared_param_assign_err.vv:2:10: error: `arr` is `shared` and must be `rlock`ed or `lock`ed to be used as non-mut right-hand side of assignment
1 | fn foo(shared arr []string) {
2 | arr2 := arr
| ~~~
3 | println(arr2)
4 | }
vlib/v/checker/tests/shared_param_assign_err.vv:3:10: error: `arr2` is `shared` and must be `rlock`ed or `lock`ed to be used as non-mut argument to print
1 | fn foo(shared arr []string) {
2 | arr2 := arr
3 | println(arr2)
| ~~~~
4 | }
5 |

View File

@ -0,0 +1,9 @@
fn foo(shared arr []string) {
arr2 := arr
println(arr2)
}
fn main() {
shared arr := ['']
foo(shared arr)
}