diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 4d30f4d57f..26a663342e 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -353,7 +353,9 @@ fn (mut p Parser) fn_decl() ast.FnDecl { same_line := p.tok.line_nr == p.prev_tok.line_nr if (p.tok.kind.is_start_of_type() && (same_line || p.tok.kind != .lsbr)) || (same_line && p.tok.kind == .key_fn) { + p.inside_fn_return = true return_type = p.parse_type() + p.inside_fn_return = false return_type_pos = return_type_pos.extend(p.prev_tok.pos()) } mut type_sym_method_idx := 0 diff --git a/vlib/v/parser/parse_type.v b/vlib/v/parser/parse_type.v index af4b58ca3f..0adbeb8e2f 100644 --- a/vlib/v/parser/parse_type.v +++ b/vlib/v/parser/parse_type.v @@ -376,6 +376,9 @@ pub fn (mut p Parser) parse_type() ast.Type { p.register_auto_import('sync') } mut nr_muls := 0 + if p.inside_fn_return && p.tok.kind == .key_mut { + p.error_with_pos('cannot use `mut` on fn return type', p.tok.pos()) + } if p.tok.kind == .key_mut || is_shared || is_atomic { nr_muls++ p.next() diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 600bbbff7a..764ef19b7f 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -40,6 +40,7 @@ mut: inside_or_expr bool inside_for bool inside_fn bool // true even with implicit main + inside_fn_return bool inside_unsafe_fn bool inside_str_interp bool inside_array_lit bool diff --git a/vlib/v/parser/tests/fn_decl_return_type_err_a.out b/vlib/v/parser/tests/fn_decl_return_type_err_a.out new file mode 100644 index 0000000000..5f8f5260a4 --- /dev/null +++ b/vlib/v/parser/tests/fn_decl_return_type_err_a.out @@ -0,0 +1,7 @@ +vlib/v/parser/tests/fn_decl_return_type_err_a.vv:3:13: error: cannot use `mut` on fn return type + 1 | struct Foo{} + 2 | + 3 | fn maker() ?mut Foo { + | ~~~ + 4 | inner := &Foo{} + 5 | return *inner diff --git a/vlib/v/parser/tests/fn_decl_return_type_err_a.vv b/vlib/v/parser/tests/fn_decl_return_type_err_a.vv new file mode 100644 index 0000000000..fc1774d9f5 --- /dev/null +++ b/vlib/v/parser/tests/fn_decl_return_type_err_a.vv @@ -0,0 +1,9 @@ +struct Foo{} + +fn maker() ?mut Foo { + inner := &Foo{} + return *inner +} + +fn main() { +} diff --git a/vlib/v/parser/tests/fn_decl_return_type_err_b.out b/vlib/v/parser/tests/fn_decl_return_type_err_b.out new file mode 100644 index 0000000000..7fe7e8dde7 --- /dev/null +++ b/vlib/v/parser/tests/fn_decl_return_type_err_b.out @@ -0,0 +1,7 @@ +vlib/v/parser/tests/fn_decl_return_type_err_b.vv:3:13: error: cannot use `mut` on fn return type + 1 | struct Foo{} + 2 | + 3 | fn maker() (mut Foo) { + | ~~~ + 4 | inner := &Foo{} + 5 | return *inner diff --git a/vlib/v/parser/tests/fn_decl_return_type_err_b.vv b/vlib/v/parser/tests/fn_decl_return_type_err_b.vv new file mode 100644 index 0000000000..2b89efad64 --- /dev/null +++ b/vlib/v/parser/tests/fn_decl_return_type_err_b.vv @@ -0,0 +1,9 @@ +struct Foo{} + +fn maker() (mut Foo) { + inner := &Foo{} + return *inner +} + +fn main() { +}