Merge 004ee0ac25 into c5d8d27b90
commit
f0e2444416
|
|
@ -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
|
// TODO: remove this for actual methods, use only for compiler magic
|
||||||
// FIXME: Argument count != 1 will break these
|
// FIXME: Argument count != 1 will break these
|
||||||
if left_sym.kind == .array && method_name in array_builtin_methods {
|
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))
|
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)
|
} else if (left_sym.kind == .map || final_left_sym.kind == .map)
|
||||||
&& method_name in ['clone', 'keys', 'move', 'delete'] {
|
&& 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 {
|
if left_sym.kind == .map {
|
||||||
return c.map_builtin_method_call(mut node, left_type, left_sym)
|
return c.map_builtin_method_call(mut node, left_type, left_sym)
|
||||||
} else {
|
} 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)
|
return c.map_builtin_method_call(mut node, parent_type, final_left_sym)
|
||||||
}
|
}
|
||||||
} else if left_sym.kind == .array && method_name in ['insert', 'prepend'] {
|
} 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 method_name == 'insert' {
|
||||||
if node.args.len != 2 {
|
if node.args.len != 2 {
|
||||||
c.error('`array.insert()` should have 2 arguments, e.g. `insert(1, val)`',
|
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())
|
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'] {
|
} 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 {
|
if final_left_sym.info is ast.Array {
|
||||||
node.return_type = final_left_sym.info.elem_type
|
node.return_type = final_left_sym.info.elem_type
|
||||||
return node.return_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 {
|
} else {
|
||||||
ret_type = left_type
|
ret_type = left_type
|
||||||
}
|
}
|
||||||
|
ret_type = ret_type.clear_flag(.shared_f)
|
||||||
}
|
}
|
||||||
'keys' {
|
'keys' {
|
||||||
info := left_sym.info as ast.Map
|
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 {}
|
else {}
|
||||||
}
|
}
|
||||||
node.receiver_type = left_type.ref()
|
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
|
node.return_type = ret_type
|
||||||
return node.return_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 {
|
} else {
|
||||||
node.return_type = node.receiver_type.set_nr_muls(0)
|
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' {
|
} else if method_name == 'sort' {
|
||||||
node.return_type = ast.void_type
|
node.return_type = ast.void_type
|
||||||
} else if method_name == 'contains' {
|
} 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
|
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
|
return node.return_type
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -404,7 +404,9 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
||||||
if node.args.len == 0 {
|
if node.args.len == 0 {
|
||||||
comparison_type = g.unwrap(info.elem_type.set_nr_muls(0))
|
comparison_type = g.unwrap(info.elem_type.set_nr_muls(0))
|
||||||
shared a := g.array_sort_fn
|
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 {
|
if compare_fn in array_sort_fn {
|
||||||
g.gen_array_sort_call(node, compare_fn)
|
g.gen_array_sort_call(node, compare_fn)
|
||||||
return
|
return
|
||||||
|
|
@ -425,7 +427,9 @@ fn (mut g Gen) gen_array_sort(node ast.CallExpr) {
|
||||||
compare_fn += '_reverse'
|
compare_fn += '_reverse'
|
||||||
}
|
}
|
||||||
shared a := g.array_sort_fn
|
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 {
|
if compare_fn in array_sort_fn {
|
||||||
g.gen_array_sort_call(node, compare_fn)
|
g.gen_array_sort_call(node, compare_fn)
|
||||||
return
|
return
|
||||||
|
|
|
||||||
|
|
@ -984,7 +984,9 @@ fn (mut g Gen) register_optional(t ast.Type) string {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn (mut g Gen) write_optionals() {
|
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 {
|
for base, styp in g.optionals {
|
||||||
if base in done {
|
if base in done {
|
||||||
continue
|
continue
|
||||||
|
|
|
||||||
|
|
@ -1046,7 +1046,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
if !node.left.is_lvalue() {
|
if !node.left.is_lvalue() {
|
||||||
g.write('ADDR($rec_cc_type, ')
|
g.write('ADDR($rec_cc_type, ')
|
||||||
has_cast = true
|
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('&')
|
g.write('&')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
@ -1102,7 +1103,8 @@ fn (mut g Gen) method_call(node ast.CallExpr) {
|
||||||
}
|
}
|
||||||
g.write(embed_name)
|
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')
|
g.write('->val')
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -50,3 +50,27 @@ fn test_shared_receiver_lock() {
|
||||||
assert x.a == 7 && y.a == 5
|
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
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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"
|
||||||
|
}
|
||||||
Loading…
Reference in New Issue