From 82a355131377023c1e9d3557071240e81814b578 Mon Sep 17 00:00:00 2001 From: yuyi Date: Thu, 22 Dec 2022 18:55:44 +0800 Subject: [PATCH] checker, cgen: fix match expr with branch returning (#16741) --- vlib/v/checker/match.v | 2 +- .../tests/match_expr_non_void_stmt_last.out | 7 ------- vlib/v/gen/c/cgen.v | 4 +++- vlib/v/gen/c/if.v | 2 ++ vlib/v/gen/c/match.v | 2 ++ ...match_expr_with_branch_returning_1_test.v} | 4 +++- .../match_expr_with_branch_returning_2_test.v | 19 +++++++++++++++++++ 7 files changed, 30 insertions(+), 10 deletions(-) delete mode 100644 vlib/v/checker/tests/match_expr_non_void_stmt_last.out rename vlib/v/{checker/tests/match_expr_non_void_stmt_last.vv => tests/match_expr_with_branch_returning_1_test.v} (62%) create mode 100644 vlib/v/tests/match_expr_with_branch_returning_2_test.v diff --git a/vlib/v/checker/match.v b/vlib/v/checker/match.v index d7ea150597..f22bc0925c 100644 --- a/vlib/v/checker/match.v +++ b/vlib/v/checker/match.v @@ -72,7 +72,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type { } else if node.is_expr && ret_type.idx() != expr_type.idx() { c.check_match_branch_last_stmt(stmt, ret_type, expr_type) } - } else { + } else if stmt !is ast.Return { if node.is_expr && ret_type != ast.void_type { c.error('`match` expression requires an expression as the last statement of every branch', stmt.pos) diff --git a/vlib/v/checker/tests/match_expr_non_void_stmt_last.out b/vlib/v/checker/tests/match_expr_non_void_stmt_last.out deleted file mode 100644 index 6b5e1612f9..0000000000 --- a/vlib/v/checker/tests/match_expr_non_void_stmt_last.out +++ /dev/null @@ -1,7 +0,0 @@ -vlib/v/checker/tests/match_expr_non_void_stmt_last.vv:9:4: error: `match` expression requires an expression as the last statement of every branch - 7 | } - 8 | []int { - 9 | return arr.str() - | ~~~~~~~~~~~~~~~~ - 10 | } - 11 | } diff --git a/vlib/v/gen/c/cgen.v b/vlib/v/gen/c/cgen.v index 599f9783b8..b4b8cad6cf 100644 --- a/vlib/v/gen/c/cgen.v +++ b/vlib/v/gen/c/cgen.v @@ -1737,7 +1737,9 @@ fn (mut g Gen) stmts_with_tmp_var(stmts []ast.Stmt, tmp_var string) bool { g.set_current_pos_as_last_stmt_pos() g.skip_stmt_pos = true mut is_noreturn := false - if stmt is ast.ExprStmt { + if stmt is ast.Return { + is_noreturn = true + } else if stmt is ast.ExprStmt { is_noreturn = is_noreturn_callexpr(stmt.expr) } if !is_noreturn { diff --git a/vlib/v/gen/c/if.v b/vlib/v/gen/c/if.v index 2c82ae285a..a5f09fdba0 100644 --- a/vlib/v/gen/c/if.v +++ b/vlib/v/gen/c/if.v @@ -23,6 +23,8 @@ fn (mut g Gen) need_tmp_var_in_if(node ast.IfExpr) bool { if g.need_tmp_var_in_expr(stmt.expr) { return true } + } else if branch.stmts[0] is ast.Return { + return true } } } diff --git a/vlib/v/gen/c/match.v b/vlib/v/gen/c/match.v index 7ccf2a9c70..82389b35ac 100644 --- a/vlib/v/gen/c/match.v +++ b/vlib/v/gen/c/match.v @@ -27,6 +27,8 @@ fn (mut g Gen) need_tmp_var_in_match(node ast.MatchExpr) bool { if g.need_tmp_var_in_expr(stmt.expr) { return true } + } else if branch.stmts[0] is ast.Return { + return true } } } diff --git a/vlib/v/checker/tests/match_expr_non_void_stmt_last.vv b/vlib/v/tests/match_expr_with_branch_returning_1_test.v similarity index 62% rename from vlib/v/checker/tests/match_expr_non_void_stmt_last.vv rename to vlib/v/tests/match_expr_with_branch_returning_1_test.v index 0737152b0d..92a3eb9097 100644 --- a/vlib/v/checker/tests/match_expr_non_void_stmt_last.vv +++ b/vlib/v/tests/match_expr_with_branch_returning_1_test.v @@ -11,7 +11,9 @@ fn (arr Arr) str() string { } } -fn main() { +fn test_match_expr_with_branch_returning() { println(Arr([0, 0])) + assert '${Arr([0, 0])}' == '[0, 0]' println(Arr(['0', '0'])) + assert '${Arr(['0', '0'])}' == '0 0' } diff --git a/vlib/v/tests/match_expr_with_branch_returning_2_test.v b/vlib/v/tests/match_expr_with_branch_returning_2_test.v new file mode 100644 index 0000000000..9bc9cbe8f3 --- /dev/null +++ b/vlib/v/tests/match_expr_with_branch_returning_2_test.v @@ -0,0 +1,19 @@ +fn foo() ! { + a := match true { + true { + 2 + } + 2 == 2 { + return error('hello') + } + else { + 0 + } + } + println(a) + assert a == 2 +} + +fn test_match_expr_with_branch_returning() { + foo()! +}