Skip to content

Commit f5c87a1

Browse files
authored
checker: fix result call or_block with multi-statements (fix #21504) (#21717)
1 parent d364e61 commit f5c87a1

File tree

8 files changed

+47
-16
lines changed

8 files changed

+47
-16
lines changed

vlib/v/checker/checker.v

Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1647,7 +1647,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
16471647
node.typ = field.typ
16481648
if node.or_block.kind == .block {
16491649
c.expected_or_type = node.typ.clear_option_and_result()
1650-
c.stmts_ending_with_expression(mut node.or_block.stmts)
1650+
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
16511651
c.check_or_expr(node.or_block, node.typ, c.expected_or_type, node)
16521652
c.expected_or_type = ast.void_type
16531653
}
@@ -2593,7 +2593,7 @@ fn (mut c Checker) import_stmt(node ast.Import) {
25932593
fn (mut c Checker) stmts(mut stmts []ast.Stmt) {
25942594
old_stmt_level := c.stmt_level
25952595
c.stmt_level = 0
2596-
c.stmts_ending_with_expression(mut stmts)
2596+
c.stmts_ending_with_expression(mut stmts, c.expected_or_type)
25972597
c.stmt_level = old_stmt_level
25982598
}
25992599

@@ -2602,7 +2602,7 @@ fn (mut c Checker) stmts(mut stmts []ast.Stmt) {
26022602
// `x := opt() or { stmt1 stmt2 ExprStmt }`,
26032603
// `x := if cond { stmt1 stmt2 ExprStmt } else { stmt2 stmt3 ExprStmt }`,
26042604
// `x := match expr { Type1 { stmt1 stmt2 ExprStmt } else { stmt2 stmt3 ExprStmt }`.
2605-
fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) {
2605+
fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt, expected_or_type ast.Type) {
26062606
if stmts.len == 0 {
26072607
c.scope_returns = false
26082608
return
@@ -2623,7 +2623,10 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) {
26232623
unreachable = stmt.pos
26242624
}
26252625
}
2626+
prev_expected_or_type := c.expected_or_type
2627+
c.expected_or_type = expected_or_type
26262628
c.stmt(mut stmt)
2629+
c.expected_or_type = prev_expected_or_type
26272630
if !c.inside_anon_fn && c.in_for_count > 0 && stmt is ast.BranchStmt
26282631
&& stmt.kind in [.key_continue, .key_break] {
26292632
c.scope_returns = true
@@ -3649,7 +3652,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
36493652
}
36503653
unwrapped_typ := typ.clear_option_and_result()
36513654
c.expected_or_type = unwrapped_typ
3652-
c.stmts_ending_with_expression(mut node.or_expr.stmts)
3655+
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
36533656
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
36543657
return unwrapped_typ
36553658
}
@@ -3759,7 +3762,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
37593762
}
37603763
unwrapped_typ := typ.clear_option_and_result()
37613764
c.expected_or_type = unwrapped_typ
3762-
c.stmts_ending_with_expression(mut node.or_expr.stmts)
3765+
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
37633766
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
37643767
return unwrapped_typ
37653768
}
@@ -3821,7 +3824,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
38213824
if node.or_expr.kind != .absent {
38223825
unwrapped_typ := typ.clear_option_and_result()
38233826
c.expected_or_type = unwrapped_typ
3824-
c.stmts_ending_with_expression(mut node.or_expr.stmts)
3827+
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
38253828
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
38263829
}
38273830
return typ
@@ -4455,7 +4458,7 @@ fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
44554458
if node.op == .arrow {
44564459
raw_right_sym := c.table.final_sym(right_type)
44574460
if raw_right_sym.kind == .chan {
4458-
c.stmts_ending_with_expression(mut node.or_block.stmts)
4461+
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
44594462
return raw_right_sym.chan_info().elem_type
44604463
}
44614464
c.type_error_for_operator('<-', '`chan`', raw_right_sym.name, node.pos)
@@ -4653,7 +4656,7 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
46534656
if node.or_expr.stmts.len > 0 && node.or_expr.stmts.last() is ast.ExprStmt {
46544657
c.expected_or_type = typ
46554658
}
4656-
c.stmts_ending_with_expression(mut node.or_expr.stmts)
4659+
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
46574660
c.check_expr_option_or_result_call(node, typ)
46584661
return typ
46594662
}

