1
Fork 0

Detect if-else chains with a missing final else in type errors

```
error[E0308]: `if` and `else` have incompatible types
  --> $DIR/if-else-chain-missing-else.rs:12:12
   |
LL |        let x = if let Ok(x) = res {
   |  ______________-
LL | |          x
   | |          - expected because of this
LL | |      } else if let Err(e) = res {
   | | ____________^
LL | ||         return Err(e);
LL | ||     };
   | ||     ^
   | ||_____|
   |  |_____`if` and `else` have incompatible types
   |        expected `i32`, found `()`
   |
   = note: `if` expressions without `else` evaluate to `()`
   = note: consider adding an `else` block that evaluates to the expected type
```

We probably want a longer explanation and fewer spans on this case.

Partially address #133316.
This commit is contained in:
Esteban Küber 2025-01-15 22:09:52 +00:00
parent 27f336106d
commit f78a1bd89a
3 changed files with 50 additions and 0 deletions

View file

@ -620,6 +620,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
}) => {
let then_span = self.find_block_span_from_hir_id(then_id);
let else_span = self.find_block_span_from_hir_id(else_id);
if let hir::Node::Expr(e) = self.tcx.hir_node(else_id)
&& let hir::ExprKind::If(_cond, _then, None) = e.kind
&& else_ty.is_unit()
{
// Account for `let x = if a { 1 } else if b { 2 };`
err.note("`if` expressions without `else` evaluate to `()`");
err.note("consider adding an `else` block that evaluates to the expected type");
}
err.span_label(then_span, "expected because of this");
if let Some(sp) = outer_span {
err.span_label(sp, "`if` and `else` have incompatible types");