From 2835a190e8d3a1ab87706f156b1c5a94aaa4cad7 Mon Sep 17 00:00:00 2001 From: crthpl <56052645+crthpl@users.noreply.github.com> Date: Thu, 19 May 2022 16:58:11 -0700 Subject: [PATCH] checker, cgen: fix shared non-decl assignment (#14466) --- vlib/v/checker/assign.v | 2 +- vlib/v/checker/containers.v | 6 +++++- vlib/v/gen/c/assign.v | 9 ++++++--- vlib/v/tests/assign_shared_test.v | 13 +++++++++++++ 4 files changed, 25 insertions(+), 5 deletions(-) create mode 100644 vlib/v/tests/assign_shared_test.v diff --git a/vlib/v/checker/assign.v b/vlib/v/checker/assign.v index 95313c55ba..21739730b6 100644 --- a/vlib/v/checker/assign.v +++ b/vlib/v/checker/assign.v @@ -224,7 +224,7 @@ pub fn (mut c Checker) assign_stmt(mut node ast.AssignStmt) { left_type = left_type.set_nr_muls(1) } } else if left_type.has_flag(.shared_f) { - left_type = left_type.clear_flag(.shared_f) + left_type = left_type.clear_flag(.shared_f).deref() } if ident_var_info.share == .atomic_t { left_type = left_type.set_flag(.atomic_f) diff --git a/vlib/v/checker/containers.v b/vlib/v/checker/containers.v index 16284444db..6de8281865 100644 --- a/vlib/v/checker/containers.v +++ b/vlib/v/checker/containers.v @@ -81,7 +81,11 @@ pub fn (mut c Checker) array_init(mut node ast.ArrayInit) ast.Type { array_info := type_sym.array_info() node.elem_type = array_info.elem_type // clear optional flag incase of: `fn opt_arr ?[]int { return [] }` - return c.expected_type.clear_flag(.optional) + return if c.expected_type.has_flag(.shared_f) { + c.expected_type.clear_flag(.shared_f).deref() + } else { + c.expected_type + }.clear_flag(.optional) } // [1,2,3] if node.exprs.len > 0 && node.elem_type == ast.void_type { diff --git a/vlib/v/gen/c/assign.v b/vlib/v/gen/c/assign.v index d5cb82dd7a..33ad955cac 100644 --- a/vlib/v/gen/c/assign.v +++ b/vlib/v/gen/c/assign.v @@ -389,6 +389,9 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) { g.write('*') } g.expr(left) + if !is_decl && var_type.has_flag(.shared_f) { + g.write('->val') // don't reset the mutex, just change the value + } } } } @@ -432,7 +435,6 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) { } */ } - g.is_shared = var_type.has_flag(.shared_f) if !cloned { if is_fixed_array_var { // TODO Instead of the translated check, check if it's a pointer already @@ -445,6 +447,7 @@ fn (mut g Gen) gen_assign_stmt(node_ ast.AssignStmt) { g.expr(val) g.write(', sizeof($typ_str))') } else if is_decl { + g.is_shared = var_type.has_flag(.shared_f) if is_fixed_array_init && !has_val { if val is ast.ArrayInit { g.array_init(val, ident.name) @@ -476,11 +479,11 @@ fn (mut g Gen) 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() { + exp_type := if left.is_auto_deref_var() || var_type.has_flag(.shared_f) { var_type.deref() } else { var_type - } + }.clear_flag(.shared_f) // don't reset the mutex, just change the value g.expr_with_cast(val, val_type, exp_type) } } diff --git a/vlib/v/tests/assign_shared_test.v b/vlib/v/tests/assign_shared_test.v new file mode 100644 index 0000000000..40f1aaf752 --- /dev/null +++ b/vlib/v/tests/assign_shared_test.v @@ -0,0 +1,13 @@ +struct AA { + a shared []int +} + +fn test_assign_shared() { + a := AA{[1]} + lock a.a { + a.a = []int{cap: 10} + } + lock a.a { + assert a.a == [] + } +}