diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 6462298127..fc97fff218 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -2548,7 +2548,7 @@ fn (mut g Gen) expr(node ast.Expr) { node.return_type.clear_flag(.optional) } mut shared_styp := '' - if g.is_shared { + if g.is_shared && !ret_type.has_flag(.shared_f) { ret_sym := g.table.get_type_symbol(ret_type) shared_typ := ret_type.set_flag(.shared_f) shared_styp = g.typ(shared_typ) @@ -2576,7 +2576,7 @@ fn (mut g Gen) expr(node ast.Expr) { g.strs_to_free0 = [] // println('pos=$node.pos.pos') } - if g.is_shared { + if g.is_shared && !ret_type.has_flag(.shared_f) { g.writeln('}, sizeof($shared_styp))') } // if g.autofree && node.autofree_pregen != '' { // g.strs_to_free0.len != 0 { diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index a66019969f..a80161eb8a 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -207,6 +207,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl { p.warn_with_pos('use `(mut f Foo)` instead of `(f mut Foo)`', lpar_pos.extend(p.peek_tok2.position())) } } + if p.tok.kind == .key_shared { + p.error_with_pos('use `(shared f Foo)` instead of `(f shared Foo)`', lpar_pos.extend(p.peek_tok2.position())) + } receiver_pos = rec_start_pos.extend(p.tok.position()) is_amp := p.tok.kind == .amp if p.tok.kind == .name && p.tok.lit == 'JS' { @@ -685,6 +688,9 @@ fn (mut p Parser) fn_args() ([]table.Param, bool, bool) { } is_mut = true } + if p.tok.kind == .key_shared { + p.error_with_pos('use `shared f Foo` instead of `f shared Foo`', p.tok.position()) + } if p.tok.kind == .ellipsis { p.next() is_variadic = true diff --git a/vlib/v/tests/fn_shared_return_test.v b/vlib/v/tests/fn_shared_return_test.v new file mode 100644 index 0000000000..99391f06dc --- /dev/null +++ b/vlib/v/tests/fn_shared_return_test.v @@ -0,0 +1,54 @@ +struct St { +mut: + x f64 +} + +fn f() shared St { + shared x := St{ x: 3.25 } + return x +} + +fn g(good bool) ?shared St { + if !good { + return error('no shared St created') + } + shared x := St{ x: 12.75 } + return x +} + +fn test_shared_fn_return() { + shared x := f() + val := rlock x { x.x } + assert val == 3.25 +} + +fn shared_opt_propagate(good bool) ?f64 { + shared x := g(good) ? + ret := rlock x { x.x } + return ret +} + +fn test_shared_opt_propagate() { + x := shared_opt_propagate(true) or { 1.25 } + y := shared_opt_propagate(false) or { 2.125 } + assert x == 12.75 + assert y == 2.125 +} + +fn test_shared_opt_good() { + shared yy := g(true) or { + shared my_default := St{ x: 37.5 } + my_default + } + val := rlock yy { yy.x } + assert val == 12.75 +} + +fn test_shared_opt_bad() { + shared yy := g(false) or { + shared my_default := St{ x: 37.5 } + my_default + } + val := rlock yy { yy.x } + assert val == 37.5 +} diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v index 3e10def019..5229da2e81 100644 --- a/vlib/v/token/token.v +++ b/vlib/v/token/token.v @@ -427,7 +427,7 @@ pub fn (tok Kind) is_relational() bool { } pub fn (k Kind) is_start_of_type() bool { - return k in [.name, .lpar, .amp, .lsbr, .question] + return k in [.name, .lpar, .amp, .lsbr, .question, .key_shared] } pub fn (kind Kind) is_prefix() bool {