about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/hair/pattern/_match.rs2
-rw-r--r--src/librustc_mir/hair/pattern/check_match.rs78
2 files changed, 39 insertions, 41 deletions
diff --git a/src/librustc_mir/hair/pattern/_match.rs b/src/librustc_mir/hair/pattern/_match.rs
index 0e8313a50bc..4b451ad81c3 100644
--- a/src/librustc_mir/hair/pattern/_match.rs
+++ b/src/librustc_mir/hair/pattern/_match.rs
@@ -1220,6 +1220,8 @@ impl<'tcx> Witness<'tcx> {
 ///
 /// We make sure to omit constructors that are statically impossible. E.g., for
 /// `Option<!>`, we do not include `Some(_)` in the returned list of constructors.
+/// Invariant: this returns an empty `Vec` if and only if the type is uninhabited (as determined by
+/// `cx.is_uninhabited()`).
 fn all_constructors<'a, 'tcx>(
     cx: &mut MatchCheckCtxt<'a, 'tcx>,
     pcx: PatCtxt<'tcx>,
diff --git a/src/librustc_mir/hair/pattern/check_match.rs b/src/librustc_mir/hair/pattern/check_match.rs
index 451e259ca7a..d29169cb341 100644
--- a/src/librustc_mir/hair/pattern/check_match.rs
+++ b/src/librustc_mir/hair/pattern/check_match.rs
@@ -438,49 +438,24 @@ fn check_exhaustive<'p, 'tcx>(
     // If the match has no arms, check whether the scrutinee is uninhabited.
     // Note: An empty match isn't the same as an empty matrix for diagnostics purposes, since an
     // empty matrix can occur when there are arms, if those arms all have guards.
-    if is_empty_match {
-        let scrutinee_is_visibly_uninhabited = if cx.tcx.features().exhaustive_patterns {
-            let module = cx.tcx.hir().get_module_parent(hir_id);
-            cx.tcx.is_ty_uninhabited_from(module, scrut_ty)
-        } else {
-            match scrut_ty.kind {
-                ty::Never => true,
-                ty::Adt(def, _) if def.is_enum() => {
-                    def.variants.is_empty() && !cx.is_foreign_non_exhaustive_enum(scrut_ty)
-                }
-                _ => false,
-            }
-        };
-        if scrutinee_is_visibly_uninhabited {
-            // If the type *is* uninhabited, it's vacuously exhaustive.
-            // This early return is only needed here because in the absence of the
-            // `exhaustive_patterns` feature, empty matches are not detected by `is_useful`
-            // to exhaustively match uninhabited types.
-            return;
-        } else {
-            // We know the type is inhabited, so this must be wrong
-            let non_empty_enum = match scrut_ty.kind {
-                ty::Adt(def, _) => def.is_enum() && !def.variants.is_empty(),
-                _ => false,
-            };
-
-            if non_empty_enum {
-                // Continue to the normal code path to display missing variants.
-            } else {
-                let mut err = create_e0004(
-                    cx.tcx.sess,
-                    sp,
-                    format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
-                );
-                err.help(
-                    "ensure that all possible cases are being handled, \
-                     possibly by adding wildcards or more match arms",
-                );
-                adt_defined_here(cx, &mut err, scrut_ty, &[]);
-                err.emit();
-                return;
+    let scrutinee_is_visibly_uninhabited = if cx.tcx.features().exhaustive_patterns {
+        let module = cx.tcx.hir().get_module_parent(hir_id);
+        cx.tcx.is_ty_uninhabited_from(module, scrut_ty)
+    } else {
+        match scrut_ty.kind {
+            ty::Never => true,
+            ty::Adt(def, _) if def.is_enum() => {
+                def.variants.is_empty() && !cx.is_foreign_non_exhaustive_enum(scrut_ty)
             }
+            _ => false,
         }
+    };
+    if is_empty_match && scrutinee_is_visibly_uninhabited {
+        // If the type *is* uninhabited, it's vacuously exhaustive.
+        // This early return is only needed here because in the absence of the
+        // `exhaustive_patterns` feature, empty matches are not detected by `is_useful`
+        // to exhaustively match uninhabited types.
+        return;
     }
 
     let witnesses = match check_not_useful(cx, scrut_ty, matrix, hir_id) {
@@ -488,6 +463,27 @@ fn check_exhaustive<'p, 'tcx>(
         Err(err) => err,
     };
 
+    let non_empty_enum = match scrut_ty.kind {
+        ty::Adt(def, _) => def.is_enum() && !def.variants.is_empty(),
+        _ => false,
+    };
+    // In the case of an empty match, replace the '`_` not covered' diagnostic with something more
+    // informative.
+    if is_empty_match && !non_empty_enum {
+        let mut err = create_e0004(
+            cx.tcx.sess,
+            sp,
+            format!("non-exhaustive patterns: type `{}` is non-empty", scrut_ty),
+        );
+        err.help(
+            "ensure that all possible cases are being handled, \
+             possibly by adding wildcards or more match arms",
+        );
+        adt_defined_here(cx, &mut err, scrut_ty, &[]);
+        err.emit();
+        return;
+    }
+
     let joined_patterns = joined_uncovered_patterns(&witnesses);
     let mut err = create_e0004(
         cx.tcx.sess,