Skip to content

Commit 409197d

Browse files
committed
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.
1 parent 27f3361 commit 409197d

File tree

3 files changed

+50
-0
lines changed

3 files changed

+50
-0
lines changed

compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs

+8
Original file line numberDiff line numberDiff line change
@@ -620,6 +620,14 @@ impl<'a, 'tcx> TypeErrCtxt<'a, 'tcx> {
620620
}) => {
621621
let then_span = self.find_block_span_from_hir_id(then_id);
622622
let else_span = self.find_block_span_from_hir_id(else_id);
623+
if let hir::Node::Expr(e) = self.tcx.hir_node(else_id)
624+
&& let hir::ExprKind::If(_cond, _then, None) = e.kind
625+
&& else_ty.is_unit()
626+
{
627+
// Account for `let x = if a { 1 } else if b { 2 };`
628+
err.note("`if` expressions without `else` evaluate to `()`");
629+
err.note("consider adding an `else` block that evaluates to the expected type");
630+
}
623631
err.span_label(then_span, "expected because of this");
624632
if let Some(sp) = outer_span {
625633
err.span_label(sp, "`if` and `else` have incompatible types");
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
enum Cause { Cause1, Cause2 }
2+
// struct MyErr { x: Cause }
3+
4+
fn main() {
5+
_ = f();
6+
}
7+
8+
fn f() -> Result<i32, MyErr> {
9+
let res = could_fail();
10+
let x = if let Ok(x) = res {
11+
x
12+
} else if let Err(e) = res { //~ ERROR `if` and `else`
13+
return Err(e);
14+
};
15+
Ok(x)
16+
}
17+
18+
fn could_fail() -> Result<i32, MyErr> {
19+
Ok(0)
20+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
error[E0308]: `if` and `else` have incompatible types
2+
--> $DIR/if-else-chain-missing-else.rs:12:12
3+
|
4+
LL | let x = if let Ok(x) = res {
5+
| ______________-
6+
LL | | x
7+
| | - expected because of this
8+
LL | | } else if let Err(e) = res {
9+
| | ____________^
10+
LL | || return Err(e);
11+
LL | || };
12+
| || ^
13+
| ||_____|
14+
| |_____`if` and `else` have incompatible types
15+
| expected `i32`, found `()`
16+
|
17+
= note: `if` expressions without `else` evaluate to `()`
18+
= note: consider adding an `else` block that evaluates to the expected type
19+
20+
error: aborting due to 1 previous error
21+
22+
For more information about this error, try `rustc --explain E0308`.

0 commit comments

Comments
 (0)