From 5e75c89b71e5aaa82cca0d04899d6b712587736e Mon Sep 17 00:00:00 2001 From: zakuro Date: Mon, 15 Nov 2021 17:29:58 +0900 Subject: [PATCH] checker: allow noreturn in if expr (#12462) --- vlib/v/checker/checker.v | 4 ++++ vlib/v/gen/c/cgen.v | 3 +++ vlib/v/tests/if_expression_test.v | 29 +++++++++++++++++++++++++++++ 3 files changed, 36 insertions(+) diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 20a6a7a229..a32cf99691 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -6870,6 +6870,10 @@ pub fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type { && c.table.get_type_symbol(former_expected_type).kind == .sum_type { continue } + if is_noreturn_callexpr(last_expr.expr) { + continue + } + c.error('mismatched types `${c.table.type_to_str(node.typ)}` and `${c.table.type_to_str(last_expr.typ)}`', node.pos) } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 2b17153633..294bf4ec09 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -5159,6 +5159,9 @@ fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool { if branch.stmts.len == 1 { if branch.stmts[0] is ast.ExprStmt { stmt := branch.stmts[0] as ast.ExprStmt + if is_noreturn_callexpr(stmt.expr) { + return true + } if stmt.expr is ast.CallExpr { if stmt.expr.is_method { left_sym := g.table.get_type_symbol(stmt.expr.receiver_type) diff --git a/vlib/v/tests/if_expression_test.v b/vlib/v/tests/if_expression_test.v index 544f6669e3..dedc6eb1e2 100644 --- a/vlib/v/tests/if_expression_test.v +++ b/vlib/v/tests/if_expression_test.v @@ -234,3 +234,32 @@ fn test_if_expr_with_or_block() { a := if arr.len == 0 || arr[0] == '-' { 123 } else { return_optional() or { -1 } } assert a == 1 } + +type Num = f32 | f64 | i64 | int + +[noreturn] +fn assert_false_noreturn() { + assert false + exit(1) +} + +fn test_noreturn() { + n := Num(int(0)) + _ := if n is int { + n + } else if n is f32 { + int(n) + } else { + exit(1) + } + + _ := if 1 == 0 { + 0 + } else if 1 == 1 { + 1 + } else if 1 == 2 { + panic('err') + } else { + assert_false_noreturn() + } +}