From a187a4abb3c902b1e1be9fbf629b54c2e3bc8358 Mon Sep 17 00:00:00 2001 From: yuyi Date: Wed, 10 Mar 2021 19:53:23 +0800 Subject: [PATCH] checker: check non-optional fn return or_block (#9227) --- vlib/v/checker/checker.v | 9 +++++++++ vlib/v/checker/tests/fn_return_or_err.out | 7 +++++++ vlib/v/checker/tests/fn_return_or_err.vv | 13 +++++++++++++ 3 files changed, 29 insertions(+) create mode 100644 vlib/v/checker/tests/fn_return_or_err.out create mode 100644 vlib/v/checker/tests/fn_return_or_err.vv diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 4d0dee42a4..295e46b3ee 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -3693,6 +3693,15 @@ pub fn (mut c Checker) expr(node ast.Expr) table.Type { } ast.CallExpr { mut ret_type := c.call_expr(mut node) + if !ret_type.has_flag(.optional) { + if node.or_block.kind == .block { + c.error('unexpected `or` block, the function `$node.name` does not return an optional', + node.or_block.pos) + } else if node.or_block.kind == .propagate { + c.error('unexpected `?`, the function `$node.name` does not return an optional', + node.or_block.pos) + } + } if ret_type.has_flag(.optional) && node.or_block.kind != .absent { ret_type = ret_type.clear_flag(.optional) } diff --git a/vlib/v/checker/tests/fn_return_or_err.out b/vlib/v/checker/tests/fn_return_or_err.out new file mode 100644 index 0000000000..ebb4494d27 --- /dev/null +++ b/vlib/v/checker/tests/fn_return_or_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/fn_return_or_err.vv:6:17: error: unexpected `or` block, the function `pop` does not return an optional + 4 | + 5 | pub fn next(mut v []Typ) Typ { + 6 | return v.pop() or { Typ{} } + | ~~~~~~~~~~~~ + 7 | } + 8 | diff --git a/vlib/v/checker/tests/fn_return_or_err.vv b/vlib/v/checker/tests/fn_return_or_err.vv new file mode 100644 index 0000000000..c303b0aa69 --- /dev/null +++ b/vlib/v/checker/tests/fn_return_or_err.vv @@ -0,0 +1,13 @@ +module main + +pub struct Typ {} + +pub fn next(mut v []Typ) Typ { + return v.pop() or { Typ{} } +} + +fn main() { + mut v := [Typ{}] + last := next(mut v) + println('$last') +}