From 53730d90df3bc9573701710bfa117bdd240d0e2e Mon Sep 17 00:00:00 2001 From: Alexander Medvednikov Date: Thu, 23 Apr 2026 18:24:14 +0300 Subject: [PATCH] checker: fix Error in return `none` from or block inside `match` (fixes #17422) --- vlib/v/checker/fn.v | 30 ++++++++++++++----- .../match_expr_returning_option_test.v | 22 ++++++++++++++ 2 files changed, 45 insertions(+), 7 deletions(-) diff --git a/vlib/v/checker/fn.v b/vlib/v/checker/fn.v index f21ee3279..f9f17f0d6 100644 --- a/vlib/v/checker/fn.v +++ b/vlib/v/checker/fn.v @@ -1421,13 +1421,29 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type { c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type) if node.or_block.kind == .block { - old_inside_or_block_value := c.inside_or_block_value - c.inside_or_block_value = true - last_cur_or_expr := c.cur_or_expr - c.cur_or_expr = &node.or_block - c.check_or_expr(node.or_block, typ, c.expected_or_type, node) - c.cur_or_expr = last_cur_or_expr - c.inside_or_block_value = old_inside_or_block_value + mut return_context_type := ast.no_type + if c.inside_return && c.table.cur_fn != unsafe { nil } && node.or_block.stmts.len > 0 { + last_stmt := node.or_block.stmts.last() + if last_stmt is ast.ExprStmt { + if last_stmt.typ == ast.none_type && c.table.cur_fn.return_type.has_flag(.option) { + return_context_type = c.table.cur_fn.return_type + } else if last_stmt.typ == ast.error_type + && c.table.cur_fn.return_type.has_flag(.result) { + return_context_type = c.table.cur_fn.return_type + } + } + } + if return_context_type != ast.no_type { + typ = return_context_type + } else { + old_inside_or_block_value := c.inside_or_block_value + c.inside_or_block_value = true + last_cur_or_expr := c.cur_or_expr + c.cur_or_expr = &node.or_block + c.check_or_expr(node.or_block, typ, c.expected_or_type, node) + c.cur_or_expr = last_cur_or_expr + c.inside_or_block_value = old_inside_or_block_value + } } c.expected_or_type = old_expected_or_type c.markused_call_expr(left_type, mut node) diff --git a/vlib/v/tests/conditions/matches/match_expr_returning_option_test.v b/vlib/v/tests/conditions/matches/match_expr_returning_option_test.v index 01f123f50..d5cb949e5 100644 --- a/vlib/v/tests/conditions/matches/match_expr_returning_option_test.v +++ b/vlib/v/tests/conditions/matches/match_expr_returning_option_test.v @@ -48,3 +48,25 @@ fn test_match_expr_returning_option_with_error() { println(ret) assert ret == 'zero' } + +fn match_expr_or_block_return_none(i int) ?int { + return match i { + 0 { 5 } + 1 { none } + else { match_expr_or_block_subfunc(i) or { none } } + } +} + +fn match_expr_or_block_subfunc(i int) !int { + if i == 2 { + return 2 + } + return error('subfunc error') +} + +fn test_match_expr_or_block_return_none() { + assert match_expr_or_block_return_none(0) or { panic(err) } == 5 + assert match_expr_or_block_return_none(2) or { panic(err) } == 2 + assert match_expr_or_block_return_none(1) == none + assert match_expr_or_block_return_none(3) == none +} -- 2.39.5