1
0
mirror of https://github.com/vlang/v.git synced 2023-08-10 21:13:21 +03:00

parser: do not allow mutable simple args

This commit is contained in:
Alexander Medvednikov 2020-04-26 10:35:10 +02:00
parent a56121c329
commit 3c08f655af

View File

@ -109,13 +109,13 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
is_method = true is_method = true
rec_mut = p.tok.kind in [.key_var, .key_mut] rec_mut = p.tok.kind in [.key_var, .key_mut]
if rec_mut { if rec_mut {
p.next() // `var` p.next() // `mut`
} }
rec_name = p.check_name() rec_name = p.check_name()
if !rec_mut { if !rec_mut {
rec_mut = p.tok.kind == .key_mut rec_mut = p.tok.kind == .key_mut
} }
is_amp := p.peek_tok.kind == .amp is_amp := p.tok.kind == .amp
// if rec_mut { // if rec_mut {
// p.check(.key_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 // or should it be a property of the arg, like this ptr/mut becomes indistinguishable
rec_type = p.parse_type_with_mut(rec_mut) rec_type = p.parse_type_with_mut(rec_mut)
if is_amp && 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{ args << table.Arg{
name: rec_name name: rec_name
@ -157,12 +157,24 @@ fn (mut p Parser) fn_decl() ast.FnDecl {
// Args // Args
args2, is_variadic := p.fn_args() args2, is_variadic := p.fn_args()
args << args2 args << args2
for arg in args { for i, arg in args {
p.scope.register(arg.name, ast.Var{ p.scope.register(arg.name, ast.Var{
name: arg.name name: arg.name
typ: arg.typ typ: arg.typ
is_mut: arg.is_mut 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() mut end_pos := p.prev_tok.position()
// Return type // Return type