diff --git a/vlib/v/checker/if.v b/vlib/v/checker/if.v index 602ce9dbb4790c..95ef6a757dc5d2 100644 --- a/vlib/v/checker/if.v +++ b/vlib/v/checker/if.v @@ -32,6 +32,8 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type { stmts := node.branches[0].stmts if stmts.len > 0 && stmts.last() is ast.ExprStmt && stmts.last().typ != ast.void_type { node_is_expr = true + } else if node.is_expr { + node_is_expr = true } } if c.expected_type == ast.void_type && node_is_expr { @@ -520,8 +522,9 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type { } } } else if !node.is_comptime && stmt !in [ast.Return, ast.BranchStmt] { + pos := if node_is_expr { stmt.pos } else { branch.pos } c.error('`${if_kind}` expression requires an expression as the last statement of every branch', - branch.pos) + pos) } } else if !node.is_comptime { c.error('`${if_kind}` expression requires an expression as the last statement of every branch', diff --git a/vlib/v/checker/tests/if_expr_last_branch_stmt_err.out b/vlib/v/checker/tests/if_expr_last_branch_stmt_err.out new file mode 100644 index 00000000000000..209f4dd136c9b3 --- /dev/null +++ b/vlib/v/checker/tests/if_expr_last_branch_stmt_err.out @@ -0,0 +1,7 @@ +vlib/v/checker/tests/if_expr_last_branch_stmt_err.vv:5:30: error: `if` expression requires an expression as the last statement of every branch + 3 | mut start := 0 + 4 | + 5 | start = if val < 20 { start += 1 } else { start } + | ~~ + 6 | dump(start) + 7 | } diff --git a/vlib/v/checker/tests/if_expr_last_branch_stmt_err.vv b/vlib/v/checker/tests/if_expr_last_branch_stmt_err.vv new file mode 100644 index 00000000000000..889bb5209aa1c0 --- /dev/null +++ b/vlib/v/checker/tests/if_expr_last_branch_stmt_err.vv @@ -0,0 +1,7 @@ +fn main() { + val := 15 + mut start := 0 + + start = if val < 20 { start += 1 } else { start } + dump(start) +} diff --git a/vlib/v/parser/expr.v b/vlib/v/parser/expr.v index bbfbe197ca2bdf..619fb452af0039 100644 --- a/vlib/v/parser/expr.v +++ b/vlib/v/parser/expr.v @@ -128,7 +128,7 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr { p.is_stmt_ident = is_stmt_ident } .key_if { - return p.if_expr(true) + return p.if_expr(true, false) } else { return p.unexpected_with_pos(p.peek_tok.pos(), @@ -222,7 +222,11 @@ fn (mut p Parser) check_expr(precedence int) !ast.Expr { if p.peek_tok.kind in [.lpar, .lsbr] && p.peek_tok.is_next_to(p.tok) { node = p.call_expr(p.language, p.mod) } else { - node = p.if_expr(false) + mut is_expr := false + if p.prev_tok.kind.is_assign() { + is_expr = true + } + node = p.if_expr(false, is_expr) } } .key_unsafe { diff --git a/vlib/v/parser/if_match.v b/vlib/v/parser/if_match.v index d395370d51e9a4..7ebc25b119cc25 100644 --- a/vlib/v/parser/if_match.v +++ b/vlib/v/parser/if_match.v @@ -6,7 +6,7 @@ module parser import v.ast import v.token -fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { +fn (mut p Parser) if_expr(is_comptime bool, is_expr bool) ast.IfExpr { was_inside_if_expr := p.inside_if_expr was_inside_ct_if_expr := p.inside_ct_if_expr defer { @@ -14,7 +14,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { p.inside_ct_if_expr = was_inside_ct_if_expr } p.inside_if_expr = true - is_expr := p.prev_tok.kind == .key_return + is_expr_ := p.prev_tok.kind == .key_return || is_expr mut pos := p.tok.pos() if is_comptime { p.inside_ct_if_expr = true @@ -213,7 +213,7 @@ fn (mut p Parser) if_expr(is_comptime bool) ast.IfExpr { post_comments: comments pos: pos has_else: has_else - is_expr: is_expr + is_expr: is_expr_ } } diff --git a/vlib/v/parser/parser.v b/vlib/v/parser/parser.v index 71c39b16760a2e..cae838d621a481 100644 --- a/vlib/v/parser/parser.v +++ b/vlib/v/parser/parser.v @@ -795,7 +795,7 @@ fn (mut p Parser) top_stmt() ast.Stmt { comptime_for_stmt := p.comptime_for() return p.other_stmts(comptime_for_stmt) } else if p.peek_tok.kind == .key_if { - if_expr := p.if_expr(true) + if_expr := p.if_expr(true, false) cur_stmt := ast.ExprStmt{ expr: if_expr pos: if_expr.pos @@ -1077,7 +1077,7 @@ fn (mut p Parser) stmt(is_top_level bool) ast.Stmt { match p.peek_tok.kind { .key_if { mut pos := p.tok.pos() - expr := p.if_expr(true) + expr := p.if_expr(true, false) pos.update_last_line(p.prev_tok.line_nr) return ast.ExprStmt{ expr: expr