about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFlorian Diebold <flodiebold@gmail.com>2022-03-29 21:55:34 +0200
committerFlorian Diebold <flodiebold@gmail.com>2022-03-29 21:56:49 +0200
commitea1d0bccef335ed55ddc7af1312074990249eb77 (patch)
tree17ecd0084270eec411bf2731fdac52a8e8afafda
parent9eb7553d5ab7cd512b7edf8d8a30b191be0dc761 (diff)
downloadrust-ea1d0bccef335ed55ddc7af1312074990249eb77.tar.gz
rust-ea1d0bccef335ed55ddc7af1312074990249eb77.zip
Fix divergence detection for bare match arms
Fixes #11814 and #11837.
-rw-r--r--crates/hir_ty/src/infer/expr.rs8
-rw-r--r--crates/hir_ty/src/tests/never_type.rs44
2 files changed, 47 insertions, 5 deletions
diff --git a/crates/hir_ty/src/infer/expr.rs b/crates/hir_ty/src/infer/expr.rs
index 0b67f2c32e5..01022f20bd1 100644
--- a/crates/hir_ty/src/infer/expr.rs
+++ b/crates/hir_ty/src/infer/expr.rs
@@ -45,10 +45,6 @@ use super::{
 impl<'a> InferenceContext<'a> {
     pub(crate) fn infer_expr(&mut self, tgt_expr: ExprId, expected: &Expectation) -> Ty {
         let ty = self.infer_expr_inner(tgt_expr, expected);
-        if self.resolve_ty_shallow(&ty).is_never() {
-            // Any expression that produces a value of type `!` must have diverged
-            self.diverges = Diverges::Always;
-        }
         if let Some(expected_ty) = expected.only_has_type(&mut self.table) {
             let could_unify = self.unify(&ty, &expected_ty);
             if !could_unify {
@@ -800,6 +796,10 @@ impl<'a> InferenceContext<'a> {
         // use a new type variable if we got unknown here
         let ty = self.insert_type_vars_shallow(ty);
         self.write_expr_ty(tgt_expr, ty.clone());
+        if self.resolve_ty_shallow(&ty).is_never() {
+            // Any expression that produces a value of type `!` must have diverged
+            self.diverges = Diverges::Always;
+        }
         ty
     }
 
diff --git a/crates/hir_ty/src/tests/never_type.rs b/crates/hir_ty/src/tests/never_type.rs
index 3ca0a5b391d..fbdc8209f8f 100644
--- a/crates/hir_ty/src/tests/never_type.rs
+++ b/crates/hir_ty/src/tests/never_type.rs
@@ -1,6 +1,6 @@
 use expect_test::expect;
 
-use super::{check_infer_with_mismatches, check_types};
+use super::{check_infer_with_mismatches, check_no_mismatches, check_types};
 
 #[test]
 fn infer_never1() {
@@ -441,3 +441,45 @@ fn let_else_must_diverge() {
         "#]],
     );
 }
+
+#[test]
+fn issue_11837() {
+    check_no_mismatches(
+        r#"
+//- minicore: result
+enum MyErr {
+    Err1,
+    Err2,
+}
+
+fn example_ng() {
+    let value: Result<i32, MyErr> = Ok(3);
+
+    loop {
+        let ret = match value {
+            Ok(value) => value,
+            Err(ref err) => {
+                match err {
+                    MyErr::Err1 => break,
+                    MyErr::Err2 => continue,
+                };
+            }
+        };
+    }
+}
+"#,
+    );
+}
+
+#[test]
+fn issue_11814() {
+    check_no_mismatches(
+        r#"
+fn example() -> bool {
+    match 1 {
+        _ => return true,
+    };
+}
+"#,
+    );
+}