about summary refs log tree commit diff
diff options
context:
space:
mode:
authorMatthias Krüger <matthias.krueger@famsik.de>2023-10-14 19:22:17 +0200
committerGitHub <noreply@github.com>2023-10-14 19:22:17 +0200
commit7d1b24f4bcd591490369862a1227273d6027fc16 (patch)
treea4bc87ce83d13294f585df5d161607f79524c7e7
parent3a5c24550e9775472d0271b71de6fa707dff3ca3 (diff)
parent89f75ff4d05d22ca3b9b3d70fc6bcd225c8dbf12 (diff)
Rollup merge of #116715 - Nadrieril:patkind-error, r=oli-obk
Prevent more spurious unreachable pattern lints

Continues the work of https://github.com/rust-lang/rust/pull/115937 by introducing `PatKind::Error`, to be used instead of `PatKind::Wild` when an error was raised during pattern lowering. Most of match checking lints are skipped when a `PatKind::Error` is encountered. This avoids confusing extra warnings when a pattern is malformed. Now `PatKind::Wild` should indicate an actual wildcard pattern.

r? `@oli-obk`
-rw-r--r--compiler/rustc_middle/src/thir.rs31
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/mod.rs5
-rw-r--r--compiler/rustc_mir_build/src/build/matches/simplify.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/matches/test.rs6
-rw-r--r--compiler/rustc_mir_build/src/check_unsafety.rs3
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs34
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs22
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs42
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs3
-rw-r--r--tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr14
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.rs2
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.stderr41
14 files changed, 108 insertions, 103 deletions
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 08f7434a4a9..67804998a32 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -19,11 +19,12 @@ use rustc_middle::middle::region;
 use rustc_middle::mir::interpret::AllocId;
 use rustc_middle::mir::{self, BinOp, BorrowKind, FakeReadCause, Mutability, UnOp};
 use rustc_middle::ty::adjustment::PointerCoercion;
-use rustc_middle::ty::GenericArgsRef;
-use rustc_middle::ty::{self, AdtDef, FnSig, List, Ty, UpvarArgs};
-use rustc_middle::ty::{CanonicalUserType, CanonicalUserTypeAnnotation};
+use rustc_middle::ty::{
+    self, AdtDef, CanonicalUserType, CanonicalUserTypeAnnotation, FnSig, GenericArgsRef, List, Ty,
+    UpvarArgs,
+};
 use rustc_span::def_id::LocalDefId;
-use rustc_span::{sym, Span, Symbol, DUMMY_SP};
+use rustc_span::{sym, ErrorGuaranteed, Span, Symbol, DUMMY_SP};
 use rustc_target::abi::{FieldIdx, VariantIdx};
 use rustc_target::asm::InlineAsmRegOrRegClass;
 use std::fmt;
@@ -632,7 +633,7 @@ impl<'tcx> Pat<'tcx> {
 
         use PatKind::*;
         match &self.kind {
-            Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {}
+            Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } | Error(_) => {}
             AscribeUserType { subpattern, .. }
             | Binding { subpattern: Some(subpattern), .. }
             | Deref { subpattern } => subpattern.walk_(it),
@@ -647,6 +648,21 @@ impl<'tcx> Pat<'tcx> {
         }
     }
 
+    /// Whether the pattern has a `PatKind::Error` nested within.
+    pub fn pat_error_reported(&self) -> Result<(), ErrorGuaranteed> {
+        let mut error = None;
+        self.walk(|pat| {
+            if let PatKind::Error(e) = pat.kind && error.is_none() {
+                error = Some(e);
+            }
+            error.is_none()
+        });
+        match error {
+            None => Ok(()),
+            Some(e) => Err(e),
+        }
+    }
+
     /// Walk the pattern in left-to-right order.
     ///
     /// If you always want to recurse, prefer this method over `walk`.
@@ -771,6 +787,10 @@ pub enum PatKind<'tcx> {
     Or {
         pats: Box<[Box<Pat<'tcx>>]>,
     },
+
+    /// An error has been encountered during lowering. We probably shouldn't report more lints
+    /// related to this pattern.
+    Error(ErrorGuaranteed),
 }
 
 #[derive(Clone, Debug, PartialEq, HashStable, TypeVisitable)]
