diff --git a/vlib/v/checker/checker.v b/vlib/v/checker/checker.v index 19f78a1af54343..83de6aa8f9c08e 100644 --- a/vlib/v/checker/checker.v +++ b/vlib/v/checker/checker.v @@ -80,6 +80,7 @@ pub mut: inside_lambda bool // true inside `|...| ...` inside_ref_lit bool // true inside `a := &something` inside_defer bool // true inside `defer {}` blocks + inside_return bool // true inside `return ...` blocks inside_fn_arg bool // `a`, `b` in `a.f(b)` inside_ct_attr bool // true inside `[if expr]` inside_x_is_type bool // true inside the Type expression of `if x is Type {` @@ -1208,7 +1209,21 @@ fn (mut c Checker) check_expr_option_or_result_call(expr ast.Expr, ret_type ast. } ast.IndexExpr { if expr.or_expr.kind != .absent { - c.check_or_expr(expr.or_expr, ret_type, ret_type.set_flag(.result), expr) + mut return_none_or_error := false + if expr.or_expr.stmts.len > 0 { + last_stmt := expr.or_expr.stmts.last() + if last_stmt is ast.ExprStmt { + if c.inside_return && last_stmt.typ in [ast.none_type, ast.error_type] { + return_none_or_error = true + } + } + } + if return_none_or_error { + c.check_expr_option_or_result_call(expr.or_expr, c.table.cur_fn.return_type) + } else { + c.check_or_expr(expr.or_expr, ret_type, ret_type.set_flag(.result), + expr) + } } } ast.CastExpr { diff --git a/vlib/v/checker/return.v b/vlib/v/checker/return.v index 1ecec7611f2ab6..f5d03b0905c436 100644 --- a/vlib/v/checker/return.v +++ b/vlib/v/checker/return.v @@ -25,6 +25,11 @@ fn (mut c Checker) return_stmt(mut node ast.Return) { if c.table.cur_fn == unsafe { nil } { return } + prev_inside_return := c.inside_return + c.inside_return = true + defer { + c.inside_return = prev_inside_return + } c.expected_type = c.table.cur_fn.return_type mut expected_type := c.unwrap_generic(c.expected_type) if expected_type != 0 && c.table.sym(expected_type).kind == .alias { diff --git a/vlib/v/tests/return_map_index_with_or_block_test.v b/vlib/v/tests/return_map_index_with_or_block_test.v new file mode 100644 index 00000000000000..8cd17570971121 --- /dev/null +++ b/vlib/v/tests/return_map_index_with_or_block_test.v @@ -0,0 +1,24 @@ +fn get_value1(m map[string]int, key string) ?int { + return m[key] or { none } +} + +fn get_value2(m map[string]int, key string) !int { + return m[key] or { error('not found') } +} + +fn test_return_map_index_with_or_block() { + m := { + 'aaa': 111 + } + if ret1 := get_value1(m, 'aaa') { + assert ret1 == 111 + } else { + assert false + } + + if ret2 := get_value2(m, 'aaa') { + assert ret2 == 111 + } else { + assert false + } +}