Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

checker: fix result call or_block with multi-statements (fix #21504) #21717

Merged
merged 1 commit into from
Jun 24, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
19 changes: 11 additions & 8 deletions vlib/v/checker/checker.v
Original file line number Diff line number Diff line change
Expand Up @@ -1647,7 +1647,7 @@ fn (mut c Checker) selector_expr(mut node ast.SelectorExpr) ast.Type {
node.typ = field.typ
if node.or_block.kind == .block {
c.expected_or_type = node.typ.clear_option_and_result()
c.stmts_ending_with_expression(mut node.or_block.stmts)
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
c.check_or_expr(node.or_block, node.typ, c.expected_or_type, node)
c.expected_or_type = ast.void_type
}
Expand Down Expand Up @@ -2593,7 +2593,7 @@ fn (mut c Checker) import_stmt(node ast.Import) {
fn (mut c Checker) stmts(mut stmts []ast.Stmt) {
old_stmt_level := c.stmt_level
c.stmt_level = 0
c.stmts_ending_with_expression(mut stmts)
c.stmts_ending_with_expression(mut stmts, c.expected_or_type)
c.stmt_level = old_stmt_level
}

Expand All @@ -2602,7 +2602,7 @@ fn (mut c Checker) stmts(mut stmts []ast.Stmt) {
// `x := opt() or { stmt1 stmt2 ExprStmt }`,
// `x := if cond { stmt1 stmt2 ExprStmt } else { stmt2 stmt3 ExprStmt }`,
// `x := match expr { Type1 { stmt1 stmt2 ExprStmt } else { stmt2 stmt3 ExprStmt }`.
fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) {
fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt, expected_or_type ast.Type) {
if stmts.len == 0 {
c.scope_returns = false
return
Expand All @@ -2623,7 +2623,10 @@ fn (mut c Checker) stmts_ending_with_expression(mut stmts []ast.Stmt) {
unreachable = stmt.pos
}
}
prev_expected_or_type := c.expected_or_type
c.expected_or_type = expected_or_type
c.stmt(mut stmt)
c.expected_or_type = prev_expected_or_type
if !c.inside_anon_fn && c.in_for_count > 0 && stmt is ast.BranchStmt
&& stmt.kind in [.key_continue, .key_break] {
c.scope_returns = true
Expand Down Expand Up @@ -3649,7 +3652,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
}
unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts)
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
return unwrapped_typ
}
Expand Down Expand Up @@ -3759,7 +3762,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
}
unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts)
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
return unwrapped_typ
}
Expand Down Expand Up @@ -3821,7 +3824,7 @@ fn (mut c Checker) ident(mut node ast.Ident) ast.Type {
if node.or_expr.kind != .absent {
unwrapped_typ := typ.clear_option_and_result()
c.expected_or_type = unwrapped_typ
c.stmts_ending_with_expression(mut node.or_expr.stmts)
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
c.check_or_expr(node.or_expr, typ, c.expected_or_type, node)
}
return typ
Expand Down Expand Up @@ -4448,7 +4451,7 @@ fn (mut c Checker) prefix_expr(mut node ast.PrefixExpr) ast.Type {
if node.op == .arrow {
raw_right_sym := c.table.final_sym(right_type)
if raw_right_sym.kind == .chan {
c.stmts_ending_with_expression(mut node.or_block.stmts)
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
return raw_right_sym.chan_info().elem_type
}
c.type_error_for_operator('<-', '`chan`', raw_right_sym.name, node.pos)
Expand Down Expand Up @@ -4645,7 +4648,7 @@ fn (mut c Checker) index_expr(mut node ast.IndexExpr) ast.Type {
if node.or_expr.stmts.len > 0 && node.or_expr.stmts.last() is ast.ExprStmt {
c.expected_or_type = typ
}
c.stmts_ending_with_expression(mut node.or_expr.stmts)
c.stmts_ending_with_expression(mut node.or_expr.stmts, c.expected_or_type)
c.check_expr_option_or_result_call(node, typ)
return typ
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/comptime.v
Original file line number Diff line number Diff line change
Expand Up @@ -123,7 +123,7 @@ fn (mut c Checker) comptime_call(mut node ast.ComptimeCall) ast.Type {
// check each arg expression
node.args[i].typ = c.expr(mut arg.expr)
}
c.stmts_ending_with_expression(mut node.or_block.stmts)
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
return c.comptime.get_comptime_var_type(node)
}
if node.method_name == 'res' {
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/fn.v
Original file line number Diff line number Diff line change
Expand Up @@ -600,7 +600,7 @@ fn (mut c Checker) call_expr(mut node ast.CallExpr) ast.Type {
}
}
c.expected_or_type = node.return_type.clear_flag(.result)
c.stmts_ending_with_expression(mut node.or_block.stmts)
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
c.expected_or_type = ast.void_type

if !c.inside_const && c.table.cur_fn != unsafe { nil } && !c.table.cur_fn.is_main
Expand Down
6 changes: 3 additions & 3 deletions vlib/v/checker/if.v
Original file line number Diff line number Diff line change
Expand Up @@ -324,7 +324,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
}
if !c.skip_flags {
if node_is_expr {
c.stmts_ending_with_expression(mut branch.stmts)
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
} else {
c.stmts(mut branch.stmts)
c.check_non_expr_branch_last_stmt(branch.stmts)
Expand All @@ -341,7 +341,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
node.branches[i].stmts = []
}
if node_is_expr {
c.stmts_ending_with_expression(mut branch.stmts)
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
} else {
c.stmts(mut branch.stmts)
c.check_non_expr_branch_last_stmt(branch.stmts)
Expand All @@ -364,7 +364,7 @@ fn (mut c Checker) if_expr(mut node ast.IfExpr) ast.Type {
// smartcast sumtypes and interfaces when using `is`
c.smartcast_if_conds(mut branch.cond, mut branch.scope)
if node_is_expr {
c.stmts_ending_with_expression(mut branch.stmts)
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
} else {
c.stmts(mut branch.stmts)
c.check_non_expr_branch_last_stmt(branch.stmts)
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/infix.v
Original file line number Diff line number Diff line change
Expand Up @@ -757,7 +757,7 @@ fn (mut c Checker) infix_expr(mut node ast.InfixExpr) ast.Type {
c.error('cannot push `${c.table.type_to_str(right_type)}` on `${left_sym.name}`',
right_pos)
}
c.stmts_ending_with_expression(mut node.or_block.stmts)
c.stmts_ending_with_expression(mut node.or_block.stmts, c.expected_or_type)
} else {
c.error('cannot push on non-channel `${left_sym.name}`', left_pos)
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/match.v
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ fn (mut c Checker) match_expr(mut node ast.MatchExpr) ast.Type {
mut nbranches_without_return := 0
for mut branch in node.branches {
if node.is_expr {
c.stmts_ending_with_expression(mut branch.stmts)
c.stmts_ending_with_expression(mut branch.stmts, c.expected_or_type)
} else {
c.stmts(mut branch.stmts)
}
Expand Down
2 changes: 1 addition & 1 deletion vlib/v/checker/orm.v
Original file line number Diff line number Diff line change
Expand Up @@ -626,7 +626,7 @@ fn (mut c Checker) check_orm_or_expr(mut expr ORMExpr) {

if expr.or_expr.kind == .block {
c.expected_or_type = return_type.clear_flag(.result)
c.stmts_ending_with_expression(mut expr.or_expr.stmts)
c.stmts_ending_with_expression(mut expr.or_expr.stmts, c.expected_or_type)
c.expected_or_type = ast.void_type
}
}
Expand Down
28 changes: 28 additions & 0 deletions vlib/v/tests/result_call_or_block_with_stmts_test.v
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
fn str_ret_fn(str string) string {
return str
}

fn foo(str string) !string {
if str.contains('foo') {
return str
}
return error('error')
}

fn test_result_call_or_block_with_stmts() {
var := foo('bar') or {
foo_var := str_ret_fn('foo')
if foo_var == 'foo' {
foo(foo_var) or {
eprintln(err)
exit(1)
}
} else {
eprintln(err)
exit(1)
}
}

println(var)
assert var == 'foo'
}
Loading