@@ -934,6 +954,7 @@ impl<'tcx> fmt::Display for Pat<'tcx> {
                 }
                 Ok(())
             }
+            PatKind::Error(_) => write!(f, "<error>"),
         }
     }
 }
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index b84e1568884..afb58438519 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -226,7 +226,7 @@ pub fn walk_pat<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, pat: &Pat<'
             is_primary: _,
             name: _,
         } => visitor.visit_pat(&subpattern),
-        Binding { .. } | Wild => {}
+        Binding { .. } | Wild | Error(_) => {}
         Variant { subpatterns, adt_def: _, args: _, variant_index: _ } | Leaf { subpatterns } => {
             for subpattern in subpatterns {
                 visitor.visit_pat(&subpattern.pattern);
diff --git a/compiler/rustc_mir_build/src/build/matches/mod.rs b/compiler/rustc_mir_build/src/build/matches/mod.rs
index eb1c6a9824a..ab3ffabe297 100644
--- a/compiler/rustc_mir_build/src/build/matches/mod.rs
+++ b/compiler/rustc_mir_build/src/build/matches/mod.rs
@@ -814,7 +814,10 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 }
             }
 
-            PatKind::Constant { .. } | PatKind::Range { .. } | PatKind::Wild => {}
+            PatKind::Constant { .. }
+            | PatKind::Range { .. }
+            | PatKind::Wild
+            | PatKind::Error(_) => {}
 
             PatKind::Deref { ref subpattern } => {
                 self.visit_primary_bindings(subpattern, pattern_user_ty.deref(), f);
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 17ac1f4e0ce..f340feb40d4 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -168,7 +168,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                 Ok(())
             }
 
-            PatKind::Wild => {
+            PatKind::Wild | PatKind::Error(_) => {
                 // nothing left to do
                 Ok(())
             }
diff --git a/compiler/rustc_mir_build/src/build/matches/test.rs b/compiler/rustc_mir_build/src/build/matches/test.rs
index 795d1db8eec..dde3702ca63 100644
--- a/compiler/rustc_mir_build/src/build/matches/test.rs
+++ b/compiler/rustc_mir_build/src/build/matches/test.rs
@@ -77,7 +77,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | PatKind::Wild
             | PatKind::Binding { .. }
             | PatKind::Leaf { .. }
-            | PatKind::Deref { .. } => self.error_simplifiable(match_pair),
+            | PatKind::Deref { .. }
+            | PatKind::Error(_) => self.error_simplifiable(match_pair),
         }
     }
 
@@ -111,7 +112,8 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
             | PatKind::Binding { .. }
             | PatKind::AscribeUserType { .. }
             | PatKind::Leaf { .. }
-            | PatKind::Deref { .. } => {
+            | PatKind::Deref { .. }
+            | PatKind::Error(_) => {
                 // don't know how to add these patterns to a switch
                 false
             }
diff --git a/compiler/rustc_mir_build/src/check_unsafety.rs b/compiler/rustc_mir_build/src/check_unsafety.rs
index 192bd4a83e3..6cf2ecc51e9 100644
--- a/compiler/rustc_mir_build/src/check_unsafety.rs
+++ b/compiler/rustc_mir_build/src/check_unsafety.rs
@@ -224,7 +224,8 @@ impl<'a, 'tcx> Visitor<'a, 'tcx> for UnsafetyVisitor<'a, 'tcx> {
                 PatKind::Wild |
                 // these just wrap other patterns
                 PatKind::Or { .. } |
-                PatKind::AscribeUserType { .. } => {}
+                PatKind::AscribeUserType { .. } |
+                PatKind::Error(_) => {}
             }
         };
 
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 93434dd3cc2..bcecd0ff9db 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -19,7 +19,7 @@ use rustc_hir::HirId;
 use rustc_middle::thir::visit::{self, Visitor};
 use rustc_middle::thir::*;
 use rustc_middle::ty::print::with_no_trimmed_paths;
