Rollup merge of #135558 - estebank:issue-133316, r=chenyukang
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:
commit
c43893005e
3 changed files with 50 additions and 0 deletions
|
@ -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");
|
||||
|
|
20
tests/ui/expr/if/if-else-chain-missing-else.rs
Normal file
20
tests/ui/expr/if/if-else-chain-missing-else.rs
Normal file
|
@ -0,0 +1,20 @@
|
|||
enum Cause { Cause1, Cause2 }
|
||||
struct MyErr { x: Cause }
|
||||
|
||||
fn main() {
|
||||
_ = f();
|
||||
}
|
||||
|
||||
fn f() -> Result<i32, MyErr> {
|
||||
let res = could_fail();
|
||||
let x = if let Ok(x) = res {
|
||||
x
|
||||
} else if let Err(e) = res { //~ ERROR `if` and `else`
|
||||
return Err(e);
|
||||
};
|
||||
Ok(x)
|
||||
}
|
||||
|
||||
fn could_fail() -> Result<i32, MyErr> {
|
||||
Ok(0)
|
||||
}
|
22
tests/ui/expr/if/if-else-chain-missing-else.stderr
Normal file
22
tests/ui/expr/if/if-else-chain-missing-else.stderr
Normal file
|
@ -0,0 +1,22 @@
|
|||
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
|
||||
|
||||
error: aborting due to 1 previous error
|
||||
|
||||
For more information about this error, try `rustc --explain E0308`.
|
Loading…
Add table
Add a link
Reference in a new issue