checker: check write access to shared elements of `struct` and `array` (#9314)
parent
1ad4623fb8
commit
9d168895ed
|
@ -349,6 +349,7 @@ pub fn (c &Checker) get_default_fmt(ftyp table.Type, typ table.Type) byte {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ table.Type, what string) {
|
pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ table.Type, what string) {
|
||||||
|
mut pos := token.Position{}
|
||||||
match expr {
|
match expr {
|
||||||
ast.Ident {
|
ast.Ident {
|
||||||
if typ.has_flag(.shared_f) {
|
if typ.has_flag(.shared_f) {
|
||||||
|
@ -361,16 +362,18 @@ pub fn (mut c Checker) fail_if_unreadable(expr ast.Expr, typ table.Type, what st
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
ast.SelectorExpr {
|
ast.SelectorExpr {
|
||||||
|
pos = expr.pos
|
||||||
c.fail_if_unreadable(expr.expr, expr.expr_type, what)
|
c.fail_if_unreadable(expr.expr, expr.expr_type, what)
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
|
pos = expr.left.position().extend(expr.pos)
|
||||||
c.fail_if_unreadable(expr.left, expr.left_type, what)
|
c.fail_if_unreadable(expr.left, expr.left_type, what)
|
||||||
}
|
}
|
||||||
else {}
|
else {}
|
||||||
}
|
}
|
||||||
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',
|
||||||
expr.position())
|
pos)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1084,6 +1084,25 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ast.IndexExpr {
|
ast.IndexExpr {
|
||||||
|
left_sym := c.table.get_type_symbol(expr.left_type)
|
||||||
|
mut elem_type := table.Type(0)
|
||||||
|
mut kind := ''
|
||||||
|
match left_sym.info {
|
||||||
|
table.Array {
|
||||||
|
elem_type, kind = left_sym.info.elem_type, 'array'
|
||||||
|
}
|
||||||
|
table.ArrayFixed {
|
||||||
|
elem_type, kind = left_sym.info.elem_type, 'fixed array'
|
||||||
|
}
|
||||||
|
table.Map {
|
||||||
|
elem_type, kind = left_sym.info.value_type, 'map'
|
||||||
|
}
|
||||||
|
else {}
|
||||||
|
}
|
||||||
|
if elem_type.has_flag(.shared_f) {
|
||||||
|
c.error('you have to create a handle and `lock` it to modify `shared` $kind element',
|
||||||
|
expr.left.position().extend(expr.pos))
|
||||||
|
}
|
||||||
to_lock, pos = c.fail_if_immutable(expr.left)
|
to_lock, pos = c.fail_if_immutable(expr.left)
|
||||||
}
|
}
|
||||||
ast.ParExpr {
|
ast.ParExpr {
|
||||||
|
@ -1128,6 +1147,11 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
|
||||||
c.error('field `$expr.field_name` of struct `$type_str` is immutable',
|
c.error('field `$expr.field_name` of struct `$type_str` is immutable',
|
||||||
expr.pos)
|
expr.pos)
|
||||||
}
|
}
|
||||||
|
if field_info.typ.has_flag(.shared_f) {
|
||||||
|
type_str := c.table.type_to_str(expr.expr_type)
|
||||||
|
c.error('you have to create a handle and `lock` it to modify `shared` field `$expr.field_name` of struct `$type_str`',
|
||||||
|
expr.pos)
|
||||||
|
}
|
||||||
to_lock, pos = c.fail_if_immutable(expr.expr)
|
to_lock, pos = c.fail_if_immutable(expr.expr)
|
||||||
if to_lock != '' {
|
if to_lock != '' {
|
||||||
// No automatic lock for struct access
|
// No automatic lock for struct access
|
||||||
|
|
|
@ -0,0 +1,27 @@
|
||||||
|
vlib/v/checker/tests/shared_element_lock.vv:36:5: error: you have to create a handle and `lock` it to modify `shared` field `pe` of struct `Programmer`
|
||||||
|
34 | }
|
||||||
|
35 | }
|
||||||
|
36 | pr.pe.color = 3
|
||||||
|
| ~~
|
||||||
|
37 | shared y := pr.pe
|
||||||
|
38 | rlock y {
|
||||||
|
vlib/v/checker/tests/shared_element_lock.vv:42:2: error: `g` is `shared` and needs explicit lock for `v.ast.SelectorExpr`
|
||||||
|
40 | }
|
||||||
|
41 | shared g := Pro{}
|
||||||
|
42 | g.pers.age = 42
|
||||||
|
| ^
|
||||||
|
43 | mut h := []shared Pro{len: 3}
|
||||||
|
44 | h[2].pers.age = 42
|
||||||
|
vlib/v/checker/tests/shared_element_lock.vv:44:2: error: you have to create a handle and `lock` it to modify `shared` array element
|
||||||
|
42 | g.pers.age = 42
|
||||||
|
43 | mut h := []shared Pro{len: 3}
|
||||||
|
44 | h[2].pers.age = 42
|
||||||
|
| ~~~~
|
||||||
|
45 | println(h[2].pers.age)
|
||||||
|
46 | }
|
||||||
|
vlib/v/checker/tests/shared_element_lock.vv:45:10: error: you have to create a handle and `rlock` it to use a `shared` element as non-mut argument to print
|
||||||
|
43 | mut h := []shared Pro{len: 3}
|
||||||
|
44 | h[2].pers.age = 42
|
||||||
|
45 | println(h[2].pers.age)
|
||||||
|
| ~~~~
|
||||||
|
46 | }
|
|
@ -0,0 +1,46 @@
|
||||||
|
struct Person {
|
||||||
|
mut:
|
||||||
|
name string
|
||||||
|
age int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Pet {
|
||||||
|
mut:
|
||||||
|
name string
|
||||||
|
color int
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Programmer {
|
||||||
|
mut:
|
||||||
|
pers Person
|
||||||
|
pe shared Pet
|
||||||
|
}
|
||||||
|
|
||||||
|
struct Pro {
|
||||||
|
mut:
|
||||||
|
pers Person
|
||||||
|
pe Pet
|
||||||
|
}
|
||||||
|
|
||||||
|
fn main() {
|
||||||
|
mut pr := Programmer{
|
||||||
|
pers: Person{
|
||||||
|
name: 'Qwe'
|
||||||
|
age: 44
|
||||||
|
}
|
||||||
|
pe: Pet{
|
||||||
|
name: 'Ghj'
|
||||||
|
color: 7
|
||||||
|
}
|
||||||
|
}
|
||||||
|
pr.pe.color = 3
|
||||||
|
shared y := pr.pe
|
||||||
|
rlock y {
|
||||||
|
println(y.color)
|
||||||
|
}
|
||||||
|
shared g := Pro{}
|
||||||
|
g.pers.age = 42
|
||||||
|
mut h := []shared Pro{len: 3}
|
||||||
|
h[2].pers.age = 42
|
||||||
|
println(h[2].pers.age)
|
||||||
|
}
|
|
@ -78,10 +78,13 @@ fn test_shared_map_in_struct() {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn test_array_of_shared() {
|
fn test_array_of_shared() {
|
||||||
mut a := []shared Xyz{len: 3}
|
mut a := []shared Xyz{cap: 3}
|
||||||
a[0] = Xyz{ n: 3 }
|
a0 := Xyz{ n: 3 }
|
||||||
a[1] = Xyz{ n: 7 }
|
a << a0
|
||||||
a[2] = Xyz{ n: 13 }
|
a1 := Xyz{ n: 7 }
|
||||||
|
a << a1
|
||||||
|
a2 := Xyz{ n: 13 }
|
||||||
|
a << a2
|
||||||
shared p := a[0]
|
shared p := a[0]
|
||||||
shared q := a[2]
|
shared q := a[2]
|
||||||
lock q {
|
lock q {
|
||||||
|
|
Loading…
Reference in New Issue