-use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt, TypeVisitableExt};
+use rustc_middle::ty::{self, AdtDef, Ty, TyCtxt};
 use rustc_session::lint::builtin::{
     BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
 };
@@ -231,6 +231,10 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         if let LetSource::None = source {
             return;
         }
+        if let Err(err) = pat.pat_error_reported() {
+            self.error = Err(err);
+            return;
+        }
         self.check_patterns(pat, Refutable);
         let mut cx = self.new_cx(self.lint_level, true);
         let tpat = self.lower_pattern(&mut cx, pat);
@@ -252,6 +256,10 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             self.with_lint_level(arm.lint_level, |this| {
                 this.check_patterns(&arm.pattern, Refutable);
             });
+            if let Err(err) = arm.pattern.pat_error_reported() {
+                self.error = Err(err);
+                return;
+            }
         }
 
         let tarms: Vec<_> = arms
@@ -334,7 +342,8 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         // and record chain members that aren't let exprs.
         let mut chain_refutabilities = Vec::new();
 
-        let add = |expr: ExprId, mut local_lint_level| {
+        let mut error = Ok(());
+        let mut add = |expr: ExprId, mut local_lint_level| {
             // `local_lint_level` is the lint level enclosing the pattern inside `expr`.
             let mut expr = &self.thir[expr];
             debug!(?expr, ?local_lint_level, "add");
@@ -348,6 +357,10 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             debug!(?expr, ?local_lint_level, "after scopes");
             match expr.kind {
                 ExprKind::Let { box ref pat, expr: _ } => {
+                    if let Err(err) = pat.pat_error_reported() {
+                        error = Err(err);
+                        return None;
+                    }
                     let mut ncx = self.new_cx(local_lint_level, true);
                     let tpat = self.lower_pattern(&mut ncx, pat);
                     let refutable = !is_let_irrefutable(&mut ncx, local_lint_level, tpat);
@@ -380,6 +393,11 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         debug!(?chain_refutabilities);
         chain_refutabilities.reverse();
 
+        if error.is_err() {
+            self.error = error;
+            return;
+        }
+
         // Third, emit the actual warnings.
         if chain_refutabilities.iter().all(|r| matches!(*r, Some((_, false)))) {
             // The entire chain is made up of irrefutable `let` statements
@@ -426,6 +444,12 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
 
     #[instrument(level = "trace", skip(self))]
     fn check_irrefutable(&mut self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
+        // If we got errors while lowering, don't emit anything more.
+        if let Err(err) = pat.pat_error_reported() {
+            self.error = Err(err);
+            return;
+        }
+
         let mut cx = self.new_cx(self.lint_level, false);
 
         let pattern = self.lower_pattern(&mut cx, pat);
@@ -682,12 +706,6 @@ fn non_exhaustive_match<'p, 'tcx>(
     arms: &[ArmId],
     expr_span: Span,
 ) -> ErrorGuaranteed {
-    for &arm in arms {
-        if let Err(err) = thir[arm].pattern.error_reported() {
-            return err;
-        }
-    }
-
     let is_empty_match = arms.is_empty();
     let non_empty_enum = match scrut_ty.kind() {
         ty::Adt(def, _) => def.is_enum() && !def.variants().is_empty(),
diff --git a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
index fde6defd87f..32d389c4354 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs
@@ -196,9 +196,7 @@ impl<'tcx> ConstToPat<'tcx> {
                     };
                     // All branches above emitted an error. Don't print any more lints.
                     // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                    let kind = PatKind::Constant {
-                        value: mir::Const::Ty(ty::Const::new_error(self.tcx(), e, cv.ty())),
-                    };
+                    let kind = PatKind::Error(e);
                     return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
                 } else if !self.saw_const_match_lint.get() {
                     if let Some(mir_structural_match_violation) = mir_structural_match_violation {
@@ -351,7 +349,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 let e = tcx.sess.emit_err(InvalidPattern { span, non_sm_ty: ty });
                 self.saw_const_match_error.set(Some(e));
                 // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) }
+                PatKind::Error(e)
             }
             ty::Adt(adt_def, _) if !self.type_marked_structural(ty) => {
                 debug!("adt_def {:?} has !type_marked_structural for cv.ty: {:?}", adt_def, ty,);
@@ -359,7 +357,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 let e = tcx.sess.emit_err(err);
                 self.saw_const_match_error.set(Some(e));
                 // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) }
+                PatKind::Error(e)
             }
             ty::Adt(adt_def, args) if adt_def.is_enum() => {
                 let (&variant_index, fields) = cv.unwrap_branch().split_first().unwrap();
@@ -434,17 +432,13 @@ impl<'tcx> ConstToPat<'tcx> {
                     } else {
                         if let Some(e) = self.saw_const_match_error.get() {
                             // We already errored. Signal that in the pattern, so that follow up errors can be silenced.
-                            PatKind::Constant {
-                                value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)),
-                            }
+                            PatKind::Error(e)
                         } else {
                             let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
                             let e = tcx.sess.emit_err(err);
                             self.saw_const_match_error.set(Some(e));
                             // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                            PatKind::Constant {
-                                value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)),
-                            }
+                            PatKind::Error(e)
                         }
                     }
                 }
@@ -456,9 +450,7 @@ impl<'tcx> ConstToPat<'tcx> {
                         let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
                         let e = tcx.sess.emit_err(err);
                         // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                        PatKind::Constant {
-                            value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)),
-                        }
+                        PatKind::Error(e)
                     } else {
                         let old = self.behind_reference.replace(true);
                         // `b"foo"` produces a `&[u8; 3]`, but you can't use constants of array type when
@@ -489,7 +481,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 let e = tcx.sess.emit_err(err);
                 self.saw_const_match_error.set(Some(e));
                 // We errored. Signal that in the pattern, so that follow up errors can be silenced.
-                PatKind::Constant { value: mir::Const::Ty(ty::Const::new_error(tcx, e, ty)) }
+                PatKind::Error(e)
             }
         };
 
