From c1904ecab7e2b05dcf36533832ed9d890f93a2d6 Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 10 Jan 2024 21:53:41 +0800 Subject: [PATCH] parser, checker: check invalid lambda expr (#20461) --- vlib/v/checker/errors.v | 10 ++++++++++ vlib/v/checker/lambda_expr.v | 4 ++-- .../checker/tests/lambda_expression_in_map.out | 4 ++-- .../tests/lambda_expression_invalid.out | 7 +++++++ .../checker/tests/lambda_expression_invalid.vv | 5 +++++ .../tests/lambda_undefined_variables_err.out | 18 +++++++++--------- vlib/v/parser/expr.v | 2 +- 7 files changed, 36 insertions(+), 14 deletions(-) create mode 100644 vlib/v/checker/tests/lambda_expression_invalid.out create mode 100644 vlib/v/checker/tests/lambda_expression_invalid.vv diff --git a/vlib/v/checker/errors.v b/vlib/v/checker/errors.v index 6a440080d..e9b463751 100644 --- a/vlib/v/checker/errors.v +++ b/vlib/v/checker/errors.v @@ -41,6 +41,16 @@ fn (mut c Checker) error(message string, pos token.Pos) { c.warn_or_error(msg, pos, false) } +fn (mut c Checker) fatal(message string, pos token.Pos) { + if (c.pref.translated || c.file.is_translated) && message.starts_with('mismatched types') { + // TODO move this + return + } + msg := message.replace('`Array_', '`[]') + c.pref.fatal_errors = true + c.warn_or_error(msg, pos, false) +} + fn (mut c Checker) note(message string, pos token.Pos) { if c.pref.message_limit >= 0 && c.nr_notices >= c.pref.message_limit { c.should_abort = true diff --git a/vlib/v/checker/lambda_expr.v b/vlib/v/checker/lambda_expr.v index 54797b024..4b95dd281 100644 --- a/vlib/v/checker/lambda_expr.v +++ b/vlib/v/checker/lambda_expr.v @@ -7,8 +7,8 @@ pub fn (mut c Checker) lambda_expr(mut node ast.LambdaExpr, exp_typ ast.Type) as if node.is_checked { return node.typ } - if exp_typ == 0 { - c.error('lambda expressions are allowed only in places expecting function callbacks', + if exp_typ in [0, ast.void_type] { + c.fatal('lambda expressions are allowed only in places expecting function callbacks', node.pos) return ast.void_type } diff --git a/vlib/v/checker/tests/lambda_expression_in_map.out b/vlib/v/checker/tests/lambda_expression_in_map.out index f9d567329..d5c0b02da 100644 --- a/vlib/v/checker/tests/lambda_expression_in_map.out +++ b/vlib/v/checker/tests/lambda_expression_in_map.out @@ -2,7 +2,7 @@ vlib/v/checker/tests/lambda_expression_in_map.vv:3:12: error: lambda expressions 1 | a := [4, 5] 2 | dump(a.map(it)) 3 | dump(a.map(|| 5)) - | ~~ + | ~~~~ 4 | dump(a.map(|x| 5 * x)) 5 | dump(a.map(|x| x)) vlib/v/checker/tests/lambda_expression_in_map.vv:3:8: error: dump expression can not be void @@ -16,7 +16,7 @@ vlib/v/checker/tests/lambda_expression_in_map.vv:6:12: error: lambda expressions 4 | dump(a.map(|x| 5 * x)) 5 | dump(a.map(|x| x)) 6 | dump(a.map(|x, y| x)) - | ^ + | ~~~~~~~~ vlib/v/checker/tests/lambda_expression_in_map.vv:6:8: error: dump expression can not be void 4 | dump(a.map(|x| 5 * x)) 5 | dump(a.map(|x| x)) diff --git a/vlib/v/checker/tests/lambda_expression_invalid.out b/vlib/v/checker/tests/lambda_expression_invalid.out new file mode 100644 index 000000000..726abbd8d --- /dev/null +++ b/vlib/v/checker/tests/lambda_expression_invalid.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/lambda_expression_invalid.vv:3:19: error: lambda expressions are allowed only in places expecting function callbacks + 1 | fn main() { + 2 | x := 5 + 3 | f := if x == 5 { |x| x - 5 } else { |x| x } + | ~~~~~~~~~ + 4 | println(f(x)) + 5 | } diff --git a/vlib/v/checker/tests/lambda_expression_invalid.vv b/vlib/v/checker/tests/lambda_expression_invalid.vv new file mode 100644 index 000000000..0f259ecd8 --- /dev/null +++ b/vlib/v/checker/tests/lambda_expression_invalid.vv @@ -0,0 +1,5 @@ +fn main() { + x := 5 + f := if x == 5 { |x| x - 5 } else { |x| x } + println(f(x)) +} diff --git a/vlib/v/checker/tests/lambda_undefined_variables_err.out b/vlib/v/checker/tests/lambda_undefined_variables_err.out index ba91e8931..db0cd3f47 100644 --- a/vlib/v/checker/tests/lambda_undefined_variables_err.out +++ b/vlib/v/checker/tests/lambda_undefined_variables_err.out @@ -1,33 +1,33 @@ vlib/v/checker/tests/lambda_undefined_variables_err.vv:7:2: warning: unused variable: `s2` 5 | f(|x| s1) - 6 | + 6 | 7 | s2 := 'abc' | ~~ 8 | f(|x| s2) 9 | } vlib/v/checker/tests/lambda_undefined_variables_err.vv:5:8: error: undefined ident: `s1` - 3 | + 3 | 4 | fn main() { 5 | f(|x| s1) | ~~ - 6 | + 6 | 7 | s2 := 'abc' vlib/v/checker/tests/lambda_undefined_variables_err.vv:5:4: error: `s1` used as value - 3 | + 3 | 4 | fn main() { 5 | f(|x| s1) - | ^ - 6 | + | ~~~~~~ + 6 | 7 | s2 := 'abc' vlib/v/checker/tests/lambda_undefined_variables_err.vv:8:8: error: undefined variable `s2` - 6 | + 6 | 7 | s2 := 'abc' 8 | f(|x| s2) | ~~ 9 | } vlib/v/checker/tests/lambda_undefined_variables_err.vv:8:4: error: `s2` used as value - 6 | + 6 | 7 | s2 := 'abc' 8 | f(|x| s2) - | ^ + | ~~~~~~ 9 | } diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index d82130d22..9e842cef5 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -900,7 +900,7 @@ fn (mut p Parser) lambda_expr() ?ast.LambdaExpr { e := p.expr(0) pos_end := p.tok.pos() return ast.LambdaExpr{ - pos: pos + pos: pos.extend(e.pos()) pos_expr: pos_expr pos_end: pos_end params: params -- 2.39.5