From 3c08f655af049286ed56318fb16d654dd548c675 Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Sun, 26 Apr 2020 10:35:10 +0200 Subject: [PATCH] parser: do not allow mutable simple args --- vlib/v/parser/fn.v | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 19bbea336a..c4b9b8f29a 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -109,13 +109,13 @@ fn (mut p Parser) fn_decl() ast.FnDecl { is_method = true rec_mut = p.tok.kind in [.key_var, .key_mut] if rec_mut { - p.next() // `var` + p.next() // `mut` } rec_name = p.check_name() if !rec_mut { rec_mut = p.tok.kind == .key_mut } - is_amp := p.peek_tok.kind == .amp + is_amp := p.tok.kind == .amp // if rec_mut { // p.check(.key_mut) // } @@ -123,7 +123,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // or should it be a property of the arg, like this ptr/mut becomes indistinguishable rec_type = p.parse_type_with_mut(rec_mut) if is_amp && rec_mut { - p.error('use `(f mut Foo)` or `(f &Foo)` instead of `(f mut &Foo)`') + p.error('use `(mut f Foo)` or `(f &Foo)` instead of `(mut f &Foo)`') } args << table.Arg{ name: rec_name @@ -157,12 +157,24 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // Args args2, is_variadic := p.fn_args() args << args2 - for arg in args { + for i, arg in args { p.scope.register(arg.name, ast.Var{ name: arg.name typ: arg.typ is_mut: arg.is_mut }) + // Do not allow `mut` with simple types + // TODO move to checker? + if arg.is_mut { + if i == 0 && is_method { + continue + } + sym := p.table.get_type_symbol(arg.typ) + if sym.kind !in [.array, .struct_, .map, .placeholder] { + p.error('mutable arguments are only allowed for arrays, maps, and structs\n' + + 'return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`') + } + } } mut end_pos := p.prev_tok.position() // Return type