diff --git a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
index a7a000ba31c..bbc0aeb66cf 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -1525,6 +1525,10 @@ impl<'p, 'tcx> DeconstructedPat<'p, 'tcx> {
                 let pats = expand_or_pat(pat);
                 fields = Fields::from_iter(cx, pats.into_iter().map(mkpat));
             }
+            PatKind::Error(_) => {
+                ctor = Opaque;
+                fields = Fields::empty();
+            }
         }
         DeconstructedPat::new(ctor, fields, pat.ty, pat.span)
     }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 25726c5a872..76ed6d2b6d7 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -252,10 +252,8 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
             hir::PatKind::Range(ref lo_expr, ref hi_expr, end) => {
                 let (lo_expr, hi_expr) = (lo_expr.as_deref(), hi_expr.as_deref());
-                // FIXME?: returning `_` can cause inaccurate "unreachable" warnings. This can be
-                // fixed by returning `PatKind::Const(ConstKind::Error(...))` if #115937 gets
-                // merged.
-                self.lower_pattern_range(lo_expr, hi_expr, end, ty, span).unwrap_or(PatKind::Wild)
+                self.lower_pattern_range(lo_expr, hi_expr, end, ty, span)
+                    .unwrap_or_else(PatKind::Error)
             }
 
             hir::PatKind::Path(ref qpath) => {
@@ -423,9 +421,9 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 if adt_def.is_enum() {
                     let args = match ty.kind() {
                         ty::Adt(_, args) | ty::FnDef(_, args) => args,
-                        ty::Error(_) => {
+                        ty::Error(e) => {
                             // Avoid ICE (#50585)
-                            return PatKind::Wild;
+                            return PatKind::Error(*e);
                         }
                         _ => bug!("inappropriate type for def: {:?}", ty),
                     };
@@ -452,7 +450,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             | Res::SelfTyAlias { .. }
             | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
             _ => {
-                match res {
+                let e = match res {
                     Res::Def(DefKind::ConstParam, _) => {
                         self.tcx.sess.emit_err(ConstParamInPattern { span })
                     }
@@ -461,7 +459,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     }
                     _ => self.tcx.sess.emit_err(NonConstPath { span }),
                 };
-                PatKind::Wild
+                PatKind::Error(e)
             }
         };
 
@@ -513,14 +511,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 // It should be assoc consts if there's no error but we cannot resolve it.
                 debug_assert!(is_associated_const);
 
-                self.tcx.sess.emit_err(AssocConstInPattern { span });
-
-                return pat_from_kind(PatKind::Wild);
+                let e = self.tcx.sess.emit_err(AssocConstInPattern { span });
+                return pat_from_kind(PatKind::Error(e));
             }
 
             Err(_) => {
-                self.tcx.sess.emit_err(CouldNotEvalConstPattern { span });
-                return pat_from_kind(PatKind::Wild);
+                let e = self.tcx.sess.emit_err(CouldNotEvalConstPattern { span });
+                return pat_from_kind(PatKind::Error(e));
             }
         };
 
