From 904f984367a341a8698779a6539b79462622adc4 Mon Sep 17 00:00:00 2001 From: Felipe Pena Date: Fri, 3 Mar 2023 03:30:44 -0300 Subject: [PATCH] checker: fix or-block expected type checking (#17469) --- vlib/v/checker/checker.v | 8 ++++---- .../tests/option_return_call_non_opt_err.out | 7 +++++++ .../tests/option_return_call_non_opt_err.vv | 17 +++++++++++++++++ .../option_return_selector_non_opt_err.out | 7 +++++++ .../tests/option_return_selector_non_opt_err.vv | 17 +++++++++++++++++ 5 files changed, 52 insertions(+), 4 deletions(-) create mode 100644 vlib/v/checker/tests/option_return_call_non_opt_err.out create mode 100644 vlib/v/checker/tests/option_return_call_non_opt_err.vv create mode 100644 vlib/v/checker/tests/option_return_selector_non_opt_err.out create mode 100644 vlib/v/checker/tests/option_return_selector_non_opt_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index b79a44503..e5daa0e4e 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -1119,12 +1119,12 @@ fn (mut c Checker) check_or_last_stmt(stmt ast.Stmt, ret_type ast.Type, expr_ret c.expected_or_type = ret_type.clear_flag(.option).clear_flag(.result) last_stmt_typ := c.expr(stmt.expr) - if stmt.expr is ast.Ident { - if ret_type.has_flag(.option) && last_stmt_typ.has_flag(.option) { - expected_type_name := c.table.type_to_str(expr_return_type) + if ret_type.has_flag(.option) && last_stmt_typ.has_flag(.option) { + if stmt.expr in [ast.Ident, ast.SelectorExpr, ast.CallExpr] { + expected_type_name := c.table.type_to_str(ret_type.clear_flag(.option).clear_flag(.result)) got_type_name := c.table.type_to_str(last_stmt_typ) c.error('`or` block must provide a value of type `${expected_type_name}`, not `${got_type_name}`', - stmt.expr.pos) + stmt.expr.pos()) return } } diff --git a/vlib/v/checker/tests/option_return_call_non_opt_err.out b/vlib/v/checker/tests/option_return_call_non_opt_err.out new file mode 100644 index 000000000..4864817bf --- /dev/null +++ b/vlib/v/checker/tests/option_return_call_non_opt_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/option_return_call_non_opt_err.vv:11:22: error: `or` block must provide a value of type `int`, not `?int` + 9 | + 10 | fn (f Foo) get(param ?int) ?int { + 11 | return param or { f.get(1) } + | ~~~~~~ + 12 | } + 13 | diff --git a/vlib/v/checker/tests/option_return_call_non_opt_err.vv b/vlib/v/checker/tests/option_return_call_non_opt_err.vv new file mode 100644 index 000000000..329df2721 --- /dev/null +++ b/vlib/v/checker/tests/option_return_call_non_opt_err.vv @@ -0,0 +1,17 @@ +interface IFoo { + age ?int + get(param ?int) ?int +} + +struct Foo { + age ?int +} + +fn (f Foo) get(param ?int) ?int { + return param or { f.get(1) } +} + +foo := IFoo(Foo{ + age: 100 +}) +println(foo.get(100)) diff --git a/vlib/v/checker/tests/option_return_selector_non_opt_err.out b/vlib/v/checker/tests/option_return_selector_non_opt_err.out new file mode 100644 index 000000000..a0c88233b --- /dev/null +++ b/vlib/v/checker/tests/option_return_selector_non_opt_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/option_return_selector_non_opt_err.vv:11:22: error: `or` block must provide a value of type `int`, not `?int` + 9 | + 10 | fn (f Foo) get(param ?int) ?int { + 11 | return param or { f.age } + | ~~~ + 12 | } + 13 | diff --git a/vlib/v/checker/tests/option_return_selector_non_opt_err.vv b/vlib/v/checker/tests/option_return_selector_non_opt_err.vv new file mode 100644 index 000000000..356ce15b3 --- /dev/null +++ b/vlib/v/checker/tests/option_return_selector_non_opt_err.vv @@ -0,0 +1,17 @@ +interface IFoo { + age ?int + get(param ?int) ?int +} + +struct Foo { + age ?int +} + +fn (f Foo) get(param ?int) ?int { + return param or { f.age } +} + +foo := IFoo(Foo{ + age: 100 +}) +println(foo.get(100)) -- 2.39.5