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 := if i < node.right.len { node.right[i] } else { node.right[0] }
mut right_type := node.right_types[i] mut right_type := node.right_types[i]
if mut right is ast.Ident { 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) right_sym := c.table.sym(right_type)
if right_sym.info is ast.Struct { if right_sym.info is ast.Struct {
if right_sym.info.generic_types.len > 0 { 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{} mut pos := token.Pos{}
match expr { match expr {
ast.Ident { 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' } 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}', c.error('`${expr.name}` is `shared` and must be `rlock`ed or `lock`ed to be ${action} as non-mut ${what}',
expr.pos) expr.pos)
return true
} }
} }
return return false
} }
ast.SelectorExpr { ast.SelectorExpr {
pos = expr.pos 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' } 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}', c.error('`${expr_name}` is `shared` and must be `rlock`ed or `lock`ed to be ${action} as non-mut ${what}',
expr.pos) expr.pos)
return true
} }
return return false
} else { } 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 { ast.CallExpr {
pos = expr.pos pos = expr.pos
if expr.is_method { 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 { ast.LockExpr {
// TODO: check expressions inside the lock by appending to c.(r)locked_names // TODO: check expressions inside the lock by appending to c.(r)locked_names
return return false
} }
ast.IndexExpr { ast.IndexExpr {
pos = expr.left.pos().extend(expr.pos) 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 { ast.InfixExpr {
pos = expr.left.pos().extend(expr.pos) 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) {
c.fail_if_unreadable(expr.right, expr.right_type, what) return true
}
if c.fail_if_unreadable(expr.right, expr.right_type, what) {
return true
}
} }
else { else {
pos = expr.pos() 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) { 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}',
pos) pos)
return true
} }
return false
} }
fn (mut c Checker) fail_if_stack_struct_action_outside_unsafe(mut ident ast.Ident, failed_action string) { 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)
}