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') +}