pull/13338/merge
Naoki MATSUMOTO 2022-04-06 21:00:00 +08:00 committed by GitHub
commit f0e2444416
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 66 additions and 5 deletions

View File

@ -1086,9 +1086,13 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
// TODO: remove this for actual methods, use only for compiler magic
// FIXME: Argument count != 1 will break these
if left_sym.kind == .array && method_name in array_builtin_methods {
// check if shared variable is locked
c.fail_if_unreadable(node.left, left_type, 'receiver')
return c.array_builtin_method_call(mut node, left_type, c.table.sym(left_type))
} else if (left_sym.kind == .map || final_left_sym.kind == .map)
&& method_name in ['clone', 'keys', 'move', 'delete'] {
// check if shared variable is locked
c.fail_if_unreadable(node.left, left_type, 'receiver')
if left_sym.kind == .map {
return c.map_builtin_method_call(mut node, left_type, left_sym)
} else {
@ -1096,6 +1100,8 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
return c.map_builtin_method_call(mut node, parent_type, final_left_sym)
}
} else if left_sym.kind == .array && method_name in ['insert', 'prepend'] {
// check if shared variable is locked
c.fail_if_unreadable(node.left, left_type, 'receiver')
if method_name == 'insert' {
if node.args.len != 2 {
c.error('`array.insert()` should have 2 arguments, e.g. `insert(1, val)`',
@ -1124,6 +1130,8 @@ pub fn (mut c Checker) method_call(mut node ast.CallExpr) ast.Type {
c.error('cannot $method_name `$arg_sym.name` to `$left_sym.name`', arg_expr.pos())
}
} else if final_left_sym.kind == .array && method_name in ['first', 'last', 'pop'] {
// check if shared variable is locked
c.fail_if_unreadable(node.left, left_type, 'receiver')
if final_left_sym.info is ast.Array {
node.return_type = final_left_sym.info.elem_type
return node.return_type
@ -1746,6 +1754,7 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type ast.
} else {
ret_type = left_type
}
ret_type = ret_type.clear_flag(.shared_f)
}
'keys' {
info := left_sym.info as ast.Map
@ -1766,6 +1775,10 @@ fn (mut c Checker) map_builtin_method_call(mut node ast.CallExpr, left_type ast.
else {}
}
node.receiver_type = left_type.ref()
// all methods does not take a lock inside them.
node.receiver_type = node.receiver_type.clear_flag(.shared_f)
node.return_type = ret_type
return node.return_type
}
@ -1874,6 +1887,7 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
} else {
node.return_type = node.receiver_type.set_nr_muls(0)
}
node.return_type = node.return_type.clear_flag(.shared_f)
} else if method_name == 'sort' {
node.return_type = ast.void_type
} else if method_name == 'contains' {
@ -1890,6 +1904,10 @@ fn (mut c Checker) array_builtin_method_call(mut node ast.CallExpr, left_type as
node.receiver_type = left_type
}
}
// all methods does not take a lock inside them.
node.receiver_type = node.receiver_type.clear_flag(.shared_f)
return node.return_type
}

View File

@ -404,7 +404,9 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
if node.args.len == 0 {
comparison_type = g.unwrap(info.elem_type.set_nr_muls(0))
shared a := g.array_sort_fn
array_sort_fn := a.clone()
array_sort_fn := rlock a {
a.clone()
}
if compare_fn in array_sort_fn {
g.gen_array_sort_call(node, compare_fn)
return
@ -425,7 +427,9 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
compare_fn += '_reverse'
}
shared a := g.array_sort_fn
array_sort_fn := a.clone()
array_sort_fn := rlock a {
a.clone()
}
if compare_fn in array_sort_fn {
g.gen_array_sort_call(node, compare_fn)
return

View File

@ -984,7 +984,9 @@ fn (mut g Gen) register_optional(t ast.Type) string {
}
fn (mut g Gen) write_optionals() {
mut done := g.done_optionals.clone()
mut done := rlock g.done_optionals {
g.done_optionals.clone()
}
for base, styp in g.optionals {
if base in done {
continue

View File

@ -1046,7 +1046,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
if !node.left.is_lvalue() {
g.write('ADDR($rec_cc_type, ')
has_cast = true
} else {
// if receiver has shared_f, the struct ptr itself is passed directly.
} else if !node.receiver_type.has_flag(.shared_f) {
g.write('&')
}
}
@ -1102,7 +1103,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
}
g.write(embed_name)
}
if node.left_type.has_flag(.shared_f) {
// if receiver has shared_f, the struct ptr itself is passed directly.
if node.left_type.has_flag(.shared_f) && !node.receiver_type.has_flag(.shared_f) {
g.write('->val')
}
}

View File

@ -50,3 +50,27 @@ fn test_shared_receiver_lock() {
assert x.a == 7 && y.a == 5
}
}
struct St2 {
mut:
a map[string]int
}
fn (shared x St2) f() {
lock x {
x.a["a"] = 123
}
}
fn test_shared_receiver_lock_2() {
shared x := St2 {
a: map[string]int
}
x.f()
rlock x {
assert x.a["a"] == 123
}
}

View File

@ -121,3 +121,14 @@ fn test_shared_lock_chan_rec_expr() {
}
}
}
fn test_shared_array_clone() {
shared a := []string{}
lock a {
a << "test"
}
b := rlock a {
a.clone()
}
assert b[0] == "test"
}