about summary refs log tree commit diff
path: root/compiler/rustc_mir_build/src
diff options
context:
space:
mode:
authorCamille GILLOT <gillot.camille@gmail.com>2023-04-09 08:09:43 +0000
committerCamille GILLOT <gillot.camille@gmail.com>2023-05-24 19:16:07 +0000
commit9a7ed3625f57ad21d646f835975ab42929214b60 (patch)
tree20e1e872db704783d3dd27a92eb15b51efb08abf /compiler/rustc_mir_build/src
parentb3cbf7c8351dd48dc2e07a1cdc69620f8e40dd2f (diff)
downloadrust-9a7ed3625f57ad21d646f835975ab42929214b60.tar.gz
rust-9a7ed3625f57ad21d646f835975ab42929214b60.zip
Emit diagnostic for privately uninhabited uncovered witnesses.
Diffstat (limited to 'compiler/rustc_mir_build/src')
-rw-r--r--compiler/rustc_mir_build/src/errors.rs2
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs18
2 files changed, 20 insertions, 0 deletions
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index dcdeaf008d6..7c0df201bc2 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -781,6 +781,8 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
     pub interpreted_as_const: Option<InterpretedAsConst>,
     #[subdiagnostic]
     pub adt_defined_here: Option<AdtDefinedHere<'tcx>>,
+    #[note(mir_build_privately_uninhabited)]
+    pub witness_1_is_privately_uninhabited: Option<()>,
     #[note(mir_build_pattern_ty)]
     pub _p: (),
     pub pattern_ty: Ty<'tcx>,
diff --git a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
index ca25f83e643..5559e8b3940 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -479,12 +479,30 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             AdtDefinedHere { adt_def_span, ty, variants }
         };
 
+        // Emit an extra note if the first uncovered witness is
+        // visibly uninhabited anywhere in the current crate.
+        let witness_1_is_privately_uninhabited =
+            if cx.tcx.features().exhaustive_patterns
+                && let Some(witness_1) = witnesses.get(0)
+                && let ty::Adt(adt, substs) = witness_1.ty().kind()
+                && adt.is_enum()
+                && let Constructor::Variant(variant_index) = witness_1.ctor()
+            {
+                let variant = adt.variant(*variant_index);
+                let inhabited = variant.inhabited_predicate(cx.tcx, *adt).subst(cx.tcx, substs);
+                assert!(inhabited.apply(cx.tcx, cx.param_env, cx.module));
+                !inhabited.apply_ignore_module(cx.tcx, cx.param_env)
+            } else {
+                false
+            };
+
         self.error = Err(self.tcx.sess.emit_err(PatternNotCovered {
             span: pat.span,
             origin,
             uncovered: Uncovered::new(pat.span, &cx, witnesses),
             inform,
             interpreted_as_const,
+            witness_1_is_privately_uninhabited: witness_1_is_privately_uninhabited.then_some(()),
             _p: (),
             pattern_ty,
             let_suggestion,