checker: check write access to shared elements of `struct` and `array` (#9314)

pull/9321/head
Uwe Krüger 2021-03-15 14:54:06 +01:00 committed by GitHub
parent 1ad4623fb8
commit 9d168895ed
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 108 additions and 5 deletions

View File

@ -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) {
mut pos := token.Position{}
match expr {
ast.Ident {
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
}
ast.SelectorExpr {
pos = expr.pos
c.fail_if_unreadable(expr.expr, expr.expr_type, what)
}
ast.IndexExpr {
pos = expr.left.position().extend(expr.pos)
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())
pos)
}
}

View File

@ -1084,6 +1084,25 @@ fn (mut c Checker) fail_if_immutable(expr ast.Expr) (string, token.Position) {
}
}
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)
}
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',
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)
if to_lock != '' {
// No automatic lock for struct access

View File

@ -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 | }

View File

@ -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)
}

View File

@ -78,10 +78,13 @@ fn test_shared_map_in_struct() {
}
fn test_array_of_shared() {
mut a := []shared Xyz{len: 3}
a[0] = Xyz{ n: 3 }
a[1] = Xyz{ n: 7 }
a[2] = Xyz{ n: 13 }
mut a := []shared Xyz{cap: 3}
a0 := Xyz{ n: 3 }
a << a0
a1 := Xyz{ n: 7 }
a << a1
a2 := Xyz{ n: 13 }
a << a2
shared p := a[0]
shared q := a[2]
lock q {