diff --git a/vlib/v/checker/tests/function_arg_mutable_err.out b/vlib/v/checker/tests/function_arg_mutable_err.out new file mode 100644 index 0000000000..7b57886ac2 --- /dev/null +++ b/vlib/v/checker/tests/function_arg_mutable_err.out @@ -0,0 +1,6 @@ +vlib/v/checker/tests/function_arg_mutable_err.v:1:18: error: mutable arguments are only allowed for arrays, maps, and structs +return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {` + 1 | fn mod_ptr(mut a int) { + | ~~~ + 2 | a = 77 + 3 | } diff --git a/vlib/v/checker/tests/function_arg_mutable_err.vv b/vlib/v/checker/tests/function_arg_mutable_err.vv new file mode 100644 index 0000000000..30165cbda4 --- /dev/null +++ b/vlib/v/checker/tests/function_arg_mutable_err.vv @@ -0,0 +1,8 @@ +fn mod_ptr(mut a int) { + a = 77 +} + +fn main() { + println('hello') +} + diff --git a/vlib/v/checker/tests/mut_int.out b/vlib/v/checker/tests/mut_int.out index 3a6e0823f6..a79bd19f43 100644 --- a/vlib/v/checker/tests/mut_int.out +++ b/vlib/v/checker/tests/mut_int.out @@ -1,6 +1,6 @@ -vlib/v/checker/tests/mut_int.v:1:12: error: mutable arguments are only allowed for arrays, maps, and structs +vlib/v/checker/tests/mut_int.v:1:14: error: mutable arguments are only allowed for arrays, maps, and structs return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {` 1 | fn foo(mut x int) { - | ^ + | ~~~ 2 | } 3 | diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index 707f3ef8ad..86d754547d 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -202,7 +202,7 @@ fn (mut p Parser) fn_decl() ast.FnDecl { // Args args2, is_variadic := p.fn_args() args << args2 - for i, arg in args { + for arg in args { if p.scope.known_var(arg.name) { p.error_with_pos('redefinition of parameter `$arg.name`', arg.pos) } @@ -214,19 +214,6 @@ fn (mut p Parser) fn_decl() ast.FnDecl { is_used: true is_arg: true }) - // 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] && arg.typ != table.t_type && !arg.typ.is_ptr() { - if sym.kind !in [.array, .struct_, .map, .placeholder] && arg.typ != table.t_type { - p.error_with_pos('mutable arguments are only allowed for arrays, maps, and structs\n' + - 'return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`', arg.pos) - } - } } mut end_pos := p.prev_tok.position() // Return type @@ -385,6 +372,7 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) { pos := p.tok.position() mut arg_type := p.parse_type() if is_mut && arg_type != table.t_type { + p.check_fn_mutable_arguments(arg_type, pos) // if arg_type.is_ptr() { // p.error('cannot mut') // } @@ -431,12 +419,10 @@ fn (mut p Parser) fn_args() ([]table.Arg, bool) { p.next() is_variadic = true } + pos := p.tok.position() mut typ := p.parse_type() if is_mut && typ != table.t_type { - if typ.is_ptr() { - // name := p.table.get_type_name(typ) - // p.warn('`$name` is already a reference, it cannot be marked as `mut`') - } + p.check_fn_mutable_arguments(typ, pos) typ = typ.set_nr_muls(1) } if is_variadic { @@ -468,6 +454,14 @@ fn (p &Parser) fileis(s string) bool { return p.file_name.contains(s) } +fn (mut p Parser) check_fn_mutable_arguments(typ table.Type, pos token.Position) { + sym := p.table.get_type_symbol(typ) + if sym.kind !in [.array, .struct_, .map, .placeholder] && !typ.is_ptr() { + p.error_with_pos('mutable arguments are only allowed for arrays, maps, and structs\n' + + 'return values instead: `fn foo(n mut int) {` => `fn foo(n int) int {`', pos) + } +} + fn (mut p Parser) fn_redefinition_error(name string) { // Find where this function was already declared // TODO