vlib/v/checker/comptime.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
123123
// check each arg expression
124124
node.args[i].typ = c.expr(mut arg.expr)
125125
}
126-
c.stmts_ending_with_expression(mut node.or_block.stmts)
126+
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
127127
return c.comptime.get_comptime_var_type(node)
128128
}
129129
if node.method_name == 'res' {

vlib/v/checker/fn.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -600,7 +600,7 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
600600
}
601601
}
602602
c.expected_or_type = node.return_type.clear_flag(.result)
603-
c.stmts_ending_with_expression(mut node.or_block.stmts)
603+
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
604604
c.expected_or_type = ast.void_type
605605

606606
if !c.inside_const && c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.is_main

vlib/v/checker/if.v

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -324,7 +324,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
324324
}
325325
if !c.skip_flags {
326326
if node_is_expr {
327-
c.stmts_ending_with_expression(mut branch.stmts)
327+
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
328328
} else {
329329
c.stmts(mut branch.stmts)
330330
c.check_non_expr_branch_last_stmt(branch.stmts)
@@ -341,7 +341,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
341341
node.branches[i].stmts = []
342342
}
343343
if node_is_expr {
344-
c.stmts_ending_with_expression(mut branch.stmts)
344+
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
345345
} else {
346346
c.stmts(mut branch.stmts)
347347
c.check_non_expr_branch_last_stmt(branch.stmts)
@@ -364,7 +364,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
364364
// smartcast sumtypes and interfaces when using `is`
365365
c.smartcast_if_conds(mut branch.cond, mut branch.scope)
366366
if node_is_expr {
367-
c.stmts_ending_with_expression(mut branch.stmts)
367+
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
368368
} else {
369369
c.stmts(mut branch.stmts)
370370
c.check_non_expr_branch_last_stmt(branch.stmts)

vlib/v/checker/infix.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -757,7 +757,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
757757
c.error('cannot push `${c.table.type_to_str(right_type)}` on `${left_sym.name}`',
758758
right_pos)
759759
}
760-
c.stmts_ending_with_expression(mut node.or_block.stmts)
760+
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
761761
} else {
762762
c.error('cannot push on non-channel `${left_sym.name}`', left_pos)
763763
}

vlib/v/checker/match.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
4343
mut nbranches_without_return := 0
4444
for mut branch in node.branches {
4545
if node.is_expr {
46-
c.stmts_ending_with_expression(mut branch.stmts)
46+
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
4747
} else {
4848
c.stmts(mut branch.stmts)
4949
}

vlib/v/checker/orm.v

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -626,7 +626,7 @@ fn (mut c Checker) check_orm_or_expr(mut expr ORMExpr) {
626626

627627
if expr.or_expr.kind == .block {
628628
c.expected_or_type = return_type.clear_flag(.result)
629-
c.stmts_ending_with_expression(mut expr.or_expr.stmts)
629+
c.stmts_ending_with_expression(mut expr.or_expr.stmts, c.expected_or_type)
630630
c.expected_or_type = ast.void_type
631631
}
632632
}
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
fn str_ret_fn(str string) string {
2+
return str
3+
}
4+
5+
fn foo(str string) !string {
6+
if str.contains('foo') {
7+
return str
8+
}
9+
return error('error')
10+
}
11+
12+
fn test_result_call_or_block_with_stmts() {
13+
var := foo('bar') or {
14+
foo_var := str_ret_fn('foo')
15+
if foo_var == 'foo' {
16+
foo(foo_var) or {
17+
eprintln(err)
18+
exit(1)
19+
}
20+
} else {
21+
eprintln(err)
22+
exit(1)
23+
}
24+
}
25+
26+
println(var)
27+
assert var == 'foo'
28+
}

0 commit comments

Comments
 (0)