about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs8
-rw-r--r--tests/ui/expr/if/if-else-chain-missing-else.rs20
-rw-r--r--tests/ui/expr/if/if-else-chain-missing-else.stderr22
3 files changed, 50 insertions, 0 deletions
diff --git a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
index 7032f7b9d31..9778299eb19 100644
--- a/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
+++ b/compiler/rustc_trait_selection/src/error_reporting/infer/mod.rs
@@ -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");
diff --git a/tests/ui/expr/if/if-else-chain-missing-else.rs b/tests/ui/expr/if/if-else-chain-missing-else.rs
new file mode 100644
index 00000000000..995aac07f2f
--- /dev/null
+++ b/tests/ui/expr/if/if-else-chain-missing-else.rs
@@ -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)
+}
diff --git a/tests/ui/expr/if/if-else-chain-missing-else.stderr b/tests/ui/expr/if/if-else-chain-missing-else.stderr
new file mode 100644
index 00000000000..374c4927e30
--- /dev/null
+++ b/tests/ui/expr/if/if-else-chain-missing-else.stderr
@@ -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`.