mirror of
https://github.com/vlang/v.git
synced 2025-09-08 14:51:53 -04:00
checker, cgen: allow for a shared variable, to be whole reassigned (keeping the same mutex state) (fix #15649) (#19751)
This commit is contained in:
parent
f82529e020
commit
510f0915b1
@ -127,6 +127,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
is_blank_ident := left.is_blank_ident()
|
||||
mut left_type := ast.void_type
|
||||
mut var_option := false
|
||||
mut is_shared_re_assign := false
|
||||
if !is_decl && !is_blank_ident {
|
||||
if left in [ast.Ident, ast.SelectorExpr] {
|
||||
c.prevent_sum_type_unwrapping_once = true
|
||||
@ -137,6 +138,9 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
left_type = c.expr(mut left)
|
||||
c.is_index_assign = false
|
||||
c.expected_type = c.unwrap_generic(left_type)
|
||||
is_shared_re_assign = left is ast.Ident && left.info is ast.IdentVar
|
||||
&& ((left.info as ast.IdentVar).share == .shared_t || left_type.has_flag(.shared_f))
|
||||
&& c.table.sym(left_type).kind in [.array, .map, .struct_]
|
||||
}
|
||||
if c.inside_comptime_for_field && mut left is ast.ComptimeSelector {
|
||||
left_type = c.comptime_fields_default_type
|
||||
@ -181,7 +185,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
} else if right is ast.ComptimeSelector {
|
||||
right_type = c.comptime_fields_default_type
|
||||
}
|
||||
if is_decl {
|
||||
if is_decl || is_shared_re_assign {
|
||||
// check generic struct init and return unwrap generic struct type
|
||||
if mut right is ast.StructInit {
|
||||
if right.typ.has_flag(.generic) {
|
||||
@ -283,7 +287,7 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
} else if left.info !is ast.IdentVar {
|
||||
c.error('cannot assign to ${left.kind} `${left.name}`', left.pos)
|
||||
} else {
|
||||
if is_decl {
|
||||
if is_decl || is_shared_re_assign {
|
||||
c.check_valid_snake_case(left.name, 'variable name', left.pos)
|
||||
if reserved_type_names_chk.matches(left.name) {
|
||||
c.error('invalid use of reserved type `${left.name}` as a variable name',
|
||||
@ -301,9 +305,9 @@ fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) {
|
||||
}
|
||||
}
|
||||
mut ident_var_info := left.info as ast.IdentVar
|
||||
if ident_var_info.share == .shared_t {
|
||||
if ident_var_info.share == .shared_t || is_shared_re_assign {
|
||||
left_type = left_type.set_flag(.shared_f)
|
||||
if is_decl {
|
||||
if is_decl || is_shared_re_assign {
|
||||
if left_type.nr_muls() > 1 {
|
||||
c.error('shared cannot be multi level reference', left.pos)
|
||||
}
|
||||
|
@ -459,6 +459,8 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
mut op_overloaded := false
|
||||
mut op_expected_left := ast.Type(0)
|
||||
mut op_expected_right := ast.Type(0)
|
||||
is_shared_re_assign := !is_decl && node.left_types[i].has_flag(.shared_f)
|
||||
&& left is ast.Ident && left_sym.kind in [.array, .map, .struct_]
|
||||
if node.op == .plus_assign && unaliased_right_sym.kind == .string {
|
||||
if mut left is ast.IndexExpr {
|
||||
if g.table.sym(left.left_type).kind == .array_fixed {
|
||||
@ -608,11 +610,11 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
if left in [ast.Ident, ast.SelectorExpr] {
|
||||
g.prevent_sum_type_unwrapping_once = true
|
||||
}
|
||||
if !is_fixed_array_var || is_decl {
|
||||
if !is_fixed_array_var || is_decl || is_shared_re_assign {
|
||||
if op_overloaded {
|
||||
g.op_arg(left, op_expected_left, var_type)
|
||||
} else {
|
||||
if !is_decl && left.is_auto_deref_var() {
|
||||
if !is_decl && !is_shared_re_assign && left.is_auto_deref_var() {
|
||||
g.write('*')
|
||||
}
|
||||
g.expr(left)
|
||||
@ -728,7 +730,8 @@ fn (mut g Gen) assign_stmt(node_ ast.AssignStmt) {
|
||||
if op_overloaded {
|
||||
g.op_arg(val, op_expected_right, val_type)
|
||||
} else {
|
||||
exp_type := if left.is_auto_deref_var() || var_type.has_flag(.shared_f) {
|
||||
exp_type := if var_type.is_ptr()
|
||||
&& (left.is_auto_deref_var() || var_type.has_flag(.shared_f)) {
|
||||
var_type.deref()
|
||||
} else {
|
||||
var_type
|
||||
|
36
vlib/v/tests/shared_re_assign_test.v
Normal file
36
vlib/v/tests/shared_re_assign_test.v
Normal file
@ -0,0 +1,36 @@
|
||||
fn test_re_assign_array() {
|
||||
shared arr := [1, 2, 3]
|
||||
lock arr {
|
||||
arr[0] = 0
|
||||
assert arr == [0, 2, 3]
|
||||
arr = [0, 0, 0]
|
||||
assert arr == [0, 0, 0]
|
||||
}
|
||||
}
|
||||
|
||||
struct Foo {
|
||||
mut:
|
||||
a int
|
||||
}
|
||||
|
||||
fn test_re_assign_struct() {
|
||||
shared st := Foo{}
|
||||
lock st {
|
||||
st.a = 1
|
||||
assert st.a == 1
|
||||
st = Foo{2}
|
||||
assert st.a == 2
|
||||
}
|
||||
}
|
||||
|
||||
fn test_re_assign_map() {
|
||||
shared m := map[int]int{}
|
||||
lock m {
|
||||
m[0] = 0
|
||||
assert m[0] == 0
|
||||
m = {
|
||||
0: 1
|
||||
}
|
||||
assert m[0] == 1
|
||||
}
|
||||
}
|
Loading…
x
Reference in New Issue
Block a user