From c0e56d10c30d5000705d38a9229cce0abc2abe74 Mon Sep 17 00:00:00 2001 From: Nick Treleaven Date: Tue, 5 Jan 2021 00:32:24 +0000 Subject: [PATCH] parser: add errors for invalid anonymous function (#7786) --- vlib/v/parser/fn.v | 16 ++++++++++++++-- vlib/v/parser/tests/anon_fn_return_type.out | 6 ++++++ vlib/v/parser/tests/anon_fn_return_type.vv | 8 ++++++++ vlib/v/token/token.v | 3 ++- 4 files changed, 30 insertions(+), 3 deletions(-) create mode 100644 vlib/v/parser/tests/anon_fn_return_type.out create mode 100644 vlib/v/parser/tests/anon_fn_return_type.vv diff --git a/vlib/v/parser/fn.v b/vlib/v/parser/fn.v index c8697f69c6..b1fedca941 100644 --- a/vlib/v/parser/fn.v +++ b/vlib/v/parser/fn.v @@ -443,12 +443,24 @@ fn (mut p Parser) anon_fn() ast.AnonFn { is_arg: true }) } + mut same_line := p.tok.line_nr == p.prev_tok.line_nr mut return_type := table.void_type - if p.tok.kind.is_start_of_type() { - return_type = p.parse_type() + // lpar: multiple return types + if same_line { + if p.tok.kind.is_start_of_type() { + return_type = p.parse_type() + } else if p.tok.kind != .lcbr { + p.error_with_pos('expected return type, not $p.tok for anonymous function', + p.tok.position()) + } } mut stmts := []ast.Stmt{} no_body := p.tok.kind != .lcbr + same_line = p.tok.line_nr == p.prev_tok.line_nr + if no_body && same_line { + p.error_with_pos('unexpected `$p.tok.kind` after anonymous function signature, expecting `{`', + p.tok.position()) + } if p.tok.kind == .lcbr { stmts = p.parse_block_no_scope(false) } diff --git a/vlib/v/parser/tests/anon_fn_return_type.out b/vlib/v/parser/tests/anon_fn_return_type.out new file mode 100644 index 0000000000..bbc18cabd5 --- /dev/null +++ b/vlib/v/parser/tests/anon_fn_return_type.out @@ -0,0 +1,6 @@ +vlib/v/parser/tests/anon_fn_return_type.vv:7:22: error: expected return type, not string "hi" for anonymous function + 5 | _ = fn (name string) flag.Flag + 6 | _ = fn (name string) flag.Flag {return {}} + 7 | _ = fn (name string) "hi" + name + | ~~~~ + 8 | diff --git a/vlib/v/parser/tests/anon_fn_return_type.vv b/vlib/v/parser/tests/anon_fn_return_type.vv new file mode 100644 index 0000000000..028d76e14c --- /dev/null +++ b/vlib/v/parser/tests/anon_fn_return_type.vv @@ -0,0 +1,8 @@ +import flag + +_ = fn (name string) +_ = fn (name string) {} +_ = fn (name string) flag.Flag +_ = fn (name string) flag.Flag {return {}} +_ = fn (name string) "hi" + name + diff --git a/vlib/v/token/token.v b/vlib/v/token/token.v index 470e7d561e..7d4a7dec4d 100644 --- a/vlib/v/token/token.v +++ b/vlib/v/token/token.v @@ -437,7 +437,8 @@ pub fn (kind Kind) is_infix() bool { pub fn (tok &Token) can_start_type(builtin_type_names []string) bool { match tok.kind { .name { return tok.lit[0].is_capital() || tok.lit in builtin_type_names } - .amp, .lsbr, .question { return true } + // Note: return type (T1, T2) should be handled elsewhere + .amp, .key_fn, .lsbr, .question { return true } else {} } return false