diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b28ea4965f..140760b3c6 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -2511,7 +2511,11 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { } mut ident_var_info := left.info as ast.IdentVar if ident_var_info.share == .shared_t { + if left_type.nr_muls() > 1 { + c.error('shared cannot be multi level reference', left.pos) + } left_type = left_type.set_flag(.shared_f) + left_type = left_type.set_nr_muls(1) } if ident_var_info.share == .atomic_t { left_type = left_type.set_flag(.atomic_f) @@ -2590,7 +2594,8 @@ pub fn (mut c Checker) assign_stmt(mut assign_stmt ast.AssignStmt) { c.error('cannot assign to `$left`: ' + c.expected_msg(right_type_unwrapped, left_type_unwrapped), right.position()) } - if (right is ast.StructInit || !right_is_ptr) && !right_sym.is_number() { + if (right is ast.StructInit || !right_is_ptr) && !(right_sym.is_number() + || left_type.has_flag(.shared_f)) { left_name := c.table.type_to_str(left_type_unwrapped) mut rtype := right_type_unwrapped if rtype.is_ptr() { diff --git a/vlib/v/gen/cgen.v b/vlib/v/gen/cgen.v index da4a8ebbd8..48fa117322 100644 --- a/vlib/v/gen/cgen.v +++ b/vlib/v/gen/cgen.v @@ -4693,13 +4693,13 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { g.is_amp = false // reset the flag immediately so that other struct inits in this expr are handled correctly if is_amp { g.out.go_back(1) // delete the `&` already generated in `prefix_expr() - if g.is_shared { - mut shared_typ := struct_init.typ.set_flag(.shared_f) - shared_styp = g.typ(shared_typ) - g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.val = ($styp){') - } else { - g.write('($styp*)memdup(&($styp){') - } + } + if g.is_shared { + mut shared_typ := struct_init.typ.set_flag(.shared_f) + shared_styp = g.typ(shared_typ) + g.writeln('($shared_styp*)__dup${shared_styp}(&($shared_styp){.val = ($styp){') + } else if is_amp { + g.write('($styp*)memdup(&($styp){') } else if struct_init.typ.is_ptr() { basetyp := g.typ(struct_init.typ.set_nr_muls(0)) if is_multiline { @@ -4708,10 +4708,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { g.write('&($basetyp){') } } else { - if g.is_shared { - // TODO: non-ref shared should be forbidden - g.writeln('{.val = {') - } else if is_multiline { + if is_multiline { g.writeln('($styp){') } else { g.write('($styp){') @@ -4870,10 +4867,7 @@ fn (mut g Gen) struct_init(struct_init ast.StructInit) { } g.write('}') if g.is_shared { - g.write('}') - if is_amp { - g.write(', sizeof($shared_styp))') - } + g.write('}, sizeof($shared_styp))') } else if is_amp { g.write(', sizeof($styp))') } diff --git a/vlib/v/tests/shared_lock_test.v b/vlib/v/tests/shared_lock_test.v index 7f3b4ec2a7..f848e63f2a 100644 --- a/vlib/v/tests/shared_lock_test.v +++ b/vlib/v/tests/shared_lock_test.v @@ -19,13 +19,13 @@ fn f(shared x St, shared y St, shared z St) { } fn test_shared_lock() { - shared x := &St{ + shared x := St{ a: 5 } shared y := &St{ a: 7 } - shared z := &St{ + shared z := St{ a: 1 } go f(shared x, shared y, shared z)