Detail expectation on non-() block tail in if then condition with no else

When encountering an `if` expression with no `else` where the then
block has a tail expression, we emit an E0308 type error. We now explain
why `()` was expected.
This commit is contained in:
Esteban Küber 2025-12-12 19:52:23 +00:00
parent 000ccd651d
commit 42ec5c7b32
11 changed files with 30 additions and 17 deletions

View file

@ -1838,7 +1838,20 @@ impl<'tcx> CoerceMany<'tcx> {
hir::ExprKind::Match(.., hir::MatchSource::TryDesugar(_))
)
{
err.span_label(cond_expr.span, "expected this to be `()`");
if let ObligationCauseCode::BlockTailExpression(hir_id, hir::MatchSource::Normal) =
cause.code()
&& let hir::Node::Block(block) = fcx.tcx.hir_node(*hir_id)
&& let hir::Node::Expr(expr) = fcx.tcx.parent_hir_node(block.hir_id)
&& let hir::Node::Expr(if_expr) = fcx.tcx.parent_hir_node(expr.hir_id)
&& let hir::ExprKind::If(_cond, _then, None) = if_expr.kind
{
err.span_label(
cond_expr.span,
"`if` expressions without `else` arms expect their inner expression to be `()`",
);
} else {
err.span_label(cond_expr.span, "expected this to be `()`");
}
if expr.can_have_side_effects() {
fcx.suggest_semicolon_at_end(cond_expr.span, &mut err);
}

View file

@ -6,7 +6,7 @@ LL | | false
| | ^^^^^ expected `()`, found `bool`
LL | |
LL | | }
| |_________- expected this to be `()`
| |_________- `if` expressions without `else` arms expect their inner expression to be `()`
error[E0308]: mismatched types
--> $DIR/dont-ice-for-type-mismatch-in-closure-in-async.rs:12:9

View file

@ -5,7 +5,7 @@ LL | / if true {
LL | | Ok(S)
| | ^^^^^ expected `()`, found `Result<S, _>`
LL | | }
| |_________- expected this to be `()`
| |_________- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found enum `Result<S, _>`
@ -21,7 +21,7 @@ LL | / if true {
LL | | Ok(S)
| | ^^^^^ expected `()`, found `Result<S, _>`
LL | | }
| |_________- expected this to be `()`
| |_________- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found enum `Result<S, _>`

View file

@ -105,7 +105,7 @@ LL | / if num == 3 {
LL | | true
| | ^^^^ expected `()`, found `bool`
LL | | }
| |_____- expected this to be `()`
| |_____- `if` expressions without `else` arms expect their inner expression to be `()`
|
help: you might have meant to return this value
|

View file

@ -6,7 +6,7 @@ LL | | Err(1)
| | ^^^^^^ expected `()`, found `Result<_, {integer}>`
... |
LL | | }
| |_____________- expected this to be `()`
| |_____________- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found enum `Result<_, {integer}>`
@ -23,7 +23,7 @@ LL | | Err(1)
| | ^^^^^^ expected `()`, found `Result<_, {integer}>`
... |
LL | | }
| |_____________- expected this to be `()`
| |_____________- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found enum `Result<_, {integer}>`
@ -40,7 +40,7 @@ LL | | Err(1)
| | ^^^^^^ expected `()`, found `Result<_, {integer}>`
LL | |
LL | | }
| |_____________- expected this to be `()`
| |_____________- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found enum `Result<_, {integer}>`
@ -53,7 +53,7 @@ LL | | Err(1)
| | ^^^^^^ expected `()`, found `Result<_, {integer}>`
LL | |
LL | | }
| |_____________- expected this to be `()`
| |_____________- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found enum `Result<_, {integer}>`

View file

@ -200,7 +200,7 @@ LL | if x == E::V { field } {}
| ---------------^^^^^--
| | |
| | expected `()`, found `bool`
| expected this to be `()`
| `if` expressions without `else` arms expect their inner expression to be `()`
|
help: you might have meant to return this value
|

View file

@ -6,7 +6,7 @@ LL | | let value = unsafe { self.values.get_unchecked_mut(index) };
LL | | value.get_or_insert_with(func)
| | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ expected `()`, found `&mut V`
LL | | }
| |_________- expected this to be `()`
| |_________- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found mutable reference `&mut V`

View file

@ -6,7 +6,7 @@ LL | | Err(42)
| | ^^^^^^^ expected `()`, found `Result<_, {integer}>`
... |
LL | | }
| |_____- expected this to be `()`
| |_____- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found enum `Result<_, {integer}>`
@ -23,7 +23,7 @@ LL | | 1i32
| | ^^^^ expected `()`, found `i32`
... |
LL | | }
| |_____- expected this to be `()`
| |_____- `if` expressions without `else` arms expect their inner expression to be `()`
|
help: you might have meant to return this value
|
@ -38,7 +38,7 @@ LL | | Err(42)
| | ^^^^^^^ expected `()`, found `Result<_, {integer}>`
... |
LL | | }
| |_____- expected this to be `()`
| |_____- `if` expressions without `else` arms expect their inner expression to be `()`
|
= note: expected unit type `()`
found enum `Result<_, {integer}>`

View file

@ -5,7 +5,7 @@ LL | / if true {
LL | | ""
| | ^^ expected `()`, found `&str`
LL | | }
| |_____- expected this to be `()`
| |_____- `if` expressions without `else` arms expect their inner expression to be `()`
error: aborting due to 1 previous error

View file

@ -12,7 +12,7 @@ fn main() -> Result<(), ()> {
// Here, we do want to suggest a semicolon:
let x = Ok(42);
if true {
//~^ NOTE: expected this to be `()`
//~^ NOTE: `if` expressions without `else` arms expect their inner expression to be `()`
x?
//~^ ERROR: mismatched types [E0308]
//~| NOTE: expected `()`, found integer

View file

@ -15,7 +15,7 @@ LL | | x?
| | ^^ expected `()`, found integer
... |
LL | | }
| |_____- expected this to be `()`
| |_____- `if` expressions without `else` arms expect their inner expression to be `()`
|
help: consider using a semicolon here
|