@@ -574,12 +571,12 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             Err(ErrorHandled::TooGeneric(_)) => {
                 // While `Reported | Linted` cases will have diagnostics emitted already
                 // it is not true for TooGeneric case, so we need to give user more information.
-                self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
-                pat_from_kind(PatKind::Wild)
+                let e = self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
+                pat_from_kind(PatKind::Error(e))
             }
             Err(_) => {
-                self.tcx.sess.emit_err(CouldNotEvalConstPattern { span });
-                pat_from_kind(PatKind::Wild)
+                let e = self.tcx.sess.emit_err(CouldNotEvalConstPattern { span });
+                pat_from_kind(PatKind::Error(e))
             }
         }
     }
@@ -629,7 +626,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let uneval = mir::UnevaluatedConst { def: def_id.to_def_id(), args, promoted: None };
         debug_assert!(!args.has_free_regions());
 
-        let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args: args };
+        let ct = ty::UnevaluatedConst { def: def_id.to_def_id(), args };
         // First try using a valtree in order to destructure the constant into a pattern.
         // FIXME: replace "try to do a thing, then fall back to another thing"
         // but something more principled, like a trait query checking whether this can be turned into a valtree.
@@ -649,10 +646,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind,
                 Err(ErrorHandled::TooGeneric(_)) => {
                     // If we land here it means the const can't be evaluated because it's `TooGeneric`.
-                    self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
-                    PatKind::Wild
+                    let e = self.tcx.sess.emit_err(ConstPatternDependsOnGenericParameter { span });
+                    PatKind::Error(e)
                 }
-                Err(ErrorHandled::Reported(..)) => PatKind::Wild,
+                Err(ErrorHandled::Reported(err, ..)) => PatKind::Error(err.into()),
             }
         }
     }
@@ -685,7 +682,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             Ok(constant) => {
                 self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind
             }
-            Err(LitToConstError::Reported(_)) => PatKind::Wild,
+            Err(LitToConstError::Reported(e)) => PatKind::Error(e),
             Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
         }
     }
@@ -791,6 +788,7 @@ impl<'tcx> PatternFoldable<'tcx> for PatKind<'tcx> {
     fn super_fold_with<F: PatternFolder<'tcx>>(&self, folder: &mut F) -> Self {
         match *self {
             PatKind::Wild => PatKind::Wild,
+            PatKind::Error(e) => PatKind::Error(e),
             PatKind::AscribeUserType {
                 ref subpattern,
                 ascription: Ascription { ref annotation, variance },
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 3b6276cfeb0..c957611b975 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -757,6 +757,9 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 print_indented!(self, "]", depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
             }
+            PatKind::Error(_) => {
+                print_indented!(self, "Error", depth_lvl + 1);
+            }
         }
 
         print_indented!(self, "}", depth_lvl);
diff --git a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
index 69bc174b6be..8cbd1265448 100644
--- a/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
+++ b/tests/ui/const-generics/generic_const_exprs/typeid-equality-by-subtyping.stderr
@@ -7,17 +7,5 @@ LL |         WHAT_A_TYPE => 0,
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
-error[E0015]: cannot match on `TypeId` in constant functions
-  --> $DIR/typeid-equality-by-subtyping.rs:18:9
-   |
-LL |         WHAT_A_TYPE => 0,
-   |         ^^^^^^^^^^^
-   |
-   = note: `TypeId` cannot be compared in compile-time, and therefore cannot be used in `match`es
-note: impl defined here, but it is not `const`
-  --> $SRC_DIR/core/src/any.rs:LL:COL
-   = note: calls in constant functions are limited to constant functions, tuple structs and tuple variants
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
-For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/pattern/usefulness/consts-opaque.rs b/tests/ui/pattern/usefulness/consts-opaque.rs
index 2032cf13bc2..6dc1425cf03 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.rs
+++ b/tests/ui/pattern/usefulness/consts-opaque.rs
@@ -52,7 +52,6 @@ fn main() {
         BAR => {}
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         _ => {}
-        //~^ ERROR unreachable pattern
     }
 
     match BAR {
@@ -60,7 +59,6 @@ fn main() {
         //~^ ERROR must be annotated with `#[derive(PartialEq, Eq)]`
         Bar => {}
         _ => {}
-        //~^ ERROR unreachable pattern
     }
 
     match BAR {
diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr
index cd88e6a22e4..51f2f276bbe 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.stderr
+++ b/tests/ui/pattern/usefulness/consts-opaque.stderr
@@ -38,7 +38,7 @@ LL |         BAR => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:59:9
+  --> $DIR/consts-opaque.rs:58:9
    |
 LL |         BAR => {}
    |         ^^^
@@ -47,7 +47,7 @@ LL |         BAR => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:67:9
+  --> $DIR/consts-opaque.rs:65:9
    |
 LL |         BAR => {}
    |         ^^^
@@ -56,7 +56,7 @@ LL |         BAR => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:69:9
+  --> $DIR/consts-opaque.rs:67:9
    |
 LL |         BAR => {}
    |         ^^^
@@ -65,7 +65,7 @@ LL |         BAR => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:75:9
+  --> $DIR/consts-opaque.rs:73:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -74,7 +74,7 @@ LL |         BAZ => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:83:9
+  --> $DIR/consts-opaque.rs:81:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -83,7 +83,7 @@ LL |         BAZ => {}
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
 error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:89:9
+  --> $DIR/consts-opaque.rs:87:9
    |
 LL |         BAZ => {}
    |         ^^^
@@ -91,37 +91,14 @@ LL |         BAZ => {}
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralEq.html for details
 
-error: unreachable pattern
-  --> $DIR/consts-opaque.rs:54:9
-   |
-LL |         Bar => {}
-   |         --- matches any value
-...
-LL |         _ => {}
-   |         ^ unreachable pattern
-   |
-note: the lint level is defined here
-  --> $DIR/consts-opaque.rs:6:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
-error: unreachable pattern
-  --> $DIR/consts-opaque.rs:62:9
-   |
-LL |         Bar => {}
-   |         --- matches any value
-LL |         _ => {}
-   |         ^ unreachable pattern
-
 error[E0004]: non-exhaustive patterns: `Wrap(_)` not covered
-  --> $DIR/consts-opaque.rs:124:11
+  --> $DIR/consts-opaque.rs:122:11
    |
 LL |     match WRAPQUUX {
    |           ^^^^^^^^ pattern `Wrap(_)` not covered
    |
 note: `Wrap<fn(usize, usize) -> usize>` defined here
-  --> $DIR/consts-opaque.rs:106:12
+  --> $DIR/consts-opaque.rs:104:12
    |
 LL |     struct Wrap<T>(T);
    |            ^^^^
@@ -132,6 +109,6 @@ LL ~         WRAPQUUX => {},
 LL +         Wrap(_) => todo!()
    |
 
-error: aborting due to 12 previous errors; 1 warning emitted
+error: aborting due to 10 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0004`.