about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2023-04-06 12:42:01 +0000
committerbors <bors@rust-lang.org>2023-04-06 12:42:01 +0000
commit0534655d9b5f61dbd75cf142ec8d2d3f68b550ee (patch)
treea61668d9e1ae870e8da030abd2412c3ecf913e95
parentce3cb03927f711f653ae2937c10ba40a5ede62c7 (diff)
parent1dde34b831089a7acbb14e47810b356bbe951301 (diff)
downloadrust-0534655d9b5f61dbd75cf142ec8d2d3f68b550ee.tar.gz
rust-0534655d9b5f61dbd75cf142ec8d2d3f68b550ee.zip
Auto merge of #108504 - cjgillot:thir-pattern, r=compiler-errors,Nilstrieb
Check pattern refutability on THIR

The current `check_match` query is based on HIR, but partially re-lowers HIR into THIR.
This PR proposed to use the results of the `thir_body` query to check matches, instead of re-building THIR.

Most of the diagnostic changes are spans getting shorter, or commas/semicolons not getting removed.

This PR degrades the diagnostic for confusing constants in patterns (`let A = foo()` where `A` resolves to a `const A` somewhere): it does not point ot the definition of `const A` any more.
-rw-r--r--compiler/rustc_hir/src/pat_util.rs11
-rw-r--r--compiler/rustc_interface/src/passes.rs2
-rw-r--r--compiler/rustc_middle/src/dep_graph/mod.rs4
-rw-r--r--compiler/rustc_middle/src/mir/mod.rs7
-rw-r--r--compiler/rustc_middle/src/query/mod.rs6
-rw-r--r--compiler/rustc_middle/src/thir.rs56
-rw-r--r--compiler/rustc_middle/src/thir/visit.rs1
-rw-r--r--compiler/rustc_mir_build/messages.ftl16
-rw-r--r--compiler/rustc_mir_build/src/build/block.rs2
-rw-r--r--compiler/rustc_mir_build/src/build/mod.rs1
-rw-r--r--compiler/rustc_mir_build/src/errors.rs37
-rw-r--r--compiler/rustc_mir_build/src/thir/cx/block.rs5
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/check_match.rs714
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/const_to_pat.rs33
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs4
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs46
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/usefulness.rs31
-rw-r--r--compiler/rustc_mir_build/src/thir/print.rs2
-rw-r--r--tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir6
-rw-r--r--tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff6
-rw-r--r--tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr10
-rw-r--r--tests/ui/chalkify/bugs/async.stderr17
-rw-r--r--tests/ui/consts/const-eval/const-eval-overflow-2.rs1
-rw-r--r--tests/ui/consts/const-eval/const-eval-overflow-2.stderr8
-rw-r--r--tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr10
-rw-r--r--tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr10
-rw-r--r--tests/ui/consts/const-eval/ref_to_int_match.rs1
-rw-r--r--tests/ui/consts/const-match-check.eval1.stderr4
-rw-r--r--tests/ui/consts/const-match-check.eval2.stderr4
-rw-r--r--tests/ui/consts/const-match-check.matchck.stderr16
-rw-r--r--tests/ui/consts/const-pattern-irrefutable.stderr15
-rw-r--r--tests/ui/consts/const_in_pattern/incomplete-slice.stderr2
-rw-r--r--tests/ui/consts/issue-43105.rs1
-rw-r--r--tests/ui/consts/issue-43105.stderr8
-rw-r--r--tests/ui/consts/issue-73976-polymorphic.rs2
-rw-r--r--tests/ui/consts/issue-73976-polymorphic.stderr16
-rw-r--r--tests/ui/consts/issue-78655.rs1
-rw-r--r--tests/ui/consts/issue-78655.stderr8
-rw-r--r--tests/ui/consts/issue-79137-toogeneric.rs1
-rw-r--r--tests/ui/consts/issue-79137-toogeneric.stderr8
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr32
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr32
-rw-r--r--tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs4
-rw-r--r--tests/ui/error-codes/E0004.stderr2
-rw-r--r--tests/ui/error-codes/E0030-teach.rs1
-rw-r--r--tests/ui/error-codes/E0030-teach.stderr8
-rw-r--r--tests/ui/error-codes/E0030.rs1
-rw-r--r--tests/ui/error-codes/E0030.stderr8
-rw-r--r--tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr2
-rw-r--r--tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr4
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs13
-rw-r--r--tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr102
-rw-r--r--tests/ui/impl-trait/auto-trait-leak.stderr10
-rw-r--r--tests/ui/inline-const/const-match-pat-generic.rs2
-rw-r--r--tests/ui/inline-const/const-match-pat-generic.stderr16
-rw-r--r--tests/ui/match/match-range-fail-2.rs9
-rw-r--r--tests/ui/match/match-range-fail-2.stderr24
-rw-r--r--tests/ui/never_type/exhaustive_patterns.stderr4
-rw-r--r--tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr6
-rw-r--r--tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr6
-rw-r--r--tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr20
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr40
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr5
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr125
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr125
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr160
-rw-r--r--tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr186
-rw-r--r--tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr25
-rw-r--r--tests/ui/pattern/issue-106552.stderr6
-rw-r--r--tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr12
-rw-r--r--tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed2
-rw-r--r--tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr2
-rw-r--r--tests/ui/pattern/usefulness/consts-opaque.stderr156
-rw-r--r--tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr10
-rw-r--r--tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr16
-rw-r--r--tests/ui/pattern/usefulness/empty-match.normal.stderr16
-rw-r--r--tests/ui/pattern/usefulness/floats.stderr2
-rw-r--r--tests/ui/pattern/usefulness/guards.stderr2
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr4
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr6
-rw-r--r--tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr4
-rw-r--r--tests/ui/pattern/usefulness/issue-2111.stderr2
-rw-r--r--tests/ui/pattern/usefulness/issue-30240.stderr4
-rw-r--r--tests/ui/pattern/usefulness/issue-35609.stderr14
-rw-r--r--tests/ui/pattern/usefulness/issue-3601.stderr2
-rw-r--r--tests/ui/pattern/usefulness/issue-50900.stderr2
-rw-r--r--tests/ui/pattern/usefulness/issue-56379.stderr2
-rw-r--r--tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr4
-rw-r--r--tests/ui/pattern/usefulness/match-privately-empty.stderr2
-rw-r--r--tests/ui/pattern/usefulness/match-slice-patterns.stderr2
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr20
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr2
-rw-r--r--tests/ui/pattern/usefulness/non-exhaustive-match.stderr12
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-errors.stderr4
-rw-r--r--tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr4
-rw-r--r--tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr40
-rw-r--r--tests/ui/pattern/usefulness/stable-gated-patterns.stderr4
-rw-r--r--tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr2
-rw-r--r--tests/ui/pattern/usefulness/unstable-gated-patterns.stderr2
-rw-r--r--tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs2
-rw-r--r--tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr16
-rw-r--r--tests/ui/rfc-2005-default-binding-mode/slice.stderr2
-rw-r--r--tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr2
-rw-r--r--tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs5
-rw-r--r--tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr9
-rw-r--r--tests/ui/suggestions/ref-pattern-binding.stderr20
106 files changed, 1041 insertions, 1482 deletions
diff --git a/compiler/rustc_hir/src/pat_util.rs b/compiler/rustc_hir/src/pat_util.rs
index e870aa543d0..838c123f83c 100644
--- a/compiler/rustc_hir/src/pat_util.rs
+++ b/compiler/rustc_hir/src/pat_util.rs
@@ -2,7 +2,6 @@ use crate::def::{CtorOf, DefKind, Res};
 use crate::def_id::DefId;
 use crate::hir::{self, BindingAnnotation, ByRef, HirId, PatKind};
 use rustc_data_structures::fx::FxHashSet;
-use rustc_span::hygiene::DesugaringKind;
 use rustc_span::symbol::Ident;
 use rustc_span::Span;
 
@@ -136,14 +135,4 @@ impl hir::Pat<'_> {
         });
         result
     }
-
-    /// If the pattern is `Some(<pat>)` from a desugared for loop, returns the inner pattern
-    pub fn for_loop_some(&self) -> Option<&Self> {
-        if self.span.desugaring_kind() == Some(DesugaringKind::ForLoop) {
-            if let hir::PatKind::Struct(_, [pat_field], _) = self.kind {
-                return Some(pat_field.pat);
-            }
-        }
-        None
-    }
 }
diff --git a/compiler/rustc_interface/src/passes.rs b/compiler/rustc_interface/src/passes.rs
index 413b40ab808..8d4892470ac 100644
--- a/compiler/rustc_interface/src/passes.rs
+++ b/compiler/rustc_interface/src/passes.rs
@@ -765,7 +765,7 @@ fn analysis(tcx: TyCtxt<'_>, (): ()) -> Result<()> {
         parallel!(
             {
                 sess.time("match_checking", || {
-                    tcx.hir().par_body_owners(|def_id| tcx.ensure().check_match(def_id.to_def_id()))
+                    tcx.hir().par_body_owners(|def_id| tcx.ensure().check_match(def_id))
                 });
             },
             {
diff --git a/compiler/rustc_middle/src/dep_graph/mod.rs b/compiler/rustc_middle/src/dep_graph/mod.rs
index 84510fe218c..0ddbe7d1c29 100644
--- a/compiler/rustc_middle/src/dep_graph/mod.rs
+++ b/compiler/rustc_middle/src/dep_graph/mod.rs
@@ -94,7 +94,7 @@ impl<'tcx> DepContext for TyCtxt<'tcx> {
     }
 
     #[inline]
-    fn dep_kind_info(&self, dep_kind: DepKind) -> &DepKindStruct<'tcx> {
-        &self.query_kinds[dep_kind as usize]
+    fn dep_kind_info(&self, dk: DepKind) -> &DepKindStruct<'tcx> {
+        &self.query_kinds[dk as usize]
     }
 }
diff --git a/compiler/rustc_middle/src/mir/mod.rs b/compiler/rustc_middle/src/mir/mod.rs
index b88a315cec1..0fad30973db 100644
--- a/compiler/rustc_middle/src/mir/mod.rs
+++ b/compiler/rustc_middle/src/mir/mod.rs
@@ -2001,6 +2001,13 @@ impl<'tcx> Rvalue<'tcx> {
 }
 
 impl BorrowKind {
+    pub fn mutability(&self) -> Mutability {
+        match *self {
+            BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => Mutability::Not,
+            BorrowKind::Mut { .. } => Mutability::Mut,
+        }
+    }
+
     pub fn allows_two_phase_borrow(&self) -> bool {
         match *self {
             BorrowKind::Shared | BorrowKind::Shallow | BorrowKind::Unique => false,
diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs
index 9203dd59a7e..d31b11f0892 100644
--- a/compiler/rustc_middle/src/query/mod.rs
+++ b/compiler/rustc_middle/src/query/mod.rs
@@ -1114,9 +1114,9 @@ rustc_queries! {
         desc { "converting literal to mir constant" }
     }
 
-    query check_match(key: DefId) {
-        desc { |tcx| "match-checking `{}`", tcx.def_path_str(key) }
-        cache_on_disk_if { key.is_local() }
+    query check_match(key: LocalDefId) {
+        desc { |tcx| "match-checking `{}`", tcx.def_path_str(key.to_def_id()) }
+        cache_on_disk_if { true }
     }
 
     /// Performs part of the privacy check and computes effective visibilities.
diff --git a/compiler/rustc_middle/src/thir.rs b/compiler/rustc_middle/src/thir.rs
index 82a7cf78517..7d79a13d3fd 100644
--- a/compiler/rustc_middle/src/thir.rs
+++ b/compiler/rustc_middle/src/thir.rs
@@ -227,6 +227,9 @@ pub enum StmtKind<'tcx> {
 
         /// The lint level for this `let` statement.
         lint_level: LintLevel,
+
+        /// Span of the `let <PAT> = <INIT>` part.
+        span: Span,
     },
 }
 
@@ -594,6 +597,55 @@ impl<'tcx> Pat<'tcx> {
             _ => None,
         }
     }
+
+    /// Call `f` on every "binding" in a pattern, e.g., on `a` in
+    /// `match foo() { Some(a) => (), None => () }`
+    pub fn each_binding(&self, mut f: impl FnMut(Symbol, BindingMode, Ty<'tcx>, Span)) {
+        self.walk_always(|p| {
+            if let PatKind::Binding { name, mode, ty, .. } = p.kind {
+                f(name, mode, ty, p.span);
+            }
+        });
+    }
+
+    /// Walk the pattern in left-to-right order.
+    ///
+    /// If `it(pat)` returns `false`, the children are not visited.
+    pub fn walk(&self, mut it: impl FnMut(&Pat<'tcx>) -> bool) {
+        self.walk_(&mut it)
+    }
+
+    fn walk_(&self, it: &mut impl FnMut(&Pat<'tcx>) -> bool) {
+        if !it(self) {
+            return;
+        }
+
+        use PatKind::*;
+        match &self.kind {
+            Wild | Range(..) | Binding { subpattern: None, .. } | Constant { .. } => {}
+            AscribeUserType { subpattern, .. }
+            | Binding { subpattern: Some(subpattern), .. }
+            | Deref { subpattern } => subpattern.walk_(it),
+            Leaf { subpatterns } | Variant { subpatterns, .. } => {
+                subpatterns.iter().for_each(|field| field.pattern.walk_(it))
+            }
+            Or { pats } => pats.iter().for_each(|p| p.walk_(it)),
+            Array { box ref prefix, ref slice, box ref suffix }
+            | Slice { box ref prefix, ref slice, box ref suffix } => {
+                prefix.iter().chain(slice.iter()).chain(suffix.iter()).for_each(|p| p.walk_(it))
+            }
+        }
+    }
+
+    /// Walk the pattern in left-to-right order.
+    ///
+    /// If you always want to recurse, prefer this method over `walk`.
+    pub fn walk_always(&self, mut it: impl FnMut(&Pat<'tcx>)) {
+        self.walk(|p| {
+            it(p);
+            true
+        })
+    }
 }
 
 impl<'tcx> IntoDiagnosticArg for Pat<'tcx> {
@@ -879,7 +931,7 @@ mod size_asserts {
     static_assert_size!(ExprKind<'_>, 40);
     static_assert_size!(Pat<'_>, 72);
     static_assert_size!(PatKind<'_>, 56);
-    static_assert_size!(Stmt<'_>, 48);
-    static_assert_size!(StmtKind<'_>, 40);
+    static_assert_size!(Stmt<'_>, 56);
+    static_assert_size!(StmtKind<'_>, 48);
     // tidy-alphabetical-end
 }
diff --git a/compiler/rustc_middle/src/thir/visit.rs b/compiler/rustc_middle/src/thir/visit.rs
index 79a0e75aa7c..5614528c4cb 100644
--- a/compiler/rustc_middle/src/thir/visit.rs
+++ b/compiler/rustc_middle/src/thir/visit.rs
@@ -175,6 +175,7 @@ pub fn walk_stmt<'a, 'tcx: 'a, V: Visitor<'a, 'tcx>>(visitor: &mut V, stmt: &Stm
             ref pattern,
             lint_level: _,
             else_block,
+            span: _,
         } => {
             if let Some(init) = initializer {
                 visitor.visit_expr(&visitor.thir()[*init]);
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index fcc7cbe0715..f346cd48347 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -239,19 +239,9 @@ mir_build_trailing_irrefutable_let_patterns = trailing irrefutable {$count ->
     } into the body
 
 mir_build_bindings_with_variant_name =
-    pattern binding `{$ident}` is named the same as one of the variants of the type `{$ty_path}`
+    pattern binding `{$name}` is named the same as one of the variants of the type `{$ty_path}`
     .suggestion = to match on the variant, qualify the path
 
-mir_build_irrefutable_let_patterns_generic_let = irrefutable `let` {$count ->
-        [one] pattern
-        *[other] patterns
-    }
-    .note = {$count ->
-        [one] this pattern
-        *[other] these patterns
-    } will always match, so the `let` is useless
-    .help = consider removing `let`
-
 mir_build_irrefutable_let_patterns_if_let = irrefutable `if let` {$count ->
         [one] pattern
         *[other] patterns
@@ -357,15 +347,13 @@ mir_build_inform_irrefutable = `let` bindings require an "irrefutable pattern",
 
 mir_build_more_information = for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
 
-mir_build_res_defined_here = {$res} defined here
-
 mir_build_adt_defined_here = `{$ty}` defined here
 
 mir_build_variant_defined_here = not covered
 
 mir_build_interpreted_as_const = introduce a variable instead
 
-mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as {$article} {$res} pattern, not a new variable
+mir_build_confused = missing patterns are not covered because `{$variable}` is interpreted as a constant pattern, not a new variable
 
 mir_build_suggest_if_let = you might want to use `if let` to ignore the {$count ->
         [one] variant that isn't
diff --git a/compiler/rustc_mir_build/src/build/block.rs b/compiler/rustc_mir_build/src/build/block.rs
index 2643d33cee0..609ab19289c 100644
--- a/compiler/rustc_mir_build/src/build/block.rs
+++ b/compiler/rustc_mir_build/src/build/block.rs
@@ -115,6 +115,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     initializer: Some(initializer),
                     lint_level,
                     else_block: Some(else_block),
+                    span: _,
                 } => {
                     // When lowering the statement `let <pat> = <expr> else { <else> };`,
                     // the `<else>` block is nested in the parent scope enclosing this statement.
@@ -278,6 +279,7 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     initializer,
                     lint_level,
                     else_block: None,
+                    span: _,
                 } => {
                     let ignores_expr_result = matches!(pattern.kind, PatKind::Wild);
                     this.block_context.push(BlockFrame::Statement { ignores_expr_result });
diff --git a/compiler/rustc_mir_build/src/build/mod.rs b/compiler/rustc_mir_build/src/build/mod.rs
index ac645cce5c6..415f5b1b1e1 100644
--- a/compiler/rustc_mir_build/src/build/mod.rs
+++ b/compiler/rustc_mir_build/src/build/mod.rs
@@ -58,6 +58,7 @@ fn mir_build(tcx: TyCtxt<'_>, def: ty::WithOptConstParam<LocalDefId>) -> Body<'_
         ty::WithOptConstParam { did, const_param_did: None } => {
             tcx.ensure_with_value().thir_check_unsafety(did);
             tcx.ensure_with_value().thir_abstract_const(did);
+            tcx.ensure_with_value().check_match(did);
         }
     }
 
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index cbfca77bd25..431c3255ab2 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -6,11 +6,11 @@ use rustc_errors::{
     error_code, AddToDiagnostic, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed,
     Handler, IntoDiagnostic, MultiSpan, SubdiagnosticMessage,
 };
-use rustc_hir::def::Res;
 use rustc_macros::{Diagnostic, LintDiagnostic, Subdiagnostic};
 use rustc_middle::thir::Pat;
 use rustc_middle::ty::{self, Ty};
-use rustc_span::{symbol::Ident, Span};
+use rustc_span::symbol::Symbol;
+use rustc_span::Span;
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_unconditional_recursion)]
@@ -534,18 +534,10 @@ pub struct TrailingIrrefutableLetPatterns {
 #[derive(LintDiagnostic)]
 #[diag(mir_build_bindings_with_variant_name, code = "E0170")]
 pub struct BindingsWithVariantName {
-    #[suggestion(code = "{ty_path}::{ident}", applicability = "machine-applicable")]
+    #[suggestion(code = "{ty_path}::{name}", applicability = "machine-applicable")]
     pub suggestion: Option<Span>,
     pub ty_path: String,
-    pub ident: Ident,
-}
-
-#[derive(LintDiagnostic)]
-#[diag(mir_build_irrefutable_let_patterns_generic_let)]
-#[note]
-#[help]
-pub struct IrrefutableLetPatternsGenericLet {
-    pub count: usize,
+    pub name: Symbol,
 }
 
 #[derive(LintDiagnostic)]
@@ -584,13 +576,12 @@ pub struct IrrefutableLetPatternsWhileLet {
 #[diag(mir_build_borrow_of_moved_value)]
 pub struct BorrowOfMovedValue<'tcx> {
     #[primary_span]
-    pub span: Span,
     #[label]
     #[label(mir_build_occurs_because_label)]
     pub binding_span: Span,
     #[label(mir_build_value_borrowed_label)]
     pub conflicts_ref: Vec<Span>,
-    pub name: Ident,
+    pub name: Symbol,
     pub ty: Ty<'tcx>,
     #[suggestion(code = "ref ", applicability = "machine-applicable")]
     pub suggest_borrowing: Option<Span>,
@@ -638,19 +629,19 @@ pub enum Conflict {
     Mut {
         #[primary_span]
         span: Span,
-        name: Ident,
+        name: Symbol,
     },
     #[label(mir_build_borrow)]
     Ref {
         #[primary_span]
         span: Span,
-        name: Ident,
+        name: Symbol,
     },
     #[label(mir_build_moved)]
     Moved {
         #[primary_span]
         span: Span,
-        name: Ident,
+        name: Symbol,
     },
 }
 
@@ -802,8 +793,6 @@ pub(crate) struct PatternNotCovered<'s, 'tcx> {
     pub let_suggestion: Option<SuggestLet>,
     #[subdiagnostic]
     pub misc_suggestion: Option<MiscPatternSuggestion>,
-    #[subdiagnostic]
-    pub res_defined_here: Option<ResDefinedHere>,
 }
 
 #[derive(Subdiagnostic)]
@@ -838,14 +827,6 @@ impl<'tcx> AddToDiagnostic for AdtDefinedHere<'tcx> {
 }
 
 #[derive(Subdiagnostic)]
-#[label(mir_build_res_defined_here)]
-pub struct ResDefinedHere {
-    #[primary_span]
-    pub def_span: Span,
-    pub res: Res,
-}
-
-#[derive(Subdiagnostic)]
 #[suggestion(
     mir_build_interpreted_as_const,
     code = "{variable}_var",
@@ -855,9 +836,7 @@ pub struct ResDefinedHere {
 pub struct InterpretedAsConst {
     #[primary_span]
     pub span: Span,
-    pub article: &'static str,
     pub variable: String,
-    pub res: Res,
 }
 
 #[derive(Subdiagnostic)]
diff --git a/compiler/rustc_mir_build/src/thir/cx/block.rs b/compiler/rustc_mir_build/src/thir/cx/block.rs
index 321353ca20b..8aacec53f94 100644
--- a/compiler/rustc_mir_build/src/thir/cx/block.rs
+++ b/compiler/rustc_mir_build/src/thir/cx/block.rs
@@ -105,6 +105,10 @@ impl<'tcx> Cx<'tcx> {
                             }
                         }
 
+                        let span = match local.init {
+                            Some(init) => local.span.with_hi(init.span.hi()),
+                            None => local.span,
+                        };
                         let stmt = Stmt {
                             kind: StmtKind::Let {
                                 remainder_scope,
@@ -116,6 +120,7 @@ impl<'tcx> Cx<'tcx> {
                                 initializer: local.init.map(|init| self.mirror_expr(init)),
                                 else_block,
                                 lint_level: LintLevel::Explicit(local.hir_id),
+                                span,
                             },
                             opt_destruction_scope: opt_dxn_ext,
                         };
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 2640ca56b00..0882b473f10 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/check_match.rs
@@ -2,45 +2,48 @@ use super::deconstruct_pat::{Constructor, DeconstructedPat};
 use super::usefulness::{
     compute_match_usefulness, MatchArm, MatchCheckCtxt, Reachability, UsefulnessReport,
 };
-use super::{PatCtxt, PatternError};
 
 use crate::errors::*;
 
-use hir::{ExprKind, PatKind};
 use rustc_arena::TypedArena;
-use rustc_ast::{LitKind, Mutability};
+use rustc_ast::Mutability;
+use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_errors::{
     struct_span_err, Applicability, Diagnostic, DiagnosticBuilder, ErrorGuaranteed, MultiSpan,
 };
 use rustc_hir as hir;
 use rustc_hir::def::*;
-use rustc_hir::def_id::DefId;
-use rustc_hir::intravisit::{self, Visitor};
-use rustc_hir::{HirId, Pat};
+use rustc_hir::def_id::LocalDefId;
+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};
-
 use rustc_session::lint::builtin::{
     BINDINGS_WITH_VARIANT_NAME, IRREFUTABLE_LET_PATTERNS, UNREACHABLE_PATTERNS,
 };
 use rustc_session::Session;
-use rustc_span::source_map::Spanned;
-use rustc_span::{BytePos, Span};
-
-pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: DefId) {
-    let body_id = match def_id.as_local() {
-        None => return,
-        Some(def_id) => tcx.hir().body_owned_by(def_id),
-    };
+use rustc_span::hygiene::DesugaringKind;
+use rustc_span::Span;
 
+pub(crate) fn check_match(tcx: TyCtxt<'_>, def_id: LocalDefId) {
+    let Ok((thir, expr)) = tcx.thir_body(ty::WithOptConstParam::unknown(def_id)) else { return };
+    let thir = thir.borrow();
     let pattern_arena = TypedArena::default();
     let mut visitor = MatchVisitor {
         tcx,
-        typeck_results: tcx.typeck_body(body_id),
+        thir: &*thir,
         param_env: tcx.param_env(def_id),
+        lint_level: tcx.hir().local_def_id_to_hir_id(def_id),
+        let_source: LetSource::None,
         pattern_arena: &pattern_arena,
     };
-    visitor.visit_body(tcx.hir().body(body_id));
+    visitor.visit_expr(&thir[expr]);
+    for param in thir.params.iter() {
+        if let Some(box ref pattern) = param.pat {
+            visitor.check_irrefutable(pattern, "function argument", None);
+        }
+    }
 }
 
 fn create_e0004(
@@ -58,77 +61,132 @@ enum RefutableFlag {
 }
 use RefutableFlag::*;
 
+#[derive(Clone, Copy, Debug, PartialEq, Eq)]
+enum LetSource {
+    None,
+    IfLet,
+    IfLetGuard,
+    LetElse,
+    WhileLet,
+}
+
 struct MatchVisitor<'a, 'p, 'tcx> {
     tcx: TyCtxt<'tcx>,
-    typeck_results: &'a ty::TypeckResults<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
+    thir: &'a Thir<'tcx>,
+    lint_level: HirId,
+    let_source: LetSource,
     pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
 }
 
-impl<'tcx> Visitor<'tcx> for MatchVisitor<'_, '_, 'tcx> {
-    fn visit_expr(&mut self, ex: &'tcx hir::Expr<'tcx>) {
-        intravisit::walk_expr(self, ex);
-        match &ex.kind {
-            hir::ExprKind::Match(scrut, arms, source) => {
-                self.check_match(scrut, arms, *source, ex.span)
+impl<'a, 'tcx> Visitor<'a, 'tcx> for MatchVisitor<'a, '_, 'tcx> {
+    fn thir(&self) -> &'a Thir<'tcx> {
+        self.thir
+    }
+
+    #[instrument(level = "trace", skip(self))]
+    fn visit_arm(&mut self, arm: &Arm<'tcx>) {
+        match arm.guard {
+            Some(Guard::If(expr)) => {
+                self.with_let_source(LetSource::IfLetGuard, |this| {
+                    this.visit_expr(&this.thir[expr])
+                });
             }
-            hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => {
-                self.check_let(pat, init, *span)
+            Some(Guard::IfLet(ref pat, expr)) => {
+                self.with_let_source(LetSource::IfLetGuard, |this| {
+                    this.check_let(pat, expr, LetSource::IfLetGuard, pat.span);
+                    this.visit_pat(pat);
+                    this.visit_expr(&this.thir[expr]);
+                });
             }
-            _ => {}
+            None => {}
         }
+        self.visit_pat(&arm.pattern);
+        self.visit_expr(&self.thir[arm.body]);
     }
 
-    fn visit_local(&mut self, loc: &'tcx hir::Local<'tcx>) {
-        intravisit::walk_local(self, loc);
-        let els = loc.els;
-        if let Some(init) = loc.init && els.is_some() {
-            // Build a span without the else { ... } as we don't want to underline
-            // the entire else block in the IDE setting.
-            let span = loc.span.with_hi(init.span.hi());
-            self.check_let(&loc.pat, init, span);
-        }
-
-        let (msg, sp) = match loc.source {
-            hir::LocalSource::Normal => ("local binding", Some(loc.span)),
-            hir::LocalSource::AsyncFn => ("async fn binding", None),
-            hir::LocalSource::AwaitDesugar => ("`await` future binding", None),
-            hir::LocalSource::AssignDesugar(_) => ("destructuring assignment binding", None),
+    #[instrument(level = "trace", skip(self))]
+    fn visit_expr(&mut self, ex: &Expr<'tcx>) {
+        match ex.kind {
+            ExprKind::Scope { value, lint_level, .. } => {
+                let old_lint_level = self.lint_level;
+                if let LintLevel::Explicit(hir_id) = lint_level {
+                    self.lint_level = hir_id;
+                }
+                self.visit_expr(&self.thir[value]);
+                self.lint_level = old_lint_level;
+                return;
+            }
+            ExprKind::If { cond, then, else_opt, if_then_scope: _ } => {
+                // Give a specific `let_source` for the condition.
+                let let_source = match ex.span.desugaring_kind() {
+                    Some(DesugaringKind::WhileLoop) => LetSource::WhileLet,
+                    _ => LetSource::IfLet,
+                };
+                self.with_let_source(let_source, |this| this.visit_expr(&self.thir[cond]));
+                self.with_let_source(LetSource::None, |this| {
+                    this.visit_expr(&this.thir[then]);
+                    if let Some(else_) = else_opt {
+                        this.visit_expr(&this.thir[else_]);
+                    }
+                });
+                return;
+            }
+            ExprKind::Match { scrutinee, box ref arms } => {
+                let source = match ex.span.desugaring_kind() {
+                    Some(DesugaringKind::ForLoop) => hir::MatchSource::ForLoopDesugar,
+                    Some(DesugaringKind::QuestionMark) => hir::MatchSource::TryDesugar,
+                    Some(DesugaringKind::Await) => hir::MatchSource::AwaitDesugar,
+                    _ => hir::MatchSource::Normal,
+                };
+                self.check_match(scrutinee, arms, source, ex.span);
+            }
+            ExprKind::Let { box ref pat, expr } => {
+                self.check_let(pat, expr, self.let_source, ex.span);
+            }
+            ExprKind::LogicalOp { op: LogicalOp::And, lhs, rhs } => {
+                self.check_let_chain(self.let_source, ex.span, lhs, rhs);
+            }
+            _ => {}
         };
-        if els.is_none() {
-            self.check_irrefutable(&loc.pat, msg, sp);
-        }
+        self.with_let_source(LetSource::None, |this| visit::walk_expr(this, ex));
     }
 
-    fn visit_param(&mut self, param: &'tcx hir::Param<'tcx>) {
-        intravisit::walk_param(self, param);
-        self.check_irrefutable(&param.pat, "function argument", None);
-    }
-}
-
-impl PatCtxt<'_, '_> {
-    fn report_inlining_errors(&self) {
-        for error in &self.errors {
-            match *error {
-                PatternError::StaticInPattern(span) => {
-                    self.tcx.sess.emit_err(StaticInPattern { span });
+    fn visit_stmt(&mut self, stmt: &Stmt<'tcx>) {
+        let old_lint_level = self.lint_level;
+        match stmt.kind {
+            StmtKind::Let {
+                box ref pattern, initializer, else_block, lint_level, span, ..
+            } => {
+                if let LintLevel::Explicit(lint_level) = lint_level {
+                    self.lint_level = lint_level;
                 }
-                PatternError::AssocConstInPattern(span) => {
-                    self.tcx.sess.emit_err(AssocConstInPattern { span });
-                }
-                PatternError::ConstParamInPattern(span) => {
-                    self.tcx.sess.emit_err(ConstParamInPattern { span });
+
+                if let Some(initializer) = initializer && else_block.is_some() {
+                    self.check_let(pattern, initializer, LetSource::LetElse, span);
                 }
-                PatternError::NonConstPath(span) => {
-                    self.tcx.sess.emit_err(NonConstPath { span });
+
+                if else_block.is_none() {
+                    self.check_irrefutable(pattern, "local binding", Some(span));
                 }
             }
+            _ => {}
         }
+        visit::walk_stmt(self, stmt);
+        self.lint_level = old_lint_level;
     }
 }
 
 impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
-    fn check_patterns(&self, pat: &Pat<'_>, rf: RefutableFlag) {
+    #[instrument(level = "trace", skip(self, f))]
+    fn with_let_source(&mut self, let_source: LetSource, f: impl FnOnce(&mut Self)) {
+        let old_let_source = self.let_source;
+        self.let_source = let_source;
+        ensure_sufficient_stack(|| f(self));
+        self.let_source = old_let_source;
+    }
+
+    fn check_patterns(&self, pat: &Pat<'tcx>, rf: RefutableFlag) {
         pat.walk_always(|pat| check_borrow_conflicts_in_at_patterns(self, pat));
         check_for_bindings_named_same_as_variants(self, pat, rf);
     }
@@ -136,73 +194,63 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
     fn lower_pattern(
         &self,
         cx: &mut MatchCheckCtxt<'p, 'tcx>,
-        pat: &'tcx hir::Pat<'tcx>,
-        have_errors: &mut bool,
+        pattern: &Pat<'tcx>,
     ) -> &'p DeconstructedPat<'p, 'tcx> {
-        let mut patcx = PatCtxt::new(self.tcx, self.param_env, self.typeck_results);
-        patcx.include_lint_checks();
-        let pattern = patcx.lower_pattern(pat);
-        let pattern: &_ = cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern));
-        if !patcx.errors.is_empty() {
-            *have_errors = true;
-            patcx.report_inlining_errors();
-        }
-        pattern
+        cx.pattern_arena.alloc(DeconstructedPat::from_pat(cx, &pattern))
     }
 
-    fn new_cx(&self, hir_id: HirId) -> MatchCheckCtxt<'p, 'tcx> {
+    fn new_cx(&self, hir_id: HirId, refutable: bool) -> MatchCheckCtxt<'p, 'tcx> {
         MatchCheckCtxt {
             tcx: self.tcx,
             param_env: self.param_env,
             module: self.tcx.parent_module(hir_id).to_def_id(),
             pattern_arena: &self.pattern_arena,
+            refutable,
         }
     }
 
-    fn check_let(&mut self, pat: &'tcx hir::Pat<'tcx>, scrutinee: &hir::Expr<'_>, span: Span) {
+    #[instrument(level = "trace", skip(self))]
+    fn check_let(&mut self, pat: &Pat<'tcx>, scrutinee: ExprId, source: LetSource, span: Span) {
+        if let LetSource::None = source {
+            return;
+        }
         self.check_patterns(pat, Refutable);
-        let mut cx = self.new_cx(scrutinee.hir_id);
-        let tpat = self.lower_pattern(&mut cx, pat, &mut false);
-        self.check_let_reachability(&mut cx, pat.hir_id, tpat, span);
+        let mut cx = self.new_cx(self.lint_level, true);
+        let tpat = self.lower_pattern(&mut cx, pat);
+        self.check_let_reachability(&mut cx, self.lint_level, source, tpat, span);
     }
 
     fn check_match(
         &mut self,
-        scrut: &hir::Expr<'_>,
-        hir_arms: &'tcx [hir::Arm<'tcx>],
+        scrut: ExprId,
+        arms: &[ArmId],
         source: hir::MatchSource,
         expr_span: Span,
     ) {
-        let mut cx = self.new_cx(scrut.hir_id);
+        let mut cx = self.new_cx(self.lint_level, true);
 
-        for arm in hir_arms {
+        for &arm in arms {
             // Check the arm for some things unrelated to exhaustiveness.
-            self.check_patterns(&arm.pat, Refutable);
-            if let Some(hir::Guard::IfLet(ref let_expr)) = arm.guard {
-                self.check_patterns(let_expr.pat, Refutable);
-                let tpat = self.lower_pattern(&mut cx, let_expr.pat, &mut false);
-                self.check_let_reachability(&mut cx, let_expr.pat.hir_id, tpat, tpat.span());
-            }
+            let arm = &self.thir.arms[arm];
+            self.check_patterns(&arm.pattern, Refutable);
         }
 
-        let mut have_errors = false;
-
-        let arms: Vec<_> = hir_arms
+        let tarms: Vec<_> = arms
             .iter()
-            .map(|hir::Arm { pat, guard, .. }| MatchArm {
-                pat: self.lower_pattern(&mut cx, pat, &mut have_errors),
-                hir_id: pat.hir_id,
-                has_guard: guard.is_some(),
+            .map(|&arm| {
+                let arm = &self.thir.arms[arm];
+                let hir_id = match arm.lint_level {
+                    LintLevel::Explicit(hir_id) => hir_id,
+                    LintLevel::Inherited => self.lint_level,
+                };
+                let pat = self.lower_pattern(&mut cx, &arm.pattern);
+                MatchArm { pat, hir_id, has_guard: arm.guard.is_some() }
             })
             .collect();
 
-        // Bail out early if lowering failed.
-        if have_errors {
-            return;
-        }
-
-        let scrut_ty = self.typeck_results.expr_ty_adjusted(scrut);
-        let report = compute_match_usefulness(&cx, &arms, scrut.hir_id, scrut_ty);
+        let scrut = &self.thir[scrut];
+        let scrut_ty = scrut.ty;
+        let report = compute_match_usefulness(&cx, &tarms, self.lint_level, scrut_ty);
 
         match source {
             // Don't report arm reachability of desugared `match $iter.into_iter() { iter => .. }`
@@ -219,12 +267,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         // Check if the match is exhaustive.
         let witnesses = report.non_exhaustiveness_witnesses;
         if !witnesses.is_empty() {
-            if source == hir::MatchSource::ForLoopDesugar && hir_arms.len() == 2 {
+            if source == hir::MatchSource::ForLoopDesugar && arms.len() == 2 {
                 // the for loop pattern is not irrefutable
-                let pat = hir_arms[1].pat.for_loop_some().unwrap();
-                self.check_irrefutable(pat, "`for` loop binding", None);
+                let pat = &self.thir[arms[1]].pattern;
+                // `pat` should be `Some(<pat_field>)` from a desugared for loop.
+                debug_assert_eq!(pat.span.desugaring_kind(), Some(DesugaringKind::ForLoop));
+                let PatKind::Variant { ref subpatterns, .. } = pat.kind else { bug!() };
+                let [pat_field] = &subpatterns[..] else { bug!() };
+                self.check_irrefutable(&pat_field.pattern, "`for` loop binding", None);
             } else {
-                non_exhaustive_match(&cx, scrut_ty, scrut.span, witnesses, hir_arms, expr_span);
+                non_exhaustive_match(
+                    &cx, self.thir, scrut_ty, scrut.span, witnesses, arms, expr_span,
+                );
             }
         }
     }
@@ -233,114 +287,96 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
         &mut self,
         cx: &mut MatchCheckCtxt<'p, 'tcx>,
         pat_id: HirId,
+        source: LetSource,
         pat: &'p DeconstructedPat<'p, 'tcx>,
         span: Span,
     ) {
-        if self.check_let_chain(cx, pat_id) {
-            return;
-        }
-
         if is_let_irrefutable(cx, pat_id, pat) {
-            irrefutable_let_pattern(cx.tcx, pat_id, span);
+            irrefutable_let_patterns(cx.tcx, pat_id, source, 1, span);
         }
     }
 
-    fn check_let_chain(&mut self, cx: &mut MatchCheckCtxt<'p, 'tcx>, pat_id: HirId) -> bool {
-        let hir = self.tcx.hir();
-        let parent = hir.parent_id(pat_id);
+    #[instrument(level = "trace", skip(self))]
+    fn check_let_chain(
+        &mut self,
+        let_source: LetSource,
+        top_expr_span: Span,
+        mut lhs: ExprId,
+        rhs: ExprId,
+    ) {
+        if let LetSource::None = let_source {
+            return;
+        }
 
-        // First, figure out if the given pattern is part of a let chain,
-        // and if so, obtain the top node of the chain.
-        let mut top = parent;
-        let mut part_of_chain = false;
-        loop {
-            let new_top = hir.parent_id(top);
-            if let hir::Node::Expr(
-                hir::Expr {
-                    kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, lhs, rhs),
-                    ..
-                },
-                ..,
-            ) = hir.get(new_top)
-            {
-                // If this isn't the first iteration, we need to check
-                // if there is a let expr before us in the chain, so
-                // that we avoid doubly checking the let chain.
-
-                // The way a chain of &&s is encoded is ((let ... && let ...) && let ...) && let ...
-                // as && is left-to-right associative. Thus, we need to check rhs.
-                if part_of_chain && matches!(rhs.kind, hir::ExprKind::Let(..)) {
-                    return true;
+        // Lint level enclosing the next `lhs`.
+        let mut cur_lint_level = self.lint_level;
+
+        // Obtain the refutabilities of all exprs in the chain,
+        // and record chain members that aren't let exprs.
+        let mut chain_refutabilities = Vec::new();
+
+        let 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");
+            // Fast-forward through scopes.
+            while let ExprKind::Scope { value, lint_level, .. } = expr.kind {
+                if let LintLevel::Explicit(hir_id) = lint_level {
+                    local_lint_level = hir_id
                 }
-                // If there is a let at the lhs, and we provide the rhs, we don't do any checking either.
-                if !part_of_chain && matches!(lhs.kind, hir::ExprKind::Let(..)) && rhs.hir_id == top
-                {
-                    return true;
+                expr = &self.thir[value];
+            }
+            debug!(?expr, ?local_lint_level, "after scopes");
+            match expr.kind {
+                ExprKind::Let { box ref pat, expr: _ } => {
+                    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);
+                    Some((expr.span, refutable))
                 }
-            } else {
-                // We've reached the top.
-                break;
+                ExprKind::LogicalOp { op: LogicalOp::And, .. } => {
+                    bug!()
+                }
+                _ => None,
             }
+        };
 
-            // Since this function is called within a let context, it is reasonable to assume that any parent
-            // `&&` infers a let chain
-            part_of_chain = true;
-            top = new_top;
-        }
-        if !part_of_chain {
-            return false;
-        }
+        // Let chains recurse on the left, so we start by adding the rightmost.
+        chain_refutabilities.push(add(rhs, cur_lint_level));
 
-        // Second, obtain the refutabilities of all exprs in the chain,
-        // and record chain members that aren't let exprs.
-        let mut chain_refutabilities = Vec::new();
-        let hir::Node::Expr(top_expr) = hir.get(top) else {
-            // We ensure right above that it's an Expr
-            unreachable!()
-        };
-        let mut cur_expr = top_expr;
         loop {
-            let mut add = |expr: &hir::Expr<'tcx>| {
-                let refutability = match expr.kind {
-                    hir::ExprKind::Let(hir::Let { pat, init, span, .. }) => {
-                        let mut ncx = self.new_cx(init.hir_id);
-                        let tpat = self.lower_pattern(&mut ncx, pat, &mut false);
-
-                        let refutable = !is_let_irrefutable(&mut ncx, pat.hir_id, tpat);
-                        Some((*span, refutable))
-                    }
-                    _ => None,
-                };
-                chain_refutabilities.push(refutability);
-            };
-            if let hir::Expr {
-                kind: hir::ExprKind::Binary(Spanned { node: hir::BinOpKind::And, .. }, lhs, rhs),
-                ..
-            } = cur_expr
+            while let ExprKind::Scope { value, lint_level, .. } = self.thir[lhs].kind {
+                if let LintLevel::Explicit(hir_id) = lint_level {
+                    cur_lint_level = hir_id
+                }
+                lhs = value;
+            }
+            if let ExprKind::LogicalOp { op: LogicalOp::And, lhs: new_lhs, rhs: expr } =
+                self.thir[lhs].kind
             {
-                add(rhs);
-                cur_expr = lhs;
+                chain_refutabilities.push(add(expr, cur_lint_level));
+                lhs = new_lhs;
             } else {
-                add(cur_expr);
+                chain_refutabilities.push(add(lhs, cur_lint_level));
                 break;
             }
         }
+        debug!(?chain_refutabilities);
         chain_refutabilities.reverse();
 
         // 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
-            let let_source = let_source_parent(self.tcx, top, None);
             irrefutable_let_patterns(
-                cx.tcx,
-                top,
+                self.tcx,
+                self.lint_level,
                 let_source,
                 chain_refutabilities.len(),
-                top_expr.span,
+                top_expr_span,
             );
-            return true;
+            return;
         }
+
         if let Some(until) = chain_refutabilities.iter().position(|r| !matches!(*r, Some((_, false)))) && until > 0 {
             // The chain has a non-zero prefix of irrefutable `let` statements.
 
@@ -350,7 +386,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             // so can't always be moved out.
             // FIXME: Add checking whether the bindings are actually used in the prefix,
             // and lint if they are not.
-            let let_source = let_source_parent(self.tcx, top, None);
             if !matches!(let_source, LetSource::WhileLet | LetSource::IfLetGuard) {
                 // Emit the lint
                 let prefix = &chain_refutabilities[..until];
@@ -358,9 +393,10 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
                 let span_end = prefix.last().unwrap().unwrap().0;
                 let span = span_start.to(span_end);
                 let count = prefix.len();
-                cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, LeadingIrrefutableLetPatterns { count });
+                self.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, self.lint_level, span, LeadingIrrefutableLetPatterns { count });
             }
         }
+
         if let Some(from) = chain_refutabilities.iter().rposition(|r| !matches!(*r, Some((_, false)))) && from != (chain_refutabilities.len() - 1) {
             // The chain has a non-empty suffix of irrefutable `let` statements
             let suffix = &chain_refutabilities[from + 1..];
@@ -368,18 +404,18 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             let span_end = suffix.last().unwrap().unwrap().0;
             let span = span_start.to(span_end);
             let count = suffix.len();
-            cx.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, top, span, TrailingIrrefutableLetPatterns { count });
+            self.tcx.emit_spanned_lint(IRREFUTABLE_LET_PATTERNS, self.lint_level, span, TrailingIrrefutableLetPatterns { count });
         }
-        true
     }
 
-    fn check_irrefutable(&self, pat: &'tcx Pat<'tcx>, origin: &str, sp: Option<Span>) {
-        let mut cx = self.new_cx(pat.hir_id);
+    #[instrument(level = "trace", skip(self))]
+    fn check_irrefutable(&self, pat: &Pat<'tcx>, origin: &str, sp: Option<Span>) {
+        let mut cx = self.new_cx(self.lint_level, false);
 
-        let pattern = self.lower_pattern(&mut cx, pat, &mut false);
+        let pattern = self.lower_pattern(&mut cx, pat);
         let pattern_ty = pattern.ty();
-        let arm = MatchArm { pat: pattern, hir_id: pat.hir_id, has_guard: false };
-        let report = compute_match_usefulness(&cx, &[arm], pat.hir_id, pattern_ty);
+        let arm = MatchArm { pat: pattern, hir_id: self.lint_level, has_guard: false };
+        let report = compute_match_usefulness(&cx, &[arm], self.lint_level, pattern_ty);
 
         // Note: we ignore whether the pattern is unreachable (i.e. whether the type is empty). We
         // only care about exhaustiveness here.
@@ -390,58 +426,45 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             return;
         }
 
-        let (inform, interpreted_as_const, res_defined_here,let_suggestion, misc_suggestion) =
-            if let hir::PatKind::Path(hir::QPath::Resolved(
-                None,
-                hir::Path {
-                    segments: &[hir::PathSegment { args: None, res, ident, .. }],
-                    ..
-                },
-            )) = &pat.kind
-            {
-                (
-                    None,
-                    Some(InterpretedAsConst {
-                        span: pat.span,
-                        article: res.article(),
-                        variable: ident.to_string().to_lowercase(),
-                        res,
-                    }),
-                    try {
-                        ResDefinedHere {
-                            def_span: cx.tcx.hir().res_span(res)?,
-                            res,
-                        }
-                    },
-                    None,
-                    None,
-                )
-            } else if let Some(span) = sp && self.tcx.sess.source_map().is_span_accessible(span) {
-                let mut bindings = vec![];
-                pat.walk_always(&mut |pat: &hir::Pat<'_>| {
-                    if let hir::PatKind::Binding(_, _, ident, _) = pat.kind {
-                        bindings.push(ident);
-                    }
+        let inform = sp.is_some().then_some(Inform);
+        let mut let_suggestion = None;
+        let mut misc_suggestion = None;
+        let mut interpreted_as_const = None;
+        if let PatKind::Constant { .. } = pat.kind
+            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(pat.span)
+        {
+            // If the pattern to match is an integer literal:
+            if snippet.chars().all(|c| c.is_digit(10)) {
+                // Then give a suggestion, the user might've meant to create a binding instead.
+                misc_suggestion = Some(MiscPatternSuggestion::AttemptedIntegerLiteral {
+                    start_span: pat.span.shrink_to_lo()
                 });
-                let semi_span = span.shrink_to_hi().with_lo(span.hi() - BytePos(1));
-                let start_span = span.shrink_to_lo();
-                let end_span = semi_span.shrink_to_lo();
-                let count = witnesses.len();
-
-                // If the pattern to match is an integer literal:
-                let int_suggestion = if
-                    let PatKind::Lit(expr) = &pat.kind
-                    && bindings.is_empty()
-                    && let ExprKind::Lit(Spanned { node: LitKind::Int(_, _), span }) = expr.kind {
-                    // Then give a suggestion, the user might've meant to create a binding instead.
-                    Some(MiscPatternSuggestion::AttemptedIntegerLiteral { start_span: span.shrink_to_lo() })
-                } else { None };
-
-                let let_suggestion = if bindings.is_empty() {SuggestLet::If{start_span, semi_span, count}} else{ SuggestLet::Else{end_span, count }};
-                (sp.map(|_|Inform), None, None, Some(let_suggestion), int_suggestion)
-            } else{
-                (sp.map(|_|Inform), None, None,  None, None)
-            };
+            } else if snippet.chars().all(|c| c.is_alphanumeric() || c == '_') {
+                interpreted_as_const = Some(InterpretedAsConst {
+                    span: pat.span,
+                    variable: snippet,
+                });
+            }
+        }
+
+        if let Some(span) = sp
+            && self.tcx.sess.source_map().is_span_accessible(span)
+            && interpreted_as_const.is_none()
+        {
+            let mut bindings = vec![];
+            pat.each_binding(|name, _, _, _| bindings.push(name));
+
+            let semi_span = span.shrink_to_hi();
+            let start_span = span.shrink_to_lo();
+            let end_span = semi_span.shrink_to_lo();
+            let count = witnesses.len();
+
+            let_suggestion = Some(if bindings.is_empty() {
+                SuggestLet::If { start_span, semi_span, count }
+            } else {
+                SuggestLet::Else { end_span, count }
+            });
+        };
 
         let adt_defined_here = try {
             let ty = pattern_ty.peel_refs();
@@ -465,7 +488,6 @@ impl<'p, 'tcx> MatchVisitor<'_, 'p, 'tcx> {
             pattern_ty,
             let_suggestion,
             misc_suggestion,
-            res_defined_here,
             adt_defined_here,
         });
     }
@@ -477,14 +499,18 @@ fn check_for_bindings_named_same_as_variants(
     rf: RefutableFlag,
 ) {
     pat.walk_always(|p| {
-        if let hir::PatKind::Binding(_, _, ident, None) = p.kind
-            && let Some(ty::BindByValue(hir::Mutability::Not)) =
-                cx.typeck_results.extract_binding_mode(cx.tcx.sess, p.hir_id, p.span)
-            && let pat_ty = cx.typeck_results.pat_ty(p).peel_refs()
-            && let ty::Adt(edef, _) = pat_ty.kind()
+        if let PatKind::Binding {
+                name,
+                mode: BindingMode::ByValue,
+                mutability: Mutability::Not,
+                subpattern: None,
+                ty,
+                ..
+            } = p.kind
+            && let ty::Adt(edef, _) = ty.peel_refs().kind()
             && edef.is_enum()
             && edef.variants().iter().any(|variant| {
-                variant.ident(cx.tcx) == ident && variant.ctor_kind() == Some(CtorKind::Const)
+                variant.name == name && variant.ctor_kind() == Some(CtorKind::Const)
             })
         {
             let variant_count = edef.variants().len();
@@ -493,7 +519,7 @@ fn check_for_bindings_named_same_as_variants(
             });
             cx.tcx.emit_spanned_lint(
                 BINDINGS_WITH_VARIANT_NAME,
-                p.hir_id,
+                cx.lint_level,
                 p.span,
                 BindingsWithVariantName {
                     // If this is an irrefutable pattern, and there's > 1 variant,
@@ -503,7 +529,7 @@ fn check_for_bindings_named_same_as_variants(
                         Some(p.span)
                     } else { None },
                     ty_path,
-                    ident,
+                    name,
                 },
             )
         }
@@ -529,11 +555,6 @@ fn unreachable_pattern(tcx: TyCtxt<'_>, span: Span, id: HirId, catchall: Option<
     );
 }
 
-fn irrefutable_let_pattern(tcx: TyCtxt<'_>, id: HirId, span: Span) {
-    let source = let_source(tcx, id);
-    irrefutable_let_patterns(tcx, id, source, 1, span);
-}
-
 fn irrefutable_let_patterns(
     tcx: TyCtxt<'_>,
     id: HirId,
@@ -548,7 +569,7 @@ fn irrefutable_let_patterns(
     }
 
     match source {
-        LetSource::GenericLet => emit_diag!(IrrefutableLetPatternsGenericLet),
+        LetSource::None => bug!(),
         LetSource::IfLet => emit_diag!(IrrefutableLetPatternsIfLet),
         LetSource::IfLetGuard => emit_diag!(IrrefutableLetPatternsIfLetGuard),
         LetSource::LetElse => emit_diag!(IrrefutableLetPatternsLetElse),
@@ -604,10 +625,11 @@ fn report_arm_reachability<'p, 'tcx>(
 /// Report that a match is not exhaustive.
 fn non_exhaustive_match<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
+    thir: &Thir<'tcx>,
     scrut_ty: Ty<'tcx>,
     sp: Span,
     witnesses: Vec<DeconstructedPat<'p, 'tcx>>,
-    arms: &[hir::Arm<'tcx>],
+    arms: &[ArmId],
     expr_span: Span,
 ) {
     let is_empty_match = arms.is_empty();
@@ -705,6 +727,7 @@ fn non_exhaustive_match<'p, 'tcx>(
             ));
         }
         [only] => {
+            let only = &thir[*only];
             let (pre_indentation, is_multiline) = if let Some(snippet) = sm.indentation_before(only.span)
                 && let Ok(with_trailing) = sm.span_extend_while(only.span, |c| c.is_whitespace() || c == ',')
                 && sm.is_multiline(with_trailing)
@@ -713,8 +736,9 @@ fn non_exhaustive_match<'p, 'tcx>(
             } else {
                 (" ".to_string(), false)
             };
-            let comma = if matches!(only.body.kind, hir::ExprKind::Block(..))
-                && only.span.eq_ctxt(only.body.span)
+            let only_body = &thir[only.body];
+            let comma = if matches!(only_body.kind, ExprKind::Block { .. })
+                && only.span.eq_ctxt(only_body.span)
                 && is_multiline
             {
                 ""
@@ -726,24 +750,29 @@ fn non_exhaustive_match<'p, 'tcx>(
                 format!("{}{}{} => todo!()", comma, pre_indentation, pattern),
             ));
         }
-        [.., prev, last] if prev.span.eq_ctxt(last.span) => {
-            let comma = if matches!(last.body.kind, hir::ExprKind::Block(..))
-                && last.span.eq_ctxt(last.body.span)
-            {
-                ""
-            } else {
-                ","
-            };
-            let spacing = if sm.is_multiline(prev.span.between(last.span)) {
-                sm.indentation_before(last.span).map(|indent| format!("\n{indent}"))
-            } else {
-                Some(" ".to_string())
-            };
-            if let Some(spacing) = spacing {
-                suggestion = Some((
-                    last.span.shrink_to_hi(),
-                    format!("{}{}{} => todo!()", comma, spacing, pattern),
-                ));
+        [.., prev, last] => {
+            let prev = &thir[*prev];
+            let last = &thir[*last];
+            if prev.span.eq_ctxt(last.span) {
+                let last_body = &thir[last.body];
+                let comma = if matches!(last_body.kind, ExprKind::Block { .. })
+                    && last.span.eq_ctxt(last_body.span)
+                {
+                    ""
+                } else {
+                    ","
+                };
+                let spacing = if sm.is_multiline(prev.span.between(last.span)) {
+                    sm.indentation_before(last.span).map(|indent| format!("\n{indent}"))
+                } else {
+                    Some(" ".to_string())
+                };
+                if let Some(spacing) = spacing {
+                    suggestion = Some((
+                        last.span.shrink_to_hi(),
+                        format!("{}{}{} => todo!()", comma, spacing, pattern),
+                    ));
+                }
             }
         }
         _ => {}
@@ -863,10 +892,6 @@ fn maybe_point_at_variant<'a, 'p: 'a, 'tcx: 'a>(
 }
 
 /// Check if a by-value binding is by-value. That is, check if the binding's type is not `Copy`.
-fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId) -> bool {
-    !cx.typeck_results.node_type(hir_id).is_copy_modulo_regions(cx.tcx, cx.param_env)
-}
-
 /// Check that there are no borrow or move conflicts in `binding @ subpat` patterns.
 ///
 /// For example, this would reject:
@@ -877,45 +902,36 @@ fn is_binding_by_move(cx: &MatchVisitor<'_, '_, '_>, hir_id: HirId) -> bool {
 /// - `x @ Some(ref mut? y)`.
 ///
 /// This analysis is *not* subsumed by NLL.
-fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pat<'_>) {
+fn check_borrow_conflicts_in_at_patterns<'tcx>(cx: &MatchVisitor<'_, '_, 'tcx>, pat: &Pat<'tcx>) {
     // Extract `sub` in `binding @ sub`.
-    let (name, sub) = match &pat.kind {
-        hir::PatKind::Binding(.., name, Some(sub)) => (*name, sub),
-        _ => return,
-    };
-    let binding_span = pat.span.with_hi(name.span.hi());
+    let PatKind::Binding { name, mode, ty, subpattern: Some(box ref sub), .. } = pat.kind else { return };
+
+    let is_binding_by_move = |ty: Ty<'tcx>| !ty.is_copy_modulo_regions(cx.tcx, cx.param_env);
 
-    let typeck_results = cx.typeck_results;
     let sess = cx.tcx.sess;
 
     // Get the binding move, extract the mutability if by-ref.
-    let mut_outer = match typeck_results.extract_binding_mode(sess, pat.hir_id, pat.span) {
-        Some(ty::BindByValue(_)) if is_binding_by_move(cx, pat.hir_id) => {
+    let mut_outer = match mode {
+        BindingMode::ByValue if is_binding_by_move(ty) => {
             // We have `x @ pat` where `x` is by-move. Reject all borrows in `pat`.
             let mut conflicts_ref = Vec::new();
-            sub.each_binding(|_, hir_id, span, _| {
-                match typeck_results.extract_binding_mode(sess, hir_id, span) {
-                    Some(ty::BindByValue(_)) | None => {}
-                    Some(ty::BindByReference(_)) => conflicts_ref.push(span),
-                }
+            sub.each_binding(|_, mode, _, span| match mode {
+                BindingMode::ByValue => {}
+                BindingMode::ByRef(_) => conflicts_ref.push(span),
             });
             if !conflicts_ref.is_empty() {
                 sess.emit_err(BorrowOfMovedValue {
-                    span: pat.span,
-                    binding_span,
+                    binding_span: pat.span,
                     conflicts_ref,
                     name,
-                    ty: typeck_results.node_type(pat.hir_id),
-                    suggest_borrowing: pat
-                        .span
-                        .contains(binding_span)
-                        .then(|| binding_span.shrink_to_lo()),
+                    ty,
+                    suggest_borrowing: Some(pat.span.shrink_to_lo()),
                 });
             }
             return;
         }
-        Some(ty::BindByValue(_)) | None => return,
-        Some(ty::BindByReference(m)) => m,
+        BindingMode::ByValue => return,
+        BindingMode::ByRef(m) => m.mutability(),
     };
 
     // We now have `ref $mut_outer binding @ sub` (semantically).
@@ -923,9 +939,9 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
     let mut conflicts_move = Vec::new();
     let mut conflicts_mut_mut = Vec::new();
     let mut conflicts_mut_ref = Vec::new();
-    sub.each_binding(|_, hir_id, span, name| {
-        match typeck_results.extract_binding_mode(sess, hir_id, span) {
-            Some(ty::BindByReference(mut_inner)) => match (mut_outer, mut_inner) {
+    sub.each_binding(|name, mode, ty, span| {
+        match mode {
+            BindingMode::ByRef(mut_inner) => match (mut_outer, mut_inner.mutability()) {
                 // Both sides are `ref`.
                 (Mutability::Not, Mutability::Not) => {}
                 // 2x `ref mut`.
@@ -939,10 +955,10 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
                     conflicts_mut_ref.push(Conflict::Ref { span, name })
                 }
             },
-            Some(ty::BindByValue(_)) if is_binding_by_move(cx, hir_id) => {
+            BindingMode::ByValue if is_binding_by_move(ty) => {
                 conflicts_move.push(Conflict::Moved { span, name }) // `ref mut?` + by-move conflict.
             }
-            Some(ty::BindByValue(_)) | None => {} // `ref mut?` + by-copy is fine.
+            BindingMode::ByValue => {} // `ref mut?` + by-copy is fine.
         }
     });
 
@@ -951,8 +967,8 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
     let report_move_conflict = !conflicts_move.is_empty();
 
     let mut occurences = match mut_outer {
-        Mutability::Mut => vec![Conflict::Mut { span: binding_span, name }],
-        Mutability::Not => vec![Conflict::Ref { span: binding_span, name }],
+        Mutability::Mut => vec![Conflict::Mut { span: pat.span, name }],
+        Mutability::Not => vec![Conflict::Ref { span: pat.span, name }],
     };
     occurences.extend(conflicts_mut_mut);
     occurences.extend(conflicts_mut_ref);
@@ -977,65 +993,3 @@ fn check_borrow_conflicts_in_at_patterns(cx: &MatchVisitor<'_, '_, '_>, pat: &Pa
         sess.emit_err(MovedWhileBorrowed { span: pat.span, occurences });
     }
 }
-
-#[derive(Clone, Copy, Debug)]
-pub enum LetSource {
-    GenericLet,
-    IfLet,
-    IfLetGuard,
-    LetElse,
-    WhileLet,
-}
-
-fn let_source(tcx: TyCtxt<'_>, pat_id: HirId) -> LetSource {
-    let hir = tcx.hir();
-
-    let parent = hir.parent_id(pat_id);
-    let_source_parent(tcx, parent, Some(pat_id))
-}
-
-fn let_source_parent(tcx: TyCtxt<'_>, parent: HirId, pat_id: Option<HirId>) -> LetSource {
-    let hir = tcx.hir();
-
-    let parent_node = hir.get(parent);
-
-    match parent_node {
-        hir::Node::Arm(hir::Arm {
-            guard: Some(hir::Guard::IfLet(&hir::Let { pat: hir::Pat { hir_id, .. }, .. })),
-            ..
-        }) if Some(*hir_id) == pat_id => {
-            return LetSource::IfLetGuard;
-        }
-        _ => {}
-    }
-
-    let parent_parent = hir.parent_id(parent);
-    let parent_parent_node = hir.get(parent_parent);
-    match parent_parent_node {
-        hir::Node::Stmt(hir::Stmt { kind: hir::StmtKind::Local(_), .. }) => {
-            return LetSource::LetElse;
-        }
-        hir::Node::Arm(hir::Arm { guard: Some(hir::Guard::If(_)), .. }) => {
-            return LetSource::IfLetGuard;
-        }
-        _ => {}
-    }
-
-    let parent_parent_parent = hir.parent_id(parent_parent);
-    let parent_parent_parent_parent = hir.parent_id(parent_parent_parent);
-    let parent_parent_parent_parent_node = hir.get(parent_parent_parent_parent);
-
-    if let hir::Node::Expr(hir::Expr {
-        kind: hir::ExprKind::Loop(_, _, hir::LoopSource::While, _),
-        ..
-    }) = parent_parent_parent_parent_node
-    {
-        return LetSource::WhileLet;
-    }
-
-    if let hir::Node::Expr(hir::Expr { kind: hir::ExprKind::If(..), .. }) = parent_parent_node {
-        return LetSource::IfLet;
-    }
-
-    LetSource::GenericLet
-}
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 2dbef740d1a..32d0404bd07 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
@@ -59,8 +59,6 @@ struct ConstToPat<'tcx> {
     // inference context used for checking `T: Structural` bounds.
     infcx: InferCtxt<'tcx>,
 
-    include_lint_checks: bool,
-
     treat_byte_string_as_slice: bool,
 }
 
@@ -93,7 +91,6 @@ impl<'tcx> ConstToPat<'tcx> {
             span,
             infcx,
             param_env: pat_ctxt.param_env,
-            include_lint_checks: pat_ctxt.include_lint_checks,
             saw_const_match_error: Cell::new(false),
             saw_const_match_lint: Cell::new(false),
             behind_reference: Cell::new(false),
@@ -134,7 +131,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 })
             });
 
-        if self.include_lint_checks && !self.saw_const_match_error.get() {
+        if !self.saw_const_match_error.get() {
             // If we were able to successfully convert the const to some pat,
             // double-check that all types in the const implement `Structural`.
 
@@ -239,21 +236,19 @@ impl<'tcx> ConstToPat<'tcx> {
 
         let kind = match cv.ty().kind() {
             ty::Float(_) => {
-                if self.include_lint_checks {
                     tcx.emit_spanned_lint(
                         lint::builtin::ILLEGAL_FLOATING_POINT_LITERAL_PATTERN,
                         id,
                         span,
                         FloatPattern,
                     );
-                }
                 PatKind::Constant { value: cv }
             }
             ty::Adt(adt_def, _) if adt_def.is_union() => {
                 // Matching on union fields is unsafe, we can't hide it in constants
                 self.saw_const_match_error.set(true);
                 let err = UnionPattern { span };
-                tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
+                tcx.sess.emit_err(err);
                 PatKind::Wild
             }
             ty::Adt(..)
@@ -267,7 +262,7 @@ impl<'tcx> ConstToPat<'tcx> {
             {
                 self.saw_const_match_error.set(true);
                 let err = TypeNotStructural { span, non_sm_ty };
-                tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
+                tcx.sess.emit_err(err);
                 PatKind::Wild
             }
             // If the type is not structurally comparable, just emit the constant directly,
@@ -280,8 +275,7 @@ impl<'tcx> ConstToPat<'tcx> {
             // Backwards compatibility hack because we can't cause hard errors on these
             // types, so we compare them via `PartialEq::eq` at runtime.
             ty::Adt(..) if !self.type_marked_structural(cv.ty()) && self.behind_reference.get() => {
-                if self.include_lint_checks
-                    && !self.saw_const_match_error.get()
+                if !self.saw_const_match_error.get()
                     && !self.saw_const_match_lint.get()
                 {
                     self.saw_const_match_lint.set(true);
@@ -305,7 +299,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 );
                 self.saw_const_match_error.set(true);
                 let err = TypeNotStructural { span, non_sm_ty: cv.ty() };
-                tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
+                tcx.sess.emit_err(err);
                 PatKind::Wild
             }
             ty::Adt(adt_def, substs) if adt_def.is_enum() => {
@@ -339,7 +333,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 ty::Dynamic(..) => {
                     self.saw_const_match_error.set(true);
                     let err = InvalidPattern { span, non_sm_ty: cv.ty() };
-                    tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
+                    tcx.sess.emit_err(err);
                     PatKind::Wild
                 }
                 // `&str` is represented as `ConstValue::Slice`, let's keep using this
@@ -406,8 +400,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 // to figure out how to get a reference again.
                 ty::Adt(_, _) if !self.type_marked_structural(*pointee_ty) => {
                     if self.behind_reference.get() {
-                        if self.include_lint_checks
-                            && !self.saw_const_match_error.get()
+                        if !self.saw_const_match_error.get()
                             && !self.saw_const_match_lint.get()
                         {
                            self.saw_const_match_lint.set(true);
@@ -423,7 +416,7 @@ impl<'tcx> ConstToPat<'tcx> {
                         if !self.saw_const_match_error.get() {
                             self.saw_const_match_error.set(true);
                             let err = TypeNotStructural { span, non_sm_ty: *pointee_ty };
-                            tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
+                            tcx.sess.emit_err(err);
                         }
                         PatKind::Wild
                     }
@@ -437,7 +430,7 @@ impl<'tcx> ConstToPat<'tcx> {
                         // (except slices, which are handled in a separate arm above).
 
                         let err = UnsizedPattern { span, non_sm_ty: *pointee_ty };
-                        tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
+                        tcx.sess.emit_err(err);
 
                         PatKind::Wild
                     } else {
@@ -465,8 +458,7 @@ impl<'tcx> ConstToPat<'tcx> {
             // compilation choices change the runtime behaviour of the match.
             // See https://github.com/rust-lang/rust/issues/70861 for examples.
             ty::FnPtr(..) | ty::RawPtr(..) => {
-                if self.include_lint_checks
-                    && !self.saw_const_match_error.get()
+                if !self.saw_const_match_error.get()
                     && !self.saw_const_match_lint.get()
                 {
                     self.saw_const_match_lint.set(true);
@@ -482,13 +474,12 @@ impl<'tcx> ConstToPat<'tcx> {
             _ => {
                 self.saw_const_match_error.set(true);
                 let err = InvalidPattern { span, non_sm_ty: cv.ty() };
-                    tcx.sess.create_err(err).emit_unless(!self.include_lint_checks);
+                    tcx.sess.emit_err(err);
                 PatKind::Wild
             }
         };
 
-        if self.include_lint_checks
-            && !self.saw_const_match_error.get()
+        if !self.saw_const_match_error.get()
             && !self.saw_const_match_lint.get()
             && mir_structural_match_violation
             // FIXME(#73448): Find a way to bring const qualification into parity with
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 29f7cae3d3f..7c29196447c 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/deconstruct_pat.rs
@@ -258,7 +258,7 @@ impl IntRange {
         pcx: &PatCtxt<'_, 'p, 'tcx>,
         pats: impl Iterator<Item = &'a DeconstructedPat<'p, 'tcx>>,
         column_count: usize,
-        hir_id: HirId,
+        lint_root: HirId,
     ) {
         if self.is_singleton() {
             return;
@@ -290,7 +290,7 @@ impl IntRange {
         if !overlap.is_empty() {
             pcx.cx.tcx.emit_spanned_lint(
                 lint::builtin::OVERLAPPING_RANGE_ENDPOINTS,
-                hir_id,
+                lint_root,
                 pcx.span,
                 OverlappingRangeEndpoints { overlap, range: pcx.span },
             );
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 9ac92f6e0a6..70d015a39e4 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -31,20 +31,10 @@ use rustc_target::abi::FieldIdx;
 
 use std::cmp::Ordering;
 
-#[derive(Clone, Debug)]
-enum PatternError {
-    AssocConstInPattern(Span),
-    ConstParamInPattern(Span),
-    StaticInPattern(Span),
-    NonConstPath(Span),
-}
-
 struct PatCtxt<'a, 'tcx> {
     tcx: TyCtxt<'tcx>,
     param_env: ty::ParamEnv<'tcx>,
     typeck_results: &'a ty::TypeckResults<'tcx>,
-    errors: Vec<PatternError>,
-    include_lint_checks: bool,
 }
 
 pub(super) fn pat_from_hir<'a, 'tcx>(
@@ -53,30 +43,13 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
     typeck_results: &'a ty::TypeckResults<'tcx>,
     pat: &'tcx hir::Pat<'tcx>,
 ) -> Box<Pat<'tcx>> {
-    let mut pcx = PatCtxt::new(tcx, param_env, typeck_results);
+    let mut pcx = PatCtxt { tcx, param_env, typeck_results };
     let result = pcx.lower_pattern(pat);
-    if !pcx.errors.is_empty() {
-        let msg = format!("encountered errors lowering pattern: {:?}", pcx.errors);
-        tcx.sess.delay_span_bug(pat.span, &msg);
-    }
     debug!("pat_from_hir({:?}) = {:?}", pat, result);
     result
 }
 
 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
-    fn new(
-        tcx: TyCtxt<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        typeck_results: &'a ty::TypeckResults<'tcx>,
-    ) -> Self {
-        PatCtxt { tcx, param_env, typeck_results, errors: vec![], include_lint_checks: false }
-    }
-
-    fn include_lint_checks(&mut self) -> &mut Self {
-        self.include_lint_checks = true;
-        self
-    }
-
     fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
         // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
         // pattern has the type that results *after* dereferencing. For example, in this code:
@@ -473,12 +446,15 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             | Res::SelfTyAlias { .. }
             | Res::SelfCtor(..) => PatKind::Leaf { subpatterns },
             _ => {
-                let pattern_error = match res {
-                    Res::Def(DefKind::ConstParam, _) => PatternError::ConstParamInPattern(span),
-                    Res::Def(DefKind::Static(_), _) => PatternError::StaticInPattern(span),
-                    _ => PatternError::NonConstPath(span),
+                match res {
+                    Res::Def(DefKind::ConstParam, _) => {
+                        self.tcx.sess.emit_err(ConstParamInPattern { span })
+                    }
+                    Res::Def(DefKind::Static(_), _) => {
+                        self.tcx.sess.emit_err(StaticInPattern { span })
+                    }
+                    _ => self.tcx.sess.emit_err(NonConstPath { span }),
                 };
-                self.errors.push(pattern_error);
                 PatKind::Wild
             }
         };
@@ -531,7 +507,7 @@ 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.errors.push(PatternError::AssocConstInPattern(span));
+                self.tcx.sess.emit_err(AssocConstInPattern { span });
 
                 return pat_from_kind(PatKind::Wild);
             }
@@ -609,7 +585,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         match value {
             mir::ConstantKind::Ty(c) => match c.kind() {
                 ConstKind::Param(_) => {
-                    self.errors.push(PatternError::ConstParamInPattern(span));
+                    self.tcx.sess.emit_err(ConstParamInPattern { span });
                     return PatKind::Wild;
                 }
                 ConstKind::Error(_) => {
diff --git a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
index a324c3a6228..d8f66a1755b 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/usefulness.rs
@@ -300,7 +300,6 @@ use rustc_arena::TypedArena;
 use rustc_data_structures::stack::ensure_sufficient_stack;
 use rustc_hir::def_id::DefId;
 use rustc_hir::HirId;
-use rustc_hir::Node;
 use rustc_middle::ty::{self, Ty, TyCtxt};
 use rustc_session::lint::builtin::NON_EXHAUSTIVE_OMITTED_PATTERNS;
 use rustc_span::{Span, DUMMY_SP};
@@ -319,6 +318,8 @@ pub(crate) struct MatchCheckCtxt<'p, 'tcx> {
     pub(crate) module: DefId,
     pub(crate) param_env: ty::ParamEnv<'tcx>,
     pub(crate) pattern_arena: &'p TypedArena<DeconstructedPat<'p, 'tcx>>,
+    /// Only produce `NON_EXHAUSTIVE_OMITTED_PATTERNS` lint on refutable patterns.
+    pub(crate) refutable: bool,
 }
 
 impl<'a, 'tcx> MatchCheckCtxt<'a, 'tcx> {
@@ -765,13 +766,13 @@ impl<'p, 'tcx> Witness<'p, 'tcx> {
 /// `is_under_guard` is used to inform if the pattern has a guard. If it
 /// has one it must not be inserted into the matrix. This shouldn't be
 /// relied on for soundness.
-#[instrument(level = "debug", skip(cx, matrix, hir_id), ret)]
+#[instrument(level = "debug", skip(cx, matrix, lint_root), ret)]
 fn is_useful<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     matrix: &Matrix<'p, 'tcx>,
     v: &PatStack<'p, 'tcx>,
     witness_preference: ArmType,
-    hir_id: HirId,
+    lint_root: HirId,
     is_under_guard: bool,
     is_top_level: bool,
 ) -> Usefulness<'p, 'tcx> {
@@ -804,7 +805,7 @@ fn is_useful<'p, 'tcx>(
         for v in v.expand_or_pat() {
             debug!(?v);
             let usefulness = ensure_sufficient_stack(|| {
-                is_useful(cx, &matrix, &v, witness_preference, hir_id, is_under_guard, false)
+                is_useful(cx, &matrix, &v, witness_preference, lint_root, is_under_guard, false)
             });
             debug!(?usefulness);
             ret.extend(usefulness);
@@ -837,7 +838,7 @@ fn is_useful<'p, 'tcx>(
                 pcx,
                 matrix.heads(),
                 matrix.column_count().unwrap_or(0),
-                hir_id,
+                lint_root,
             )
         }
         // We split the head constructor of `v`.
@@ -852,7 +853,15 @@ fn is_useful<'p, 'tcx>(
             let spec_matrix = start_matrix.specialize_constructor(pcx, &ctor);
             let v = v.pop_head_constructor(pcx, &ctor);
             let usefulness = ensure_sufficient_stack(|| {
-                is_useful(cx, &spec_matrix, &v, witness_preference, hir_id, is_under_guard, false)
+                is_useful(
+                    cx,
+                    &spec_matrix,
+                    &v,
+                    witness_preference,
+                    lint_root,
+                    is_under_guard,
+                    false,
+                )
             });
             let usefulness = usefulness.apply_constructor(pcx, start_matrix, &ctor);
 
@@ -860,6 +869,8 @@ fn is_useful<'p, 'tcx>(
             // that has the potential to trigger the `non_exhaustive_omitted_patterns` lint.
             // To understand the workings checkout `Constructor::split` and `SplitWildcard::new/into_ctors`
             if is_non_exhaustive_and_wild
+                // Only emit a lint on refutable patterns.
+                && cx.refutable
                 // We check that the match has a wildcard pattern and that wildcard is useful,
                 // meaning there are variants that are covered by the wildcard. Without the check
                 // for `witness_preference` the lint would trigger on `if let NonExhaustiveEnum::A = foo {}`
@@ -868,8 +879,6 @@ fn is_useful<'p, 'tcx>(
                     &ctor,
                     Constructor::Missing { nonexhaustive_enum_missing_real_variants: true }
                 )
-                // We don't want to lint patterns which are function arguments or locals
-                && !matches!(cx.tcx.hir().find_parent(hir_id), Some(Node::Param(_)|Node::Local(_)))
             {
                 let patterns = {
                     let mut split_wildcard = SplitWildcard::new(pcx);
@@ -896,7 +905,7 @@ fn is_useful<'p, 'tcx>(
                 // NB: The partner lint for structs lives in `compiler/rustc_hir_analysis/src/check/pat.rs`.
                 cx.tcx.emit_spanned_lint(
                     NON_EXHAUSTIVE_OMITTED_PATTERNS,
-                    hir_id,
+                    lint_root,
                     pcx.span,
                     NonExhaustiveOmittedPattern {
                         scrut_ty: pcx.ty,
@@ -954,7 +963,7 @@ pub(crate) struct UsefulnessReport<'p, 'tcx> {
 pub(crate) fn compute_match_usefulness<'p, 'tcx>(
     cx: &MatchCheckCtxt<'p, 'tcx>,
     arms: &[MatchArm<'p, 'tcx>],
-    scrut_hir_id: HirId,
+    lint_root: HirId,
     scrut_ty: Ty<'tcx>,
 ) -> UsefulnessReport<'p, 'tcx> {
     let mut matrix = Matrix::empty();
@@ -979,7 +988,7 @@ pub(crate) fn compute_match_usefulness<'p, 'tcx>(
 
     let wild_pattern = cx.pattern_arena.alloc(DeconstructedPat::wildcard(scrut_ty, DUMMY_SP));
     let v = PatStack::from_pattern(wild_pattern);
-    let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, scrut_hir_id, false, true);
+    let usefulness = is_useful(cx, &matrix, &v, FakeExtraWildcard, lint_root, false, true);
     let non_exhaustiveness_witnesses = match usefulness {
         WithWitnesses(pats) => pats.into_iter().map(|w| w.single_pattern()).collect(),
         NoWitnesses { .. } => bug!(),
diff --git a/compiler/rustc_mir_build/src/thir/print.rs b/compiler/rustc_mir_build/src/thir/print.rs
index 8028227aafd..ed61d6ee78b 100644
--- a/compiler/rustc_mir_build/src/thir/print.rs
+++ b/compiler/rustc_mir_build/src/thir/print.rs
@@ -151,6 +151,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 initializer,
                 else_block,
                 lint_level,
+                span,
             } => {
                 print_indented!(self, "kind: Let {", depth_lvl + 1);
                 print_indented!(
@@ -181,6 +182,7 @@ impl<'a, 'tcx> ThirPrinter<'a, 'tcx> {
                 }
 
                 print_indented!(self, format!("lint_level: {:?}", lint_level), depth_lvl + 2);
+                print_indented!(self, format!("span: {:?}", span), depth_lvl + 2);
                 print_indented!(self, "}", depth_lvl + 1);
             }
         }
diff --git a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
index 41657b53fc1..19daae86589 100644
--- a/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
+++ b/tests/mir-opt/const_promotion_extern_static.FOO-promoted[0].SimplifyCfg-elaborate-drops.after.mir
@@ -7,10 +7,10 @@ promoted[0] in FOO: &[&i32; 1] = {
     let mut _3: *const i32;              // in scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
 
     bb0: {
-        _3 = const {alloc3: *const i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
+        _3 = const {alloc2: *const i32}; // scope 0 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
                                          // mir::Constant
                                          // + span: $DIR/const_promotion_extern_static.rs:13:42: 13:43
-                                         // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) }
+                                         // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) }
         _2 = &(*_3);                     // scope 0 at $DIR/const_promotion_extern_static.rs:+0:41: +0:43
         _1 = [move _2];                  // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46
         _0 = &_1;                        // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55
@@ -18,4 +18,4 @@ promoted[0] in FOO: &[&i32; 1] = {
     }
 }
 
-alloc3 (extern static: X)
+alloc2 (extern static: X)
diff --git a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
index 25ba0face6b..5b13d60052f 100644
--- a/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
+++ b/tests/mir-opt/const_promotion_extern_static.FOO.PromoteTemps.diff
@@ -18,11 +18,11 @@
 -         StorageLive(_3);                 // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46
 -         StorageLive(_4);                 // scope 0 at $DIR/const_promotion_extern_static.rs:+0:32: +0:45
 -         StorageLive(_5);                 // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
--         _5 = const {alloc3: *const i32}; // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
+-         _5 = const {alloc2: *const i32}; // scope 1 at $DIR/const_promotion_extern_static.rs:+0:42: +0:43
 +         _6 = const _;                    // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55
                                            // mir::Constant
 -                                          // + span: $DIR/const_promotion_extern_static.rs:13:42: 13:43
--                                          // + literal: Const { ty: *const i32, val: Value(Scalar(alloc3)) }
+-                                          // + literal: Const { ty: *const i32, val: Value(Scalar(alloc2)) }
 -         _4 = &(*_5);                     // scope 1 at $DIR/const_promotion_extern_static.rs:+0:41: +0:43
 -         _3 = [move _4];                  // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:46
 -         _2 = &_3;                        // scope 0 at $DIR/const_promotion_extern_static.rs:+0:31: +0:55
@@ -50,5 +50,5 @@
       }
   }
 - 
-- alloc3 (extern static: X)
+- alloc2 (extern static: X)
   
diff --git a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
index 5835f06753b..0ca14c3f3bc 100644
--- a/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
+++ b/tests/ui/borrowck/bindings-after-at-or-patterns-slice-patterns-box-patterns.stderr
@@ -2,18 +2,16 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:36:9
    |
 LL |         ref foo @ [.., ref mut bar] => (),
-   |         -------^^^^^^^^-----------^
-   |         |              |
-   |         |              value is mutably borrowed by `bar` here
+   |         ^^^^^^^        ----------- value is mutably borrowed by `bar` here
+   |         |
    |         value is borrowed by `foo` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/bindings-after-at-or-patterns-slice-patterns-box-patterns.rs:120:9
    |
 LL |         ref foo @ Some(box ref mut s) => (),
-   |         -------^^^^^^^^^^^^---------^
-   |         |                  |
-   |         |                  value is mutably borrowed by `s` here
+   |         ^^^^^^^            --------- value is mutably borrowed by `s` here
+   |         |
    |         value is borrowed by `foo` here
 
 error[E0382]: borrow of moved value: `x`
diff --git a/tests/ui/chalkify/bugs/async.stderr b/tests/ui/chalkify/bugs/async.stderr
index 9c559640b23..36606fd49f2 100644
--- a/tests/ui/chalkify/bugs/async.stderr
+++ b/tests/ui/chalkify/bugs/async.stderr
@@ -14,14 +14,15 @@ LL | async fn foo(x: u32) -> u32 {
    |                         ^^^query stack during panic:
 #0 [typeck] type-checking `foo`
 #1 [thir_body] building THIR for `foo`
-#2 [mir_built] building MIR for `foo`
-#3 [unsafety_check_result] unsafety-checking `foo`
-#4 [mir_const] preparing `foo` for borrow checking
-#5 [mir_promoted] processing MIR for `foo`
-#6 [mir_borrowck] borrow-checking `foo`
-#7 [type_of] computing type of `foo::{opaque#0}`
-#8 [check_mod_item_types] checking item types in top-level module
-#9 [analysis] running analysis passes on this crate
+#2 [check_match] match-checking `foo`
+#3 [mir_built] building MIR for `foo`
+#4 [unsafety_check_result] unsafety-checking `foo`
+#5 [mir_const] preparing `foo` for borrow checking
+#6 [mir_promoted] processing MIR for `foo`
+#7 [mir_borrowck] borrow-checking `foo`
+#8 [type_of] computing type of `foo::{opaque#0}`
+#9 [check_mod_item_types] checking item types in top-level module
+#10 [analysis] running analysis passes on this crate
 end of query stack
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.rs b/tests/ui/consts/const-eval/const-eval-overflow-2.rs
index 535d9135916..c19a0c443ec 100644
--- a/tests/ui/consts/const-eval/const-eval-overflow-2.rs
+++ b/tests/ui/consts/const-eval/const-eval-overflow-2.rs
@@ -14,7 +14,6 @@ fn main() {
     match -128i8 {
         NEG_NEG_128 => println!("A"),
         //~^ ERROR could not evaluate constant pattern
-        //~| ERROR could not evaluate constant pattern
         _ => println!("B"),
     }
 }
diff --git a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr
index 7b1fe49d434..fc0baf11051 100644
--- a/tests/ui/consts/const-eval/const-eval-overflow-2.stderr
+++ b/tests/ui/consts/const-eval/const-eval-overflow-2.stderr
@@ -10,12 +10,6 @@ error: could not evaluate constant pattern
 LL |         NEG_NEG_128 => println!("A"),
    |         ^^^^^^^^^^^
 
-error: could not evaluate constant pattern
-  --> $DIR/const-eval-overflow-2.rs:15:9
-   |
-LL |         NEG_NEG_128 => println!("A"),
-   |         ^^^^^^^^^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr
index 032ceb2467c..eaa2d6b2794 100644
--- a/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr
+++ b/tests/ui/consts/const-eval/ref_to_int_match.32bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ref_to_int_match.rs:25:27
+  --> $DIR/ref_to_int_match.rs:24:27
    |
 LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
    |                           ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -13,12 +13,6 @@ error: could not evaluate constant pattern
 LL |         10..=BAR => {},
    |              ^^^
 
-error: could not evaluate constant pattern
-  --> $DIR/ref_to_int_match.rs:7:14
-   |
-LL |         10..=BAR => {},
-   |              ^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr
index 032ceb2467c..eaa2d6b2794 100644
--- a/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr
+++ b/tests/ui/consts/const-eval/ref_to_int_match.64bit.stderr
@@ -1,5 +1,5 @@
 error[E0080]: evaluation of constant value failed
-  --> $DIR/ref_to_int_match.rs:25:27
+  --> $DIR/ref_to_int_match.rs:24:27
    |
 LL | const BAR: Int = unsafe { Foo { r: &42 }.f };
    |                           ^^^^^^^^^^^^^^^^ unable to turn pointer into raw bytes
@@ -13,12 +13,6 @@ error: could not evaluate constant pattern
 LL |         10..=BAR => {},
    |              ^^^
 
-error: could not evaluate constant pattern
-  --> $DIR/ref_to_int_match.rs:7:14
-   |
-LL |         10..=BAR => {},
-   |              ^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/const-eval/ref_to_int_match.rs b/tests/ui/consts/const-eval/ref_to_int_match.rs
index 70c6e7d94ae..a2dabde25bc 100644
--- a/tests/ui/consts/const-eval/ref_to_int_match.rs
+++ b/tests/ui/consts/const-eval/ref_to_int_match.rs
@@ -5,7 +5,6 @@ fn main() {
     match n {
         0..=10 => {},
         10..=BAR => {}, //~ ERROR could not evaluate constant pattern
-                        //~| ERROR could not evaluate constant pattern
         _ => {},
     }
 }
diff --git a/tests/ui/consts/const-match-check.eval1.stderr b/tests/ui/consts/const-match-check.eval1.stderr
index 08fcd1deab1..27ff5d4cd5c 100644
--- a/tests/ui/consts/const-match-check.eval1.stderr
+++ b/tests/ui/consts/const-match-check.eval1.stderr
@@ -9,8 +9,8 @@ LL |     A = { let 0 = 0; 0 },
    = note: the matched value is of type `i32`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     A = { if let 0 = 0 { todo!() } 0 },
-   |           ++           ~~~~~~~~~~~
+LL |     A = { if let 0 = 0 { todo!() }; 0 },
+   |           ++           +++++++++++
 help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
    |
 LL |     A = { let _0 = 0; 0 },
diff --git a/tests/ui/consts/const-match-check.eval2.stderr b/tests/ui/consts/const-match-check.eval2.stderr
index 5d86ca4bfd1..0c74a7b3dd4 100644
--- a/tests/ui/consts/const-match-check.eval2.stderr
+++ b/tests/ui/consts/const-match-check.eval2.stderr
@@ -9,8 +9,8 @@ LL |     let x: [i32; { let 0 = 0; 0 }] = [];
    = note: the matched value is of type `i32`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     let x: [i32; { if let 0 = 0 { todo!() } 0 }] = [];
-   |                    ++           ~~~~~~~~~~~
+LL |     let x: [i32; { if let 0 = 0 { todo!() }; 0 }] = [];
+   |                    ++           +++++++++++
 help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
    |
 LL |     let x: [i32; { let _0 = 0; 0 }] = [];
diff --git a/tests/ui/consts/const-match-check.matchck.stderr b/tests/ui/consts/const-match-check.matchck.stderr
index c8f66bb0fc0..bcca4c2a647 100644
--- a/tests/ui/consts/const-match-check.matchck.stderr
+++ b/tests/ui/consts/const-match-check.matchck.stderr
@@ -9,8 +9,8 @@ LL | const X: i32 = { let 0 = 0; 0 };
    = note: the matched value is of type `i32`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL | const X: i32 = { if let 0 = 0 { todo!() } 0 };
-   |                  ++           ~~~~~~~~~~~
+LL | const X: i32 = { if let 0 = 0 { todo!() }; 0 };
+   |                  ++           +++++++++++
 help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
    |
 LL | const X: i32 = { let _0 = 0; 0 };
@@ -27,8 +27,8 @@ LL | static Y: i32 = { let 0 = 0; 0 };
    = note: the matched value is of type `i32`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL | static Y: i32 = { if let 0 = 0 { todo!() } 0 };
-   |                   ++           ~~~~~~~~~~~
+LL | static Y: i32 = { if let 0 = 0 { todo!() }; 0 };
+   |                   ++           +++++++++++
 help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
    |
 LL | static Y: i32 = { let _0 = 0; 0 };
@@ -45,8 +45,8 @@ LL |     const X: i32 = { let 0 = 0; 0 };
    = note: the matched value is of type `i32`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     const X: i32 = { if let 0 = 0 { todo!() } 0 };
-   |                      ++           ~~~~~~~~~~~
+LL |     const X: i32 = { if let 0 = 0 { todo!() }; 0 };
+   |                      ++           +++++++++++
 help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
    |
 LL |     const X: i32 = { let _0 = 0; 0 };
@@ -63,8 +63,8 @@ LL |     const X: i32 = { let 0 = 0; 0 };
    = note: the matched value is of type `i32`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     const X: i32 = { if let 0 = 0 { todo!() } 0 };
-   |                      ++           ~~~~~~~~~~~
+LL |     const X: i32 = { if let 0 = 0 { todo!() }; 0 };
+   |                      ++           +++++++++++
 help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
    |
 LL |     const X: i32 = { let _0 = 0; 0 };
diff --git a/tests/ui/consts/const-pattern-irrefutable.stderr b/tests/ui/consts/const-pattern-irrefutable.stderr
index c156ea1610c..2aed68bdd64 100644
--- a/tests/ui/consts/const-pattern-irrefutable.stderr
+++ b/tests/ui/consts/const-pattern-irrefutable.stderr
@@ -1,9 +1,6 @@
 error[E0005]: refutable pattern in local binding
   --> $DIR/const-pattern-irrefutable.rs:12:9
    |
-LL | const a: u8 = 2;
-   | ----------- constant defined here
-...
 LL |     let a = 4;
    |         ^
    |         |
@@ -11,14 +8,13 @@ LL |     let a = 4;
    |         missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
    |         help: introduce a variable instead: `a_var`
    |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `u8`
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/const-pattern-irrefutable.rs:17:9
    |
-LL |     pub const b: u8 = 2;
-   |     --------------- constant defined here
-...
 LL |     let c = 4;
    |         ^
    |         |
@@ -26,14 +22,13 @@ LL |     let c = 4;
    |         missing patterns are not covered because `c` is interpreted as a constant pattern, not a new variable
    |         help: introduce a variable instead: `c_var`
    |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `u8`
 
 error[E0005]: refutable pattern in local binding
   --> $DIR/const-pattern-irrefutable.rs:22:9
    |
-LL |     pub const d: u8 = 2;
-   |     --------------- constant defined here
-...
 LL |     let d = 4;
    |         ^
    |         |
@@ -41,6 +36,8 @@ LL |     let d = 4;
    |         missing patterns are not covered because `d` is interpreted as a constant pattern, not a new variable
    |         help: introduce a variable instead: `d_var`
    |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `u8`
 
 error: aborting due to 3 previous errors
diff --git a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr
index b005f3220e9..be144a87b8b 100644
--- a/tests/ui/consts/const_in_pattern/incomplete-slice.stderr
+++ b/tests/ui/consts/const_in_pattern/incomplete-slice.stderr
@@ -19,7 +19,7 @@ LL |     match &[][..] {
    = note: the matched value is of type `&[E]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         E_SL => {}
+LL ~         E_SL => {},
 LL +         &_ => todo!()
    |
 
diff --git a/tests/ui/consts/issue-43105.rs b/tests/ui/consts/issue-43105.rs
index cac12b90970..20b78d64209 100644
--- a/tests/ui/consts/issue-43105.rs
+++ b/tests/ui/consts/issue-43105.rs
@@ -7,7 +7,6 @@ fn main() {
     match 1 {
         NUM => unimplemented!(),
         //~^ ERROR could not evaluate constant pattern
-        //~| ERROR could not evaluate constant pattern
         _ => unimplemented!(),
     }
 }
diff --git a/tests/ui/consts/issue-43105.stderr b/tests/ui/consts/issue-43105.stderr
index 2d1174af71c..856a8f0dab6 100644
--- a/tests/ui/consts/issue-43105.stderr
+++ b/tests/ui/consts/issue-43105.stderr
@@ -12,12 +12,6 @@ error: could not evaluate constant pattern
 LL |         NUM => unimplemented!(),
    |         ^^^
 
-error: could not evaluate constant pattern
-  --> $DIR/issue-43105.rs:8:9
-   |
-LL |         NUM => unimplemented!(),
-   |         ^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0015`.
diff --git a/tests/ui/consts/issue-73976-polymorphic.rs b/tests/ui/consts/issue-73976-polymorphic.rs
index 787462da9f9..2c576d1f9ef 100644
--- a/tests/ui/consts/issue-73976-polymorphic.rs
+++ b/tests/ui/consts/issue-73976-polymorphic.rs
@@ -19,7 +19,6 @@ impl<T: 'static> GetTypeId<T> {
 const fn check_type_id<T: 'static>() -> bool {
     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
     //~^ ERROR constant pattern depends on a generic parameter
-    //~| ERROR constant pattern depends on a generic parameter
 }
 
 pub struct GetTypeNameLen<T>(T);
@@ -31,7 +30,6 @@ impl<T: 'static> GetTypeNameLen<T> {
 const fn check_type_name_len<T: 'static>() -> bool {
     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
     //~^ ERROR constant pattern depends on a generic parameter
-    //~| ERROR constant pattern depends on a generic parameter
 }
 
 fn main() {
diff --git a/tests/ui/consts/issue-73976-polymorphic.stderr b/tests/ui/consts/issue-73976-polymorphic.stderr
index 442ad23f2cc..97a5fbc5747 100644
--- a/tests/ui/consts/issue-73976-polymorphic.stderr
+++ b/tests/ui/consts/issue-73976-polymorphic.stderr
@@ -5,22 +5,10 @@ LL |     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
    |                                     ^^^^^^^^^^^^^^^^^^^^^
 
 error: constant pattern depends on a generic parameter
-  --> $DIR/issue-73976-polymorphic.rs:32:42
+  --> $DIR/issue-73976-polymorphic.rs:31:42
    |
 LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
    |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: constant pattern depends on a generic parameter
-  --> $DIR/issue-73976-polymorphic.rs:20:37
-   |
-LL |     matches!(GetTypeId::<T>::VALUE, GetTypeId::<T>::VALUE)
-   |                                     ^^^^^^^^^^^^^^^^^^^^^
-
-error: constant pattern depends on a generic parameter
-  --> $DIR/issue-73976-polymorphic.rs:32:42
-   |
-LL |     matches!(GetTypeNameLen::<T>::VALUE, GetTypeNameLen::<T>::VALUE)
-   |                                          ^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/consts/issue-78655.rs b/tests/ui/consts/issue-78655.rs
index 82d2d7c21d8..cd95ee32c60 100644
--- a/tests/ui/consts/issue-78655.rs
+++ b/tests/ui/consts/issue-78655.rs
@@ -6,5 +6,4 @@ const FOO: *const u32 = {
 fn main() {
     let FOO = FOO;
     //~^ ERROR could not evaluate constant pattern
-    //~| ERROR could not evaluate constant pattern
 }
diff --git a/tests/ui/consts/issue-78655.stderr b/tests/ui/consts/issue-78655.stderr
index 6b83fa0e5a0..5a38d023d6f 100644
--- a/tests/ui/consts/issue-78655.stderr
+++ b/tests/ui/consts/issue-78655.stderr
@@ -17,12 +17,6 @@ error: could not evaluate constant pattern
 LL |     let FOO = FOO;
    |         ^^^
 
-error: could not evaluate constant pattern
-  --> $DIR/issue-78655.rs:7:9
-   |
-LL |     let FOO = FOO;
-   |         ^^^
-
-error: aborting due to 3 previous errors
+error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0381`.
diff --git a/tests/ui/consts/issue-79137-toogeneric.rs b/tests/ui/consts/issue-79137-toogeneric.rs
index 456035458cf..a80c9f48d7b 100644
--- a/tests/ui/consts/issue-79137-toogeneric.rs
+++ b/tests/ui/consts/issue-79137-toogeneric.rs
@@ -11,7 +11,6 @@ impl<T> GetVariantCount<T> {
 const fn check_variant_count<T>() -> bool {
     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
     //~^ ERROR constant pattern depends on a generic parameter
-    //~| ERROR constant pattern depends on a generic parameter
 }
 
 fn main() {
diff --git a/tests/ui/consts/issue-79137-toogeneric.stderr b/tests/ui/consts/issue-79137-toogeneric.stderr
index 579e6aa09bd..efe4fd22e54 100644
--- a/tests/ui/consts/issue-79137-toogeneric.stderr
+++ b/tests/ui/consts/issue-79137-toogeneric.stderr
@@ -4,11 +4,5 @@ error: constant pattern depends on a generic parameter
 LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
    |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: constant pattern depends on a generic parameter
-  --> $DIR/issue-79137-toogeneric.rs:12:43
-   |
-LL |     matches!(GetVariantCount::<T>::VALUE, GetVariantCount::<T>::VALUE)
-   |                                           ^^^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
index 6df2fe3d03b..e3a0d93f09b 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.32bit.stderr
@@ -27,7 +27,7 @@ LL | const U8_MUT: &u8 = {
            }
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:43:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:42:9
    |
 LL |         U8_MUT => true,
    |         ^^^^^^
@@ -39,7 +39,7 @@ LL |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:54:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:52:9
    |
 LL |         U8_MUT2 => true,
    |         ^^^^^^^
@@ -51,31 +51,7 @@ LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None =>
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:62:9
-   |
-LL |         U8_MUT3 => true,
-   |         ^^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:34:9
-   |
-LL |         SLICE_MUT => true,
-   |         ^^^^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:43:9
-   |
-LL |         U8_MUT => true,
-   |         ^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:54:9
-   |
-LL |         U8_MUT2 => true,
-   |         ^^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:62:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:59:9
    |
 LL |         U8_MUT3 => true,
    |         ^^^^^^^
@@ -133,6 +109,6 @@ help: skipping check that does not even have a feature gate
 LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors; 1 warning emitted
+error: aborting due to 8 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
index 8802f3adaca..a323e9a05f0 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.64bit.stderr
@@ -27,7 +27,7 @@ LL | const U8_MUT: &u8 = {
            }
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:43:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:42:9
    |
 LL |         U8_MUT => true,
    |         ^^^^^^
@@ -39,7 +39,7 @@ LL |     unsafe { &(*static_cross_crate::ZERO_REF)[0] }
    |               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:54:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:52:9
    |
 LL |         U8_MUT2 => true,
    |         ^^^^^^^
@@ -51,31 +51,7 @@ LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None =>
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ constant accesses static
 
 error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:62:9
-   |
-LL |         U8_MUT3 => true,
-   |         ^^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:34:9
-   |
-LL |         SLICE_MUT => true,
-   |         ^^^^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:43:9
-   |
-LL |         U8_MUT => true,
-   |         ^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:54:9
-   |
-LL |         U8_MUT2 => true,
-   |         ^^^^^^^
-
-error: could not evaluate constant pattern
-  --> $DIR/const_refers_to_static_cross_crate.rs:62:9
+  --> $DIR/const_refers_to_static_cross_crate.rs:59:9
    |
 LL |         U8_MUT3 => true,
    |         ^^^^^^^
@@ -133,6 +109,6 @@ help: skipping check that does not even have a feature gate
 LL |     unsafe { match static_cross_crate::OPT_ZERO { Some(ref u) => u, None => panic!() } }
    |                    ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 12 previous errors; 1 warning emitted
+error: aborting due to 8 previous errors; 1 warning emitted
 
 For more information about this error, try `rustc --explain E0080`.
diff --git a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
index bf4f14f4d5a..bbaa32ddfd1 100644
--- a/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
+++ b/tests/ui/consts/miri_unleashed/const_refers_to_static_cross_crate.rs
@@ -33,7 +33,6 @@ pub fn test(x: &[u8; 1]) -> bool {
     match x {
         SLICE_MUT => true,
         //~^ ERROR could not evaluate constant pattern
-        //~| ERROR could not evaluate constant pattern
         &[1..] => false,
     }
 }
@@ -42,7 +41,6 @@ pub fn test2(x: &u8) -> bool {
     match x {
         U8_MUT => true,
         //~^ ERROR could not evaluate constant pattern
-        //~| ERROR could not evaluate constant pattern
         &(1..) => false,
     }
 }
@@ -53,7 +51,6 @@ pub fn test3(x: &u8) -> bool {
     match x {
         U8_MUT2 => true,
         //~^ ERROR could not evaluate constant pattern
-        //~| ERROR could not evaluate constant pattern
         &(1..) => false,
     }
 }
@@ -61,7 +58,6 @@ pub fn test4(x: &u8) -> bool {
     match x {
         U8_MUT3 => true,
         //~^ ERROR could not evaluate constant pattern
-        //~| ERROR could not evaluate constant pattern
         &(1..) => false,
     }
 }
diff --git a/tests/ui/error-codes/E0004.stderr b/tests/ui/error-codes/E0004.stderr
index 4ac8c904f05..603bc5237ea 100644
--- a/tests/ui/error-codes/E0004.stderr
+++ b/tests/ui/error-codes/E0004.stderr
@@ -14,7 +14,7 @@ LL |     HastaLaVistaBaby,
    = note: the matched value is of type `Terminator`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         Terminator::TalkToMyHand => {}
+LL ~         Terminator::TalkToMyHand => {},
 LL +         Terminator::HastaLaVistaBaby => todo!()
    |
 
diff --git a/tests/ui/error-codes/E0030-teach.rs b/tests/ui/error-codes/E0030-teach.rs
index 8caa4f0931d..388064fb0fa 100644
--- a/tests/ui/error-codes/E0030-teach.rs
+++ b/tests/ui/error-codes/E0030-teach.rs
@@ -4,6 +4,5 @@ fn main() {
     match 5u32 {
         1000 ..= 5 => {}
         //~^ ERROR lower range bound must be less than or equal to upper
-        //~| ERROR lower range bound must be less than or equal to upper
     }
 }
diff --git a/tests/ui/error-codes/E0030-teach.stderr b/tests/ui/error-codes/E0030-teach.stderr
index 800f66416a8..3f1ad4af3a9 100644
--- a/tests/ui/error-codes/E0030-teach.stderr
+++ b/tests/ui/error-codes/E0030-teach.stderr
@@ -6,12 +6,6 @@ LL |         1000 ..= 5 => {}
    |
    = note: When matching against a range, the compiler verifies that the range is non-empty. Range patterns include both end-points, so this is equivalent to requiring the start of the range to be less than or equal to the end of the range.
 
-error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/E0030-teach.rs:5:9
-   |
-LL |         1000 ..= 5 => {}
-   |         ^^^^ lower bound larger than upper bound
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0030`.
diff --git a/tests/ui/error-codes/E0030.rs b/tests/ui/error-codes/E0030.rs
index a5d8f87261b..58d856b7c9d 100644
--- a/tests/ui/error-codes/E0030.rs
+++ b/tests/ui/error-codes/E0030.rs
@@ -2,6 +2,5 @@ fn main() {
     match 5u32 {
         1000 ..= 5 => {}
         //~^ ERROR lower range bound must be less than or equal to upper
-        //~| ERROR lower range bound must be less than or equal to upper
     }
 }
diff --git a/tests/ui/error-codes/E0030.stderr b/tests/ui/error-codes/E0030.stderr
index 8a6114024b6..db8161d8fd5 100644
--- a/tests/ui/error-codes/E0030.stderr
+++ b/tests/ui/error-codes/E0030.stderr
@@ -4,12 +4,6 @@ error[E0030]: lower range bound must be less than or equal to upper
 LL |         1000 ..= 5 => {}
    |         ^^^^ lower bound larger than upper bound
 
-error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/E0030.rs:3:9
-   |
-LL |         1000 ..= 5 => {}
-   |         ^^^^ lower bound larger than upper bound
-
-error: aborting due to 2 previous errors
+error: aborting due to previous error
 
 For more information about this error, try `rustc --explain E0030`.
diff --git a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
index 4d79ce3c659..fb39c404c20 100644
--- a/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
+++ b/tests/ui/feature-gates/feature-gate-non_exhaustive_omitted_patterns_lint.stderr
@@ -115,7 +115,7 @@ LL |         A, B, C,
    = note: the matched value is of type `Foo`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         Foo::B => {}
+LL ~         Foo::B => {},
 LL +         Foo::C => todo!()
    |
 
diff --git a/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
index b5510683328..853b57052ac 100644
--- a/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
+++ b/tests/ui/feature-gates/feature-gate-precise_pointer_size_matching.stderr
@@ -9,7 +9,7 @@ LL |     match 0usize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         0..=usize::MAX => {}
+LL ~         0..=usize::MAX => {},
 LL +         _ => todo!()
    |
 
@@ -24,7 +24,7 @@ LL |     match 0isize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         isize::MIN..=isize::MAX => {}
+LL ~         isize::MIN..=isize::MAX => {},
 LL +         _ => todo!()
    |
 
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
index f55566602db..4b14a314e7a 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.rs
@@ -10,44 +10,31 @@ macro_rules! m {
 fn main() {
     m!(0, ..u8::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0, ..u16::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0, ..u32::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0, ..u64::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0, ..u128::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
 
     m!(0, ..i8::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0, ..i16::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0, ..i32::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0, ..i64::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0, ..i128::MIN);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
 
     m!(0f32, ..f32::NEG_INFINITY);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
     m!(0f64, ..f64::NEG_INFINITY);
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
 
     m!('a', ..'\u{0}');
     //~^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
 }
diff --git a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
index 56b224a8542..e9702bb380f 100644
--- a/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
+++ b/tests/ui/half-open-range-patterns/half-open-range-pats-thir-lower-empty.stderr
@@ -5,155 +5,77 @@ LL |     m!(0, ..u8::MIN);
    |           ^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:13:11
    |
 LL |     m!(0, ..u16::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:15:11
    |
 LL |     m!(0, ..u32::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:20:11
-   |
-LL |     m!(0, ..u64::MIN);
-   |           ^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11
-   |
-LL |     m!(0, ..u128::MIN);
-   |           ^^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11
-   |
-LL |     m!(0, ..i8::MIN);
-   |           ^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11
-   |
-LL |     m!(0, ..i16::MIN);
-   |           ^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:11
-   |
-LL |     m!(0, ..i32::MIN);
-   |           ^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:36:11
-   |
-LL |     m!(0, ..i64::MIN);
-   |           ^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:39:11
-   |
-LL |     m!(0, ..i128::MIN);
-   |           ^^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:43:14
-   |
-LL |     m!(0f32, ..f32::NEG_INFINITY);
-   |              ^^^^^^^^^^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:46:14
-   |
-LL |     m!(0f64, ..f64::NEG_INFINITY);
-   |              ^^^^^^^^^^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:50:13
-   |
-LL |     m!('a', ..'\u{0}');
-   |             ^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:11:11
-   |
-LL |     m!(0, ..u8::MIN);
-   |           ^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:14:11
-   |
-LL |     m!(0, ..u16::MIN);
-   |           ^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
   --> $DIR/half-open-range-pats-thir-lower-empty.rs:17:11
    |
-LL |     m!(0, ..u32::MIN);
-   |           ^^^^^^^^^^
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:20:11
-   |
 LL |     m!(0, ..u64::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:23:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:19:11
    |
 LL |     m!(0, ..u128::MIN);
    |           ^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:27:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:22:11
    |
 LL |     m!(0, ..i8::MIN);
    |           ^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:24:11
    |
 LL |     m!(0, ..i16::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:26:11
    |
 LL |     m!(0, ..i32::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:36:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:28:11
    |
 LL |     m!(0, ..i64::MIN);
    |           ^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:39:11
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:30:11
    |
 LL |     m!(0, ..i128::MIN);
    |           ^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:43:14
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:33:14
    |
 LL |     m!(0f32, ..f32::NEG_INFINITY);
    |              ^^^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:46:14
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:35:14
    |
 LL |     m!(0f64, ..f64::NEG_INFINITY);
    |              ^^^^^^^^^^^^^^^^^^^
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/half-open-range-pats-thir-lower-empty.rs:50:13
+  --> $DIR/half-open-range-pats-thir-lower-empty.rs:38:13
    |
 LL |     m!('a', ..'\u{0}');
    |             ^^^^^^^^^
 
-error: aborting due to 26 previous errors
+error: aborting due to 13 previous errors
 
 For more information about this error, try `rustc --explain E0579`.
diff --git a/tests/ui/impl-trait/auto-trait-leak.stderr b/tests/ui/impl-trait/auto-trait-leak.stderr
index fd0358421eb..e6c750d0e42 100644
--- a/tests/ui/impl-trait/auto-trait-leak.stderr
+++ b/tests/ui/impl-trait/auto-trait-leak.stderr
@@ -29,6 +29,11 @@ note: ...which requires building MIR for `cycle1`...
    |
 LL | fn cycle1() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `cycle1`...
+  --> $DIR/auto-trait-leak.rs:12:1
+   |
+LL | fn cycle1() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building THIR for `cycle1`...
   --> $DIR/auto-trait-leak.rs:12:1
    |
@@ -70,6 +75,11 @@ note: ...which requires building MIR for `cycle2`...
    |
 LL | fn cycle2() -> impl Clone {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^
+note: ...which requires match-checking `cycle2`...
+  --> $DIR/auto-trait-leak.rs:19:1
+   |
+LL | fn cycle2() -> impl Clone {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^
 note: ...which requires building THIR for `cycle2`...
   --> $DIR/auto-trait-leak.rs:19:1
    |
diff --git a/tests/ui/inline-const/const-match-pat-generic.rs b/tests/ui/inline-const/const-match-pat-generic.rs
index 7c0d83516ea..46e501abf6c 100644
--- a/tests/ui/inline-const/const-match-pat-generic.rs
+++ b/tests/ui/inline-const/const-match-pat-generic.rs
@@ -7,7 +7,6 @@ fn foo<const V: usize>() {
     match 0 {
         const { V } => {},
         //~^ ERROR constant pattern depends on a generic parameter
-        //~| ERROR constant pattern depends on a generic parameter
         _ => {},
     }
 }
@@ -20,7 +19,6 @@ fn bar<const V: usize>() {
     match 0 {
         const { f(V) } => {},
         //~^ ERROR constant pattern depends on a generic parameter
-        //~| ERROR constant pattern depends on a generic parameter
         _ => {},
     }
 }
diff --git a/tests/ui/inline-const/const-match-pat-generic.stderr b/tests/ui/inline-const/const-match-pat-generic.stderr
index 77267f12fb1..4ffbde4101d 100644
--- a/tests/ui/inline-const/const-match-pat-generic.stderr
+++ b/tests/ui/inline-const/const-match-pat-generic.stderr
@@ -5,22 +5,10 @@ LL |         const { V } => {},
    |         ^^^^^^^^^^^
 
 error: constant pattern depends on a generic parameter
-  --> $DIR/const-match-pat-generic.rs:21:9
+  --> $DIR/const-match-pat-generic.rs:20:9
    |
 LL |         const { f(V) } => {},
    |         ^^^^^^^^^^^^^^
 
-error: constant pattern depends on a generic parameter
-  --> $DIR/const-match-pat-generic.rs:8:9
-   |
-LL |         const { V } => {},
-   |         ^^^^^^^^^^^
-
-error: constant pattern depends on a generic parameter
-  --> $DIR/const-match-pat-generic.rs:21:9
-   |
-LL |         const { f(V) } => {},
-   |         ^^^^^^^^^^^^^^
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/match/match-range-fail-2.rs b/tests/ui/match/match-range-fail-2.rs
index 792664e1db8..4489cf1ab1f 100644
--- a/tests/ui/match/match-range-fail-2.rs
+++ b/tests/ui/match/match-range-fail-2.rs
@@ -3,22 +3,19 @@
 fn main() {
     match 5 {
         6 ..= 1 => { }
+        //~^ ERROR lower range bound must be less than or equal to upper
         _ => { }
     };
-    //~^^^ ERROR lower range bound must be less than or equal to upper
-    //~| ERROR lower range bound must be less than or equal to upper
 
     match 5 {
         0 .. 0 => { }
+        //~^ ERROR lower range bound must be less than upper
         _ => { }
     };
-    //~^^^ ERROR lower range bound must be less than upper
-    //~| ERROR lower range bound must be less than upper
 
     match 5u64 {
         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
+        //~^ ERROR lower range bound must be less than or equal to upper
         _ => { }
     };
-    //~^^^ ERROR lower range bound must be less than or equal to upper
-    //~| ERROR lower range bound must be less than or equal to upper
 }
diff --git a/tests/ui/match/match-range-fail-2.stderr b/tests/ui/match/match-range-fail-2.stderr
index 7a0852d7e6c..52a2bf2b34a 100644
--- a/tests/ui/match/match-range-fail-2.stderr
+++ b/tests/ui/match/match-range-fail-2.stderr
@@ -5,36 +5,18 @@ LL |         6 ..= 1 => { }
    |         ^ lower bound larger than upper bound
 
 error[E0579]: lower range bound must be less than upper
-  --> $DIR/match-range-fail-2.rs:12:9
+  --> $DIR/match-range-fail-2.rs:11:9
    |
 LL |         0 .. 0 => { }
    |         ^
 
 error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/match-range-fail-2.rs:19:9
+  --> $DIR/match-range-fail-2.rs:17:9
    |
 LL |         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
    |         ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
 
-error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/match-range-fail-2.rs:5:9
-   |
-LL |         6 ..= 1 => { }
-   |         ^ lower bound larger than upper bound
-
-error[E0579]: lower range bound must be less than upper
-  --> $DIR/match-range-fail-2.rs:12:9
-   |
-LL |         0 .. 0 => { }
-   |         ^
-
-error[E0030]: lower range bound must be less than or equal to upper
-  --> $DIR/match-range-fail-2.rs:19:9
-   |
-LL |         0xFFFF_FFFF_FFFF_FFFF ..= 1 => { }
-   |         ^^^^^^^^^^^^^^^^^^^^^ lower bound larger than upper bound
-
-error: aborting due to 6 previous errors
+error: aborting due to 3 previous errors
 
 Some errors have detailed explanations: E0030, E0579.
 For more information about an error, try `rustc --explain E0030`.
diff --git a/tests/ui/never_type/exhaustive_patterns.stderr b/tests/ui/never_type/exhaustive_patterns.stderr
index 40c7c1d1067..5fed903eb70 100644
--- a/tests/ui/never_type/exhaustive_patterns.stderr
+++ b/tests/ui/never_type/exhaustive_patterns.stderr
@@ -17,8 +17,8 @@ LL |     B(inner::Wrapper<B>),
    = note: the matched value is of type `Either<(), !>`
 help: you might want to use `if let` to ignore the variant that isn't matched
    |
-LL |     if let Either::A(()) = foo() { todo!() }
-   |     ++                           ~~~~~~~~~~~
+LL |     if let Either::A(()) = foo() { todo!() };
+   |     ++                           +++++++++++
 
 error: aborting due to previous error
 
diff --git a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
index 9aa808e6bc9..9f691aea8a7 100644
--- a/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
+++ b/tests/ui/or-patterns/exhaustiveness-non-exhaustive.stderr
@@ -7,7 +7,7 @@ LL |     match (0u8, 0u8) {
    = note: the matched value is of type `(u8, u8)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         (0 | 1, 2 | 3) => {}
+LL ~         (0 | 1, 2 | 3) => {},
 LL +         (2_u8..=u8::MAX, _) => todo!()
    |
 
@@ -20,7 +20,7 @@ LL |     match ((0u8,),) {
    = note: the matched value is of type `((u8,),)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         ((0 | 1,) | (2 | 3,),) => {}
+LL ~         ((0 | 1,) | (2 | 3,),) => {},
 LL +         ((4_u8..=u8::MAX)) => todo!()
    |
 
@@ -33,7 +33,7 @@ LL |     match (Some(0u8),) {
    = note: the matched value is of type `(Option<u8>,)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         (None | Some(0 | 1),) => {}
+LL ~         (None | Some(0 | 1),) => {},
 LL +         (Some(2_u8..=u8::MAX)) => todo!()
    |
 
diff --git a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
index 4adcf4feee9..fdb1a9bb4b7 100644
--- a/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
+++ b/tests/ui/or-patterns/issue-69875-should-have-been-expanded-earlier-non-exhaustive.stderr
@@ -9,8 +9,8 @@ LL |     let (0 | (1 | 2)) = 0;
    = note: the matched value is of type `i32`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let (0 | (1 | 2)) = 0 { todo!() }
-   |     ++                       ~~~~~~~~~~~
+LL |     if let (0 | (1 | 2)) = 0 { todo!() };
+   |     ++                       +++++++++++
 
 error[E0004]: non-exhaustive patterns: `i32::MIN..=-1_i32` and `3_i32..=i32::MAX` not covered
   --> $DIR/issue-69875-should-have-been-expanded-earlier-non-exhaustive.rs:3:11
@@ -21,7 +21,7 @@ LL |     match 0 {
    = note: the matched value is of type `i32`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         0 | (1 | 2) => {}
+LL ~         0 | (1 | 2) => {},
 LL +         i32::MIN..=-1_i32 | 3_i32..=i32::MAX => todo!()
    |
 
diff --git a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
index 29cd6c45c34..25838fbf0ab 100644
--- a/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
+++ b/tests/ui/pattern/bindings-after-at/bind-by-move-neither-can-live-while-the-other-survives-1.stderr
@@ -2,18 +2,16 @@ error: cannot move out of value because it is borrowed
   --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:12:14
    |
 LL |         Some(ref _y @ _z) => {}
-   |              ------^^^--
-   |              |        |
-   |              |        value is moved into `_z` here
+   |              ^^^^^^   -- value is moved into `_z` here
+   |              |
    |              value is borrowed by `_y` here
 
 error: borrow of moved value
   --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:19:14
    |
 LL |         Some(_z @ ref _y) => {}
-   |              --^^^------
-   |              |    |
-   |              |    value borrowed here after move
+   |              ^^   ------ value borrowed here after move
+   |              |
    |              value moved into `_z` here
    |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
    |
@@ -26,18 +24,16 @@ error: cannot move out of value because it is borrowed
   --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:26:14
    |
 LL |         Some(ref mut _y @ _z) => {}
-   |              ----------^^^--
-   |              |            |
-   |              |            value is moved into `_z` here
+   |              ^^^^^^^^^^   -- value is moved into `_z` here
+   |              |
    |              value is mutably borrowed by `_y` here
 
 error: borrow of moved value
   --> $DIR/bind-by-move-neither-can-live-while-the-other-survives-1.rs:33:14
    |
 LL |         Some(_z @ ref mut _y) => {}
-   |              --^^^----------
-   |              |    |
-   |              |    value borrowed here after move
+   |              ^^   ---------- value borrowed here after move
+   |              |
    |              value moved into `_z` here
    |              move occurs because `_z` has type `X` which does not implement the `Copy` trait
    |
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
index 2c123b01e17..9305facc406 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-at-and-box.stderr
@@ -2,72 +2,64 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-at-and-box.rs:31:9
    |
 LL |     let ref a @ box b = Box::new(NC);
-   |         -----^^^^^^^-
-   |         |           |
-   |         |           value is moved into `b` here
+   |         ^^^^^       - value is moved into `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-at-and-box.rs:34:9
    |
 LL |     let ref a @ box ref mut b = Box::new(nc());
-   |         -----^^^^^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^       --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-at-and-box.rs:36:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
-   |         -----^^^^^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^       --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-at-and-box.rs:38:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
-   |         -----^^^^^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^       --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-at-and-box.rs:42:9
    |
 LL |     let ref a @ box ref mut b = Box::new(NC);
-   |         -----^^^^^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^       --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-at-and-box.rs:48:9
    |
 LL |     let ref mut a @ box ref b = Box::new(NC);
-   |         ---------^^^^^^^-----
-   |         |               |
-   |         |               value is borrowed by `b` here
+   |         ^^^^^^^^^       ----- value is borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-at-and-box.rs:62:9
    |
 LL |         ref mut a @ box ref b => {
-   |         ---------^^^^^^^-----
-   |         |               |
-   |         |               value is borrowed by `b` here
+   |         ^^^^^^^^^       ----- value is borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-at-and-box.rs:54:11
    |
 LL |     fn f5(ref mut a @ box ref b: Box<NC>) {
-   |           ---------^^^^^^^-----
-   |           |               |
-   |           |               value is borrowed by `b` here
+   |           ^^^^^^^^^       ----- value is borrowed by `b` here
+   |           |
    |           value is mutably borrowed by `a` here
 
 error[E0382]: borrow of moved value
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
index d6474f1b49f..c440f4619f5 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse-promotion.stderr
@@ -2,9 +2,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse-promotion.rs:6:9
    |
 LL |     let a @ ref b = U;
-   |         -^^^-----
-   |         |   |
-   |         |   value borrowed here after move
+   |         ^   ----- value borrowed here after move
+   |         |
    |         value moved into `a` here
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
    |
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
index 389e86e6464..13989ebadcb 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.stderr
@@ -2,9 +2,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:22:9
    |
 LL |     let a @ ref b = U;
-   |         -^^^-----
-   |         |   |
-   |         |   value borrowed here after move
+   |         ^   ----- value borrowed here after move
+   |         |
    |         value moved into `a` here
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
    |
@@ -17,9 +16,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:9
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
-   |         -^^^^^^^^^^^^---------^^^^^^-----^
-   |         |            |              |
-   |         |            |              value borrowed here after move
+   |         ^            ---------      ----- value borrowed here after move
+   |         |            |
    |         |            value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
@@ -33,9 +31,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:14
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
-   |              -----^^^---------
-   |              |       |
-   |              |       value borrowed here after move
+   |              ^^^^^   --------- value borrowed here after move
+   |              |
    |              value moved into `b` here
    |              move occurs because `b` has type `U` which does not implement the `Copy` trait
    |
@@ -48,9 +45,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:24:33
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (U, U);
-   |                                 -^^^-----
-   |                                 |   |
-   |                                 |   value borrowed here after move
+   |                                 ^   ----- value borrowed here after move
+   |                                 |
    |                                 value moved into `d` here
    |                                 move occurs because `d` has type `U` which does not implement the `Copy` trait
    |
@@ -63,9 +59,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:29:9
    |
 LL |     let a @ [ref mut b, ref c] = [U, U];
-   |         -^^^^---------^^-----^
-   |         |    |          |
-   |         |    |          value borrowed here after move
+   |         ^    ---------  ----- value borrowed here after move
+   |         |    |
    |         |    value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
@@ -79,9 +74,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:31:9
    |
 LL |     let a @ ref b = u();
-   |         -^^^-----
-   |         |   |
-   |         |   value borrowed here after move
+   |         ^   ----- value borrowed here after move
+   |         |
    |         value moved into `a` here
    |         move occurs because `a` has type `U` which does not implement the `Copy` trait
    |
@@ -94,9 +88,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:9
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
-   |         -^^^^^^^^^^^^---------^^^^^^-----^
-   |         |            |              |
-   |         |            |              value borrowed here after move
+   |         ^            ---------      ----- value borrowed here after move
+   |         |            |
    |         |            value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
@@ -110,9 +103,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:14
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
-   |              -----^^^---------
-   |              |       |
-   |              |       value borrowed here after move
+   |              ^^^^^   --------- value borrowed here after move
+   |              |
    |              value moved into `b` here
    |              move occurs because `b` has type `U` which does not implement the `Copy` trait
    |
@@ -125,9 +117,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:33:33
    |
 LL |     let a @ (mut b @ ref mut c, d @ ref e) = (u(), u());
-   |                                 -^^^-----
-   |                                 |   |
-   |                                 |   value borrowed here after move
+   |                                 ^   ----- value borrowed here after move
+   |                                 |
    |                                 value moved into `d` here
    |                                 move occurs because `d` has type `U` which does not implement the `Copy` trait
    |
@@ -140,9 +131,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:38:9
    |
 LL |     let a @ [ref mut b, ref c] = [u(), u()];
-   |         -^^^^---------^^-----^
-   |         |    |          |
-   |         |    |          value borrowed here after move
+   |         ^    ---------  ----- value borrowed here after move
+   |         |    |
    |         |    value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
@@ -156,9 +146,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:42:9
    |
 LL |         a @ Some(ref b) => {}
-   |         -^^^^^^^^-----^
-   |         |        |
-   |         |        value borrowed here after move
+   |         ^        ----- value borrowed here after move
+   |         |
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
    |
@@ -171,9 +160,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |         -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
-   |         |                 |              |
-   |         |                 |              value borrowed here after move
+   |         ^                 ---------      ----- value borrowed here after move
+   |         |                 |
    |         |                 value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
@@ -187,9 +175,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:19
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |                   -----^^^---------
-   |                   |       |
-   |                   |       value borrowed here after move
+   |                   ^^^^^   --------- value borrowed here after move
+   |                   |
    |                   value moved into `b` here
    |                   move occurs because `b` has type `U` which does not implement the `Copy` trait
    |
@@ -202,9 +189,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |                                      -^^^-----
-   |                                      |   |
-   |                                      |   value borrowed here after move
+   |                                      ^   ----- value borrowed here after move
+   |                                      |
    |                                      value moved into `d` here
    |                                      move occurs because `d` has type `U` which does not implement the `Copy` trait
    |
@@ -217,9 +203,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:9
    |
 LL |         mut a @ Some([ref b, ref mut c]) => {}
-   |         -----^^^^^^^^^-----^^---------^^
-   |         |             |      |
-   |         |             |      value borrowed here after move
+   |         ^^^^^         -----  --------- value borrowed here after move
+   |         |             |
    |         |             value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
@@ -233,9 +218,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9
    |
 LL |         a @ Some(ref b) => {}
-   |         -^^^^^^^^-----^
-   |         |        |
-   |         |        value borrowed here after move
+   |         ^        ----- value borrowed here after move
+   |         |
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<U>` which does not implement the `Copy` trait
    |
@@ -248,9 +232,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |         -^^^^^^^^^^^^^^^^^---------^^^^^^-----^^
-   |         |                 |              |
-   |         |                 |              value borrowed here after move
+   |         ^                 ---------      ----- value borrowed here after move
+   |         |                 |
    |         |                 value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<(U, U)>` which does not implement the `Copy` trait
@@ -264,9 +247,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |                   -----^^^---------
-   |                   |       |
-   |                   |       value borrowed here after move
+   |                   ^^^^^   --------- value borrowed here after move
+   |                   |
    |                   value moved into `b` here
    |                   move occurs because `b` has type `U` which does not implement the `Copy` trait
    |
@@ -279,9 +261,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |                                      -^^^-----
-   |                                      |   |
-   |                                      |   value borrowed here after move
+   |                                      ^   ----- value borrowed here after move
+   |                                      |
    |                                      value moved into `d` here
    |                                      move occurs because `d` has type `U` which does not implement the `Copy` trait
    |
@@ -294,9 +275,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9
    |
 LL |         mut a @ Some([ref b, ref mut c]) => {}
-   |         -----^^^^^^^^^-----^^---------^^
-   |         |             |      |
-   |         |             |      value borrowed here after move
+   |         ^^^^^         -----  --------- value borrowed here after move
+   |         |             |
    |         |             value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `Option<[U; 2]>` which does not implement the `Copy` trait
@@ -310,9 +290,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11
    |
 LL |     fn f1(a @ ref b: U) {}
-   |           -^^^-----
-   |           |   |
-   |           |   value borrowed here after move
+   |           ^   ----- value borrowed here after move
+   |           |
    |           value moved into `a` here
    |           move occurs because `a` has type `U` which does not implement the `Copy` trait
    |
@@ -325,9 +304,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:11
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
-   |           -----^^^^^^^^-----^^^^^^^^^^-----^
-   |           |            |              |
-   |           |            |              value borrowed here after move
+   |           ^^^^^        -----          ----- value borrowed here after move
+   |           |            |
    |           |            value borrowed here after move
    |           value moved into `a` here
    |           move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
@@ -341,9 +319,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:20
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
-   |                    -^^^-----
-   |                    |   |
-   |                    |   value borrowed here after move
+   |                    ^   ----- value borrowed here after move
+   |                    |
    |                    value moved into `b` here
    |                    move occurs because `b` has type `U` which does not implement the `Copy` trait
    |
@@ -356,9 +333,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:14:31
    |
 LL |     fn f2(mut a @ (b @ ref c, mut d @ ref e): (U, U)) {}
-   |                               -----^^^-----
-   |                               |       |
-   |                               |       value borrowed here after move
+   |                               ^^^^^   ----- value borrowed here after move
+   |                               |
    |                               value moved into `d` here
    |                               move occurs because `d` has type `U` which does not implement the `Copy` trait
    |
@@ -371,9 +347,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:19:11
    |
 LL |     fn f3(a @ [ref mut b, ref c]: [U; 2]) {}
-   |           -^^^^---------^^-----^
-   |           |    |          |
-   |           |    |          value borrowed here after move
+   |           ^    ---------  ----- value borrowed here after move
+   |           |    |
    |           |    value borrowed here after move
    |           value moved into `a` here
    |           move occurs because `a` has type `[U; 2]` which does not implement the `Copy` trait
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
index 4f7fbc9e04b..00593b2a98f 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.stderr
@@ -2,18 +2,16 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:24:9
    |
 LL |     let ref a @ b = U;
-   |         -----^^^-
-   |         |       |
-   |         |       value is moved into `b` here
+   |         ^^^^^   - value is moved into `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:26:9
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
-   |         -----^^^^^^^^^^^^-----^^^^^^^^^^-^
-   |         |                |              |
-   |         |                |              value is moved into `e` here
+   |         ^^^^^            -----          - value is moved into `e` here
+   |         |                |
    |         |                value is moved into `c` here
    |         value is borrowed by `a` here
 
@@ -21,27 +19,24 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:26:18
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
-   |                  -----^^^-----
-   |                  |       |
-   |                  |       value is moved into `c` here
+   |                  ^^^^^   ----- value is moved into `c` here
+   |                  |
    |                  value is borrowed by `b` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:26:33
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (U, U);
-   |                                 -----^^^-
-   |                                 |       |
-   |                                 |       value is moved into `e` here
+   |                                 ^^^^^   - value is moved into `e` here
+   |                                 |
    |                                 value is borrowed by `d` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:30:9
    |
 LL |     let ref mut a @ [b, mut c] = [U, U];
-   |         ---------^^^^-^^-----^
-   |         |            |  |
-   |         |            |  value is moved into `c` here
+   |         ^^^^^^^^^    -  ----- value is moved into `c` here
+   |         |            |
    |         |            value is moved into `b` here
    |         value is mutably borrowed by `a` here
 
@@ -49,18 +44,16 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:33:9
    |
 LL |     let ref a @ b = u();
-   |         -----^^^-
-   |         |       |
-   |         |       value is moved into `b` here
+   |         ^^^^^   - value is moved into `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:36:9
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
-   |         -----^^^^^^^^^^^^-----^^^^^^^^^^-^
-   |         |                |              |
-   |         |                |              value is moved into `e` here
+   |         ^^^^^            -----          - value is moved into `e` here
+   |         |                |
    |         |                value is moved into `c` here
    |         value is borrowed by `a` here
 
@@ -68,27 +61,24 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:36:18
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
-   |                  -----^^^-----
-   |                  |       |
-   |                  |       value is moved into `c` here
+   |                  ^^^^^   ----- value is moved into `c` here
+   |                  |
    |                  value is borrowed by `b` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:36:33
    |
 LL |     let ref a @ (ref b @ mut c, ref d @ e) = (u(), u());
-   |                                 -----^^^-
-   |                                 |       |
-   |                                 |       value is moved into `e` here
+   |                                 ^^^^^   - value is moved into `e` here
+   |                                 |
    |                                 value is borrowed by `d` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:42:9
    |
 LL |     let ref mut a @ [b, mut c] = [u(), u()];
-   |         ---------^^^^-^^-----^
-   |         |            |  |
-   |         |            |  value is moved into `c` here
+   |         ^^^^^^^^^    -  ----- value is moved into `c` here
+   |         |            |
    |         |            value is moved into `b` here
    |         value is mutably borrowed by `a` here
 
@@ -96,18 +86,16 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:47:9
    |
 LL |         ref a @ Some(b) => {}
-   |         -----^^^^^^^^-^
-   |         |            |
-   |         |            value is moved into `b` here
+   |         ^^^^^        - value is moved into `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:52:9
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
-   |         -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
-   |         |                     |              |
-   |         |                     |              value is moved into `e` here
+   |         ^^^^^                 -----          - value is moved into `e` here
+   |         |                     |
    |         |                     value is moved into `c` here
    |         value is borrowed by `a` here
 
@@ -115,27 +103,24 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:52:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
-   |                       -----^^^-----
-   |                       |       |
-   |                       |       value is moved into `c` here
+   |                       ^^^^^   ----- value is moved into `c` here
+   |                       |
    |                       value is borrowed by `b` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:52:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
-   |                                      -----^^^-
-   |                                      |       |
-   |                                      |       value is moved into `e` here
+   |                                      ^^^^^   - value is moved into `e` here
+   |                                      |
    |                                      value is borrowed by `d` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9
    |
 LL |         ref mut a @ Some([b, mut c]) => {}
-   |         ---------^^^^^^^^^-^^-----^^
-   |         |                 |  |
-   |         |                 |  value is moved into `c` here
+   |         ^^^^^^^^^         -  ----- value is moved into `c` here
+   |         |                 |
    |         |                 value is moved into `b` here
    |         value is mutably borrowed by `a` here
 
@@ -143,18 +128,16 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9
    |
 LL |         ref a @ Some(b) => {}
-   |         -----^^^^^^^^-^
-   |         |            |
-   |         |            value is moved into `b` here
+   |         ^^^^^        - value is moved into `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:69:9
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
-   |         -----^^^^^^^^^^^^^^^^^-----^^^^^^^^^^-^^
-   |         |                     |              |
-   |         |                     |              value is moved into `e` here
+   |         ^^^^^                 -----          - value is moved into `e` here
+   |         |                     |
    |         |                     value is moved into `c` here
    |         value is borrowed by `a` here
 
@@ -162,27 +145,24 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
-   |                       -----^^^-----
-   |                       |       |
-   |                       |       value is moved into `c` here
+   |                       ^^^^^   ----- value is moved into `c` here
+   |                       |
    |                       value is borrowed by `b` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
-   |                                      -----^^^-
-   |                                      |       |
-   |                                      |       value is moved into `e` here
+   |                                      ^^^^^   - value is moved into `e` here
+   |                                      |
    |                                      value is borrowed by `d` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:78:9
    |
 LL |         ref mut a @ Some([b, mut c]) => {}
-   |         ---------^^^^^^^^^-^^-----^^
-   |         |                 |  |
-   |         |                 |  value is moved into `c` here
+   |         ^^^^^^^^^         -  ----- value is moved into `c` here
+   |         |                 |
    |         |                 value is moved into `b` here
    |         value is mutably borrowed by `a` here
 
@@ -190,18 +170,16 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11
    |
 LL |     fn f1(ref a @ b: U) {}
-   |           -----^^^-
-   |           |       |
-   |           |       value is moved into `b` here
+   |           ^^^^^   - value is moved into `b` here
+   |           |
    |           value is borrowed by `a` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:14:11
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
-   |           -----^^^^^^^^^^^^-----^^^^^^^^^^-^
-   |           |                |              |
-   |           |                |              value is moved into `e` here
+   |           ^^^^^            -----          - value is moved into `e` here
+   |           |                |
    |           |                value is moved into `c` here
    |           value is borrowed by `a` here
 
@@ -209,27 +187,24 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:14:20
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
-   |                    -----^^^-----
-   |                    |       |
-   |                    |       value is moved into `c` here
+   |                    ^^^^^   ----- value is moved into `c` here
+   |                    |
    |                    value is borrowed by `b` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:14:35
    |
 LL |     fn f2(ref a @ (ref b @ mut c, ref d @ e): (U, U)) {}
-   |                                   -----^^^-
-   |                                   |       |
-   |                                   |       value is moved into `e` here
+   |                                   ^^^^^   - value is moved into `e` here
+   |                                   |
    |                                   value is borrowed by `d` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:20:11
    |
 LL |     fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
-   |           ---------^^^^-^^-----^
-   |           |            |  |
-   |           |            |  value is moved into `c` here
+   |           ^^^^^^^^^    -  ----- value is moved into `c` here
+   |           |            |
    |           |            value is moved into `b` here
    |           value is mutably borrowed by `a` here
 
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
index f51b5041858..d6409d1b643 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.stderr
@@ -2,18 +2,16 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9
    |
 LL |         ref mut z @ &mut Some(ref a) => {
-   |         ---------^^^^^^^^^^^^^-----^
-   |         |                     |
-   |         |                     value is borrowed by `a` here
+   |         ^^^^^^^^^             ----- value is borrowed by `a` here
+   |         |
    |         value is mutably borrowed by `z` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:9
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
-   |         ---------^^^^-----------------^
-   |         |            |       |
-   |         |            |       value is mutably borrowed by `c` here
+   |         ^^^^^^^^^    -----   --------- value is mutably borrowed by `c` here
+   |         |            |
    |         |            value is borrowed by `b` here
    |         value is mutably borrowed by `a` here
 
@@ -21,36 +19,32 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:33:22
    |
 LL |     let ref mut a @ (ref b @ ref mut c) = u(); // sub-in-sub
-   |                      -----^^^---------
-   |                      |       |
-   |                      |       value is mutably borrowed by `c` here
+   |                      ^^^^^   --------- value is mutably borrowed by `c` here
+   |                      |
    |                      value is borrowed by `b` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:37:9
    |
 LL |     let ref a @ ref mut b = U;
-   |         -----^^^---------
-   |         |       |
-   |         |       value is mutably borrowed by `b` here
+   |         ^^^^^   --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:39:9
    |
 LL |     let ref mut a @ ref b = U;
-   |         ---------^^^-----
-   |         |           |
-   |         |           value is borrowed by `b` here
+   |         ^^^^^^^^^   ----- value is borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:41:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
-   |         -----^^^^---------^^---------^
-   |         |        |          |
-   |         |        |          value is mutably borrowed by `c` here
+   |         ^^^^^    ---------  --------- value is mutably borrowed by `c` here
+   |         |        |
    |         |        value is mutably borrowed by `b` here
    |         value is borrowed by `a` here
 
@@ -58,9 +52,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:43:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
-   |         ---------^^^^-----^^-----^
-   |         |            |      |
-   |         |            |      value is borrowed by `c` here
+   |         ^^^^^^^^^    -----  ----- value is borrowed by `c` here
+   |         |            |
    |         |            value is borrowed by `b` here
    |         value is mutably borrowed by `a` here
 
@@ -68,153 +61,136 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9
    |
 LL |     let ref mut a @ ref b = u();
-   |         ---------^^^-----
-   |         |           |
-   |         |           value is borrowed by `b` here
+   |         ^^^^^^^^^   ----- value is borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:51:9
    |
 LL |     let ref a @ ref mut b = u();
-   |         -----^^^---------
-   |         |       |
-   |         |       value is mutably borrowed by `b` here
+   |         ^^^^^   --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:57:9
    |
 LL |     let ref mut a @ ref b = U;
-   |         ---------^^^-----
-   |         |           |
-   |         |           value is borrowed by `b` here
+   |         ^^^^^^^^^   ----- value is borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:61:9
    |
 LL |     let ref a @ ref mut b = U;
-   |         -----^^^---------
-   |         |       |
-   |         |       value is mutably borrowed by `b` here
+   |         ^^^^^   --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
-   |         ---------^^^^^^-----^
-   |         |              |
-   |         |              value is borrowed by `b` here
+   |         ^^^^^^^^^      ----- value is borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:67:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) => {
-   |                                 ---------^^^^^^^-----^
-   |                                 |               |
-   |                                 |               value is borrowed by `b` here
+   |                                 ^^^^^^^^^       ----- value is borrowed by `b` here
+   |                                 |
    |                                 value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
-   |         -----^^^^^^---------^
-   |         |          |
-   |         |          value is mutably borrowed by `b` here
+   |         ^^^^^      --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
-   |                                 -----^^^^^^^---------^
-   |                                 |           |
-   |                                 |           value is mutably borrowed by `b` here
+   |                                 ^^^^^       --------- value is mutably borrowed by `b` here
+   |                                 |
    |                                 value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
-   |         -----^^^^^^---------^
-   |         |          |
-   |         |          value is mutably borrowed by `b` here
+   |         ^^^^^      --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
-   |                                 -----^^^^^^^---------^
-   |                                 |           |
-   |                                 |           value is mutably borrowed by `b` here
+   |                                 ^^^^^       --------- value is mutably borrowed by `b` here
+   |                                 |
    |                                 value is borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
-   |         ---------^^^^^^-----^
-   |         |              |
-   |         |              value is borrowed by `b` here
+   |         ^^^^^^^^^      ----- value is borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
-   |                                 ---------^^^^^^^-----^
-   |                                 |               |
-   |                                 |               value is borrowed by `b` here
+   |                                 ^^^^^^^^^       ----- value is borrowed by `b` here
+   |                                 |
    |                                 value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
-   |         -----^^^^^^---------^
-   |         |          |
-   |         |          value is mutably borrowed by `b` here
+   |         ^^^^^      --------- value is mutably borrowed by `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
-   |                                 -----^^^^^^^---------^
-   |                                 |           |
-   |                                 |           value is mutably borrowed by `b` here
+   |                                 ^^^^^       --------- value is mutably borrowed by `b` here
+   |                                 |
    |                                 value is borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
-   |         ---------^^^^^^-----^
-   |         |              |
-   |         |              value is borrowed by `b` here
+   |         ^^^^^^^^^      ----- value is borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
-   |                                 ---------^^^^^^^-----^
-   |                                 |               |
-   |                                 |               value is borrowed by `b` here
+   |                                 ^^^^^^^^^       ----- value is borrowed by `b` here
+   |                                 |
    |                                 value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
-   |         -----^^^^---------^^---------^
-   |         |        |          |
-   |         |        |          value is mutably borrowed by `c` here
+   |         ^^^^^    ---------  --------- value is mutably borrowed by `c` here
+   |         |        |
    |         |        value is mutably borrowed by `b` here
    |         value is borrowed by `a` here
 
@@ -222,9 +198,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
-   |         -----^^^^---------^^---------^
-   |         |        |          |
-   |         |        |          value is mutably borrowed by `c` here
+   |         ^^^^^    ---------  --------- value is mutably borrowed by `c` here
+   |         |        |
    |         |        value is mutably borrowed by `b` here
    |         value is borrowed by `a` here
 
@@ -232,9 +207,8 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
-   |         -----^^^^---------^^---------^
-   |         |        |          |
-   |         |        |          value is mutably borrowed by `c` here
+   |         ^^^^^    ---------  --------- value is mutably borrowed by `c` here
+   |         |        |
    |         |        value is mutably borrowed by `b` here
    |         value is borrowed by `a` here
 
@@ -242,9 +216,8 @@ error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:134:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
-   |         ---------^^^^-----^^-----^
-   |         |            |      |
-   |         |            |      value is borrowed by `c` here
+   |         ^^^^^^^^^    -----  ----- value is borrowed by `c` here
+   |         |            |
    |         |            value is borrowed by `b` here
    |         value is mutably borrowed by `a` here
 
@@ -252,36 +225,32 @@ error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:22:11
    |
 LL |     fn f1(ref a @ ref mut b: U) {}
-   |           -----^^^---------
-   |           |       |
-   |           |       value is mutably borrowed by `b` here
+   |           ^^^^^   --------- value is mutably borrowed by `b` here
+   |           |
    |           value is borrowed by `a` here
 
 error: cannot borrow value as immutable because it is also borrowed as mutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:24:11
    |
 LL |     fn f2(ref mut a @ ref b: U) {}
-   |           ---------^^^-----
-   |           |           |
-   |           |           value is borrowed by `b` here
+   |           ^^^^^^^^^   ----- value is borrowed by `b` here
+   |           |
    |           value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:26:11
    |
 LL |     fn f3(ref a @ [ref b, ref mut mid @ .., ref c]: [U; 4]) {}
-   |           -----^^^^^^^^^^^----------------^^^^^^^^
-   |           |               |
-   |           |               value is mutably borrowed by `mid` here
+   |           ^^^^^           ----------- value is mutably borrowed by `mid` here
+   |           |
    |           value is borrowed by `a` here
 
 error: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:22
    |
 LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
-   |                      -----^^^-------------
-   |                      |       |           |
-   |                      |       |           value is moved into `c` here
+   |                      ^^^^^   ---------   - value is moved into `c` here
+   |                      |       |
    |                      |       value is mutably borrowed by `b` here
    |                      value is borrowed by `a` here
 
@@ -289,9 +258,8 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:28:30
    |
 LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
-   |                              ---------^^^-
-   |                              |           |
-   |                              |           value is moved into `c` here
+   |                              ^^^^^^^^^   - value is moved into `c` here
+   |                              |
    |                              value is mutably borrowed by `b` here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
index a0cb04a064e..24189d0615c 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.stderr
@@ -2,98 +2,80 @@ error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:26:9
    |
 LL |     let ref mut a @ ref mut b = U;
-   |         ---------^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:29:9
    |
 LL |     let ref mut a @ ref mut b = U;
-   |         ---------^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:33:9
    |
 LL |     let ref mut a @ ref mut b = U;
-   |         ---------^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:36:9
    |
 LL |     let ref mut a @ ref mut b = U;
-   |         ---------^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:39:9
    |
 LL |     let ref mut a @ ref mut b = U;
-   |         ---------^^^---------
-   |         |           |
-   |         |           value is mutably borrowed by `b` here
+   |         ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:44:9
    |
-LL |       let ref mut a @ (
-   |           ^--------
-   |           |
-   |  _________value is mutably borrowed by `a` here
-   | |
-LL | |
-LL | |         ref mut b,
-   | |         --------- value is mutably borrowed by `b` here
-LL | |         [
-LL | |             ref mut c,
-   | |             --------- value is mutably borrowed by `c` here
-LL | |             ref mut d,
-   | |             --------- value is mutably borrowed by `d` here
-LL | |             ref e,
-   | |             ----- value is borrowed by `e` here
-LL | |         ]
-LL | |     ) = (U, [U, U, U]);
-   | |_____^
+LL |     let ref mut a @ (
+   |         ^^^^^^^^^ value is mutably borrowed by `a` here
+LL |
+LL |         ref mut b,
+   |         --------- value is mutably borrowed by `b` here
+LL |         [
+LL |             ref mut c,
+   |             --------- value is mutably borrowed by `c` here
+LL |             ref mut d,
+   |             --------- value is mutably borrowed by `d` here
+LL |             ref e,
+   |             ----- value is borrowed by `e` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:54:9
    |
-LL |       let ref mut a @ (
-   |           ^--------
-   |           |
-   |  _________value is mutably borrowed by `a` here
-   | |
-LL | |
-LL | |             ref mut b,
-   | |             --------- value is mutably borrowed by `b` here
-LL | |             [
-LL | |                 ref mut c,
-   | |                 --------- value is mutably borrowed by `c` here
-LL | |                 ref mut d,
-   | |                 --------- value is mutably borrowed by `d` here
-LL | |                 ref e,
-   | |                 ----- value is borrowed by `e` here
-LL | |             ]
-LL | |         ) = (u(), [u(), u(), u()]);
-   | |_________^
+LL |     let ref mut a @ (
+   |         ^^^^^^^^^ value is mutably borrowed by `a` here
+LL |
+LL |             ref mut b,
+   |             --------- value is mutably borrowed by `b` here
+LL |             [
+LL |                 ref mut c,
+   |                 --------- value is mutably borrowed by `c` here
+LL |                 ref mut d,
+   |                 --------- value is mutably borrowed by `d` here
+LL |                 ref e,
+   |                 ----- value is borrowed by `e` here
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:64:9
    |
 LL |     let a @ (ref mut b, ref mut c) = (U, U);
-   |         -^^^^---------^^---------^
-   |         |    |          |
-   |         |    |          value borrowed here after move
+   |         ^    ---------  --------- value borrowed here after move
+   |         |    |
    |         |    value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `(U, U)` which does not implement the `Copy` trait
@@ -107,9 +89,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:67:9
    |
 LL |     let a @ (b, [c, d]) = &mut val; // Same as ^--
-   |         -^^^^-^^^-^^-^^
-   |         |    |   |  |
-   |         |    |   |  value borrowed here after move
+   |         ^    -   -  - value borrowed here after move
+   |         |    |   |
    |         |    |   value borrowed here after move
    |         |    value borrowed here after move
    |         value moved into `a` here
@@ -124,9 +105,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:70:9
    |
 LL |     let a @ &mut ref mut b = &mut U;
-   |         -^^^^^^^^---------
-   |         |        |
-   |         |        value borrowed here after move
+   |         ^        --------- value borrowed here after move
+   |         |
    |         value moved into `a` here
    |         move occurs because `a` has type `&mut U` which does not implement the `Copy` trait
    |
@@ -139,9 +119,8 @@ error: borrow of moved value
   --> $DIR/borrowck-pat-ref-mut-twice.rs:72:9
    |
 LL |     let a @ &mut (ref mut b, ref mut c) = &mut (U, U);
-   |         -^^^^^^^^^---------^^---------^
-   |         |         |          |
-   |         |         |          value borrowed here after move
+   |         ^         ---------  --------- value borrowed here after move
+   |         |         |
    |         |         value borrowed here after move
    |         value moved into `a` here
    |         move occurs because `a` has type `&mut (U, U)` which does not implement the `Copy` trait
@@ -155,117 +134,99 @@ error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:76:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |         ---------^^^^^^---------^
-   |         |              |
-   |         |              value is mutably borrowed by `b` here
+   |         ^^^^^^^^^      --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:76:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |                                     ---------^^^^^^^---------^
-   |                                     |               |
-   |                                     |               value is mutably borrowed by `b` here
+   |                                     ^^^^^^^^^       --------- value is mutably borrowed by `b` here
+   |                                     |
    |                                     value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |         ---------^^^^^^---------^
-   |         |              |
-   |         |              value is mutably borrowed by `b` here
+   |         ^^^^^^^^^      --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |                                     ---------^^^^^^^---------^
-   |                                     |               |
-   |                                     |               value is mutably borrowed by `b` here
+   |                                     ^^^^^^^^^       --------- value is mutably borrowed by `b` here
+   |                                     |
    |                                     value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:89:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |         ---------^^^^^^---------^
-   |         |              |
-   |         |              value is mutably borrowed by `b` here
+   |         ^^^^^^^^^      --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:89:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |                                     ---------^^^^^^^---------^
-   |                                     |               |
-   |                                     |               value is mutably borrowed by `b` here
+   |                                     ^^^^^^^^^       --------- value is mutably borrowed by `b` here
+   |                                     |
    |                                     value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:101:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |         ---------^^^^^^---------^
-   |         |              |
-   |         |              value is mutably borrowed by `b` here
+   |         ^^^^^^^^^      --------- value is mutably borrowed by `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:101:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |                                     ---------^^^^^^^---------^
-   |                                     |               |
-   |                                     |               value is mutably borrowed by `b` here
+   |                                     ^^^^^^^^^       --------- value is mutably borrowed by `b` here
+   |                                     |
    |                                     value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11
    |
 LL |     fn f1(ref mut a @ ref mut b: U) {}
-   |           ---------^^^---------
-   |           |           |
-   |           |           value is mutably borrowed by `b` here
+   |           ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |           |
    |           value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:10:11
    |
 LL |     fn f2(ref mut a @ ref mut b: U) {}
-   |           ---------^^^---------
-   |           |           |
-   |           |           value is mutably borrowed by `b` here
+   |           ^^^^^^^^^   --------- value is mutably borrowed by `b` here
+   |           |
    |           value is mutably borrowed by `a` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:13:9
    |
-LL |           ref mut a @ [
-   |           ^--------
-   |           |
-   |  _________value is mutably borrowed by `a` here
-   | |
-LL | |
-LL | |             [ref b @ .., _],
-   | |              ---------- value is borrowed by `b` here
-LL | |             [_, ref mut mid @ ..],
-   | |                 ---------------- value is mutably borrowed by `mid` here
-LL | |             ..,
-LL | |             [..],
-LL | |         ] : [[U; 4]; 5]
-   | |_________^
+LL |         ref mut a @ [
+   |         ^^^^^^^^^ value is mutably borrowed by `a` here
+LL |
+LL |             [ref b @ .., _],
+   |              ----- value is borrowed by `b` here
+LL |             [_, ref mut mid @ ..],
+   |                 ----------- value is mutably borrowed by `mid` here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:21:22
    |
 LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
-   |                      ---------^^^-------------
-   |                      |           |           |
-   |                      |           |           value is moved into `c` here
+   |                      ^^^^^^^^^   ---------   - value is moved into `c` here
+   |                      |           |
    |                      |           value is mutably borrowed by `b` here
    |                      value is mutably borrowed by `a` here
 
@@ -273,9 +234,8 @@ error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-ref-mut-twice.rs:21:34
    |
 LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
-   |                                  ---------^^^-
-   |                                  |           |
-   |                                  |           value is moved into `c` here
+   |                                  ^^^^^^^^^   - value is moved into `c` here
+   |                                  |
    |                                  value is mutably borrowed by `b` here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
diff --git a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
index 73ebbf48118..36515c1a29b 100644
--- a/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
+++ b/tests/ui/pattern/bindings-after-at/default-binding-modes-both-sides-independent.stderr
@@ -2,36 +2,32 @@ error: cannot move out of value because it is borrowed
   --> $DIR/default-binding-modes-both-sides-independent.rs:26:9
    |
 LL |     let ref a @ b = NotCopy;
-   |         -----^^^-
-   |         |       |
-   |         |       value is moved into `b` here
+   |         ^^^^^   - value is moved into `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/default-binding-modes-both-sides-independent.rs:29:9
    |
 LL |     let ref mut a @ b = NotCopy;
-   |         ---------^^^-
-   |         |           |
-   |         |           value is moved into `b` here
+   |         ^^^^^^^^^   - value is moved into `b` here
+   |         |
    |         value is mutably borrowed by `a` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/default-binding-modes-both-sides-independent.rs:34:12
    |
 LL |         Ok(ref a @ b) | Err(b @ ref a) => {
-   |            -----^^^-
-   |            |       |
-   |            |       value is moved into `b` here
+   |            ^^^^^   - value is moved into `b` here
+   |            |
    |            value is borrowed by `a` here
 
 error: borrow of moved value
   --> $DIR/default-binding-modes-both-sides-independent.rs:34:29
    |
 LL |         Ok(ref a @ b) | Err(b @ ref a) => {
-   |                             -^^^-----
-   |                             |   |
-   |                             |   value borrowed here after move
+   |                             ^   ----- value borrowed here after move
+   |                             |
    |                             value moved into `b` here
    |                             move occurs because `b` has type `NotCopy` which does not implement the `Copy` trait
    |
@@ -44,9 +40,8 @@ error: cannot move out of value because it is borrowed
   --> $DIR/default-binding-modes-both-sides-independent.rs:42:9
    |
 LL |         ref a @ b => {
-   |         -----^^^-
-   |         |       |
-   |         |       value is moved into `b` here
+   |         ^^^^^   - value is moved into `b` here
+   |         |
    |         value is borrowed by `a` here
 
 error[E0382]: borrow of moved value
diff --git a/tests/ui/pattern/issue-106552.stderr b/tests/ui/pattern/issue-106552.stderr
index ed5d40c0968..96f3d68458f 100644
--- a/tests/ui/pattern/issue-106552.stderr
+++ b/tests/ui/pattern/issue-106552.stderr
@@ -9,8 +9,8 @@ LL |     let 5 = 6;
    = note: the matched value is of type `i32`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let 5 = 6 { todo!() }
-   |     ++           ~~~~~~~~~~~
+LL |     if let 5 = 6 { todo!() };
+   |     ++           +++++++++++
 help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
    |
 LL |     let _5 = 6;
@@ -20,7 +20,7 @@ error[E0005]: refutable pattern in local binding
   --> $DIR/issue-106552.rs:5:9
    |
 LL |     let x @ 5 = 6;
-   |         ^^^^^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered
+   |         ^ patterns `i32::MIN..=4_i32` and `6_i32..=i32::MAX` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
diff --git a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr
index 54ecc24981f..62c90b638d7 100644
--- a/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr
+++ b/tests/ui/pattern/issue-68393-let-pat-assoc-constant.stderr
@@ -1,15 +1,15 @@
 error[E0158]: associated consts cannot be referenced in patterns
-  --> $DIR/issue-68393-let-pat-assoc-constant.rs:20:40
-   |
-LL | pub fn test<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
-   |                                        ^^^^
-
-error[E0158]: associated consts cannot be referenced in patterns
   --> $DIR/issue-68393-let-pat-assoc-constant.rs:22:9
    |
 LL |     let A::X = arg;
    |         ^^^^
 
+error[E0158]: associated consts cannot be referenced in patterns
+  --> $DIR/issue-68393-let-pat-assoc-constant.rs:20:40
+   |
+LL | pub fn test<A: Foo, B: Foo>(arg: EFoo, A::X: EFoo) {
+   |                                        ^^^^
+
 error: aborting due to 2 previous errors
 
 For more information about this error, try `rustc --explain E0158`.
diff --git a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed
index b28dce88105..b469fade3ea 100644
--- a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed
+++ b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.fixed
@@ -4,7 +4,7 @@ fn main() {
     match Some(1) { //~ ERROR non-exhaustive patterns: `None` not covered
         Some(1) => {}
         // hello
-        Some(_) => {}
+        Some(_) => {},
         None => todo!()
     }
 }
diff --git a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr
index 2a016048f2f..5f2c89246e3 100644
--- a/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr
+++ b/tests/ui/pattern/suggest-adding-appropriate-missing-pattern-excluding-comments.stderr
@@ -12,7 +12,7 @@ note: `Option<i32>` defined here
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         Some(_) => {}
+LL ~         Some(_) => {},
 LL +         None => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr
index 08e3d76b538..3f0b4a9f26a 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.stderr
+++ b/tests/ui/pattern/usefulness/consts-opaque.stderr
@@ -7,21 +7,6 @@ LL |         FOO => {}
    = 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:32:9
-   |
-LL |         FOO => {}
-   |         --- matches any value
-LL |
-LL |         _ => {} // should not be emitting unreachable warning
-   |         ^ unreachable pattern
-   |
-note: the lint level is defined here
-  --> $DIR/consts-opaque.rs:6:9
-   |
-LL | #![deny(unreachable_patterns)]
-   |         ^^^^^^^^^^^^^^^^^^^^
-
 error: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
   --> $DIR/consts-opaque.rs:37:9
    |
@@ -31,15 +16,6 @@ LL |         FOO_REF => {}
    = 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:39:9
-   |
-LL |         FOO_REF => {}
-   |         ------- matches any value
-LL |
-LL |         Foo(_) => {} // should not be emitting unreachable warning
-   |         ^^^^^^ unreachable pattern
-
 warning: to use a constant of type `Foo` in a pattern, `Foo` must be annotated with `#[derive(PartialEq, Eq)]`
   --> $DIR/consts-opaque.rs:45:9
    |
@@ -61,6 +37,84 @@ LL |         BAR => {} // should not be emitting unreachable warning
    = 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: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/consts-opaque.rs:61:9
+   |
+LL |         BAR => {}
+   |         ^^^
+   |
+   = 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: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/consts-opaque.rs:70:9
+   |
+LL |         BAR => {}
+   |         ^^^
+   |
+   = 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: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/consts-opaque.rs:72:9
+   |
+LL |         BAR => {} // should not be emitting unreachable warning
+   |         ^^^
+   |
+   = 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: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/consts-opaque.rs:80:9
+   |
+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: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/consts-opaque.rs:90:9
+   |
+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: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
+  --> $DIR/consts-opaque.rs:97:9
+   |
+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:32:9
+   |
+LL |         FOO => {}
+   |         --- matches any value
+LL |
+LL |         _ => {} // should not be emitting unreachable warning
+   |         ^ 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:39:9
+   |
+LL |         FOO_REF => {}
+   |         ------- matches any value
+LL |
+LL |         Foo(_) => {} // should not be emitting unreachable warning
+   |         ^^^^^^ unreachable pattern
+
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:53:9
    |
@@ -78,15 +132,6 @@ LL |         Bar => {}
 LL |         _ => {}
    |         ^ unreachable pattern
 
-error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:61:9
-   |
-LL |         BAR => {}
-   |         ^^^
-   |
-   = 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:63:9
    |
@@ -105,24 +150,6 @@ LL |         BAR => {}
 LL |         _ => {}
    |         ^ unreachable pattern
 
-error: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:70:9
-   |
-LL |         BAR => {}
-   |         ^^^
-   |
-   = 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: to use a constant of type `Bar` in a pattern, `Bar` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:72:9
-   |
-LL |         BAR => {} // should not be emitting unreachable warning
-   |         ^^^
-   |
-   = 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:72:9
    |
@@ -141,15 +168,6 @@ LL |         BAR => {}
 LL |         _ => {} // should not be emitting unreachable warning
    |         ^ unreachable pattern
 
-error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:80:9
-   |
-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:82:9
    |
@@ -168,15 +186,6 @@ LL |         BAZ => {}
 LL |         _ => {}
    |         ^ unreachable pattern
 
-error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:90:9
-   |
-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:92:9
    |
@@ -186,15 +195,6 @@ LL |
 LL |         _ => {}
    |         ^ unreachable pattern
 
-error: to use a constant of type `Baz` in a pattern, `Baz` must be annotated with `#[derive(PartialEq, Eq)]`
-  --> $DIR/consts-opaque.rs:97:9
-   |
-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:99:9
    |
diff --git a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
index 17e1a2304a1..ff29de03d6b 100644
--- a/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
+++ b/tests/ui/pattern/usefulness/doc-hidden-non-exhaustive.stderr
@@ -12,7 +12,7 @@ LL | pub enum HiddenEnum {
    = note: the matched value is of type `HiddenEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         HiddenEnum::B => {}
+LL ~         HiddenEnum::B => {},
 LL +         _ => todo!()
    |
 
@@ -33,7 +33,7 @@ LL |     B,
    = note: the matched value is of type `HiddenEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         HiddenEnum::C => {}
+LL ~         HiddenEnum::C => {},
 LL +         HiddenEnum::B => todo!()
    |
 
@@ -54,7 +54,7 @@ LL |     B,
    = note: the matched value is of type `HiddenEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         HiddenEnum::A => {}
+LL ~         HiddenEnum::A => {},
 LL +         HiddenEnum::B | _ => todo!()
    |
 
@@ -72,7 +72,7 @@ note: `Option<HiddenEnum>` defined here
    = note: the matched value is of type `Option<HiddenEnum>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         Some(HiddenEnum::A) => {}
+LL ~         Some(HiddenEnum::A) => {},
 LL +         Some(HiddenEnum::B) | Some(_) => todo!()
    |
 
@@ -93,7 +93,7 @@ LL |     C,
    = note: the matched value is of type `InCrate`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         InCrate::B => {}
+LL ~         InCrate::B => {},
 LL +         InCrate::C => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
index 5e12bc1d22f..5a145efce94 100644
--- a/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.exhaustive_patterns.stderr
@@ -162,7 +162,7 @@ LL |     match_guarded_arm!(0u8);
    = note: the matched value is of type `u8`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             _ => todo!()
    |
 
@@ -180,7 +180,7 @@ LL | struct NonEmptyStruct1;
    = note: the matched value is of type `NonEmptyStruct1`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyStruct1 => todo!()
    |
 
@@ -198,7 +198,7 @@ LL | struct NonEmptyStruct2(bool);
    = note: the matched value is of type `NonEmptyStruct2`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyStruct2(_) => todo!()
    |
 
@@ -216,7 +216,7 @@ LL | union NonEmptyUnion1 {
    = note: the matched value is of type `NonEmptyUnion1`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyUnion1 { .. } => todo!()
    |
 
@@ -234,7 +234,7 @@ LL | union NonEmptyUnion2 {
    = note: the matched value is of type `NonEmptyUnion2`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyUnion2 { .. } => todo!()
    |
 
@@ -254,7 +254,7 @@ LL |     Foo(bool),
    = note: the matched value is of type `NonEmptyEnum1`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyEnum1::Foo(_) => todo!()
    |
 
@@ -276,7 +276,7 @@ LL |     Bar,
    = note: the matched value is of type `NonEmptyEnum2`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
    |
 
@@ -294,7 +294,7 @@ LL | enum NonEmptyEnum5 {
    = note: the matched value is of type `NonEmptyEnum5`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/empty-match.normal.stderr b/tests/ui/pattern/usefulness/empty-match.normal.stderr
index 5e12bc1d22f..5a145efce94 100644
--- a/tests/ui/pattern/usefulness/empty-match.normal.stderr
+++ b/tests/ui/pattern/usefulness/empty-match.normal.stderr
@@ -162,7 +162,7 @@ LL |     match_guarded_arm!(0u8);
    = note: the matched value is of type `u8`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             _ => todo!()
    |
 
@@ -180,7 +180,7 @@ LL | struct NonEmptyStruct1;
    = note: the matched value is of type `NonEmptyStruct1`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyStruct1 => todo!()
    |
 
@@ -198,7 +198,7 @@ LL | struct NonEmptyStruct2(bool);
    = note: the matched value is of type `NonEmptyStruct2`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyStruct2(_) => todo!()
    |
 
@@ -216,7 +216,7 @@ LL | union NonEmptyUnion1 {
    = note: the matched value is of type `NonEmptyUnion1`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyUnion1 { .. } => todo!()
    |
 
@@ -234,7 +234,7 @@ LL | union NonEmptyUnion2 {
    = note: the matched value is of type `NonEmptyUnion2`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyUnion2 { .. } => todo!()
    |
 
@@ -254,7 +254,7 @@ LL |     Foo(bool),
    = note: the matched value is of type `NonEmptyEnum1`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyEnum1::Foo(_) => todo!()
    |
 
@@ -276,7 +276,7 @@ LL |     Bar,
    = note: the matched value is of type `NonEmptyEnum2`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             NonEmptyEnum2::Foo(_) | NonEmptyEnum2::Bar => todo!()
    |
 
@@ -294,7 +294,7 @@ LL | enum NonEmptyEnum5 {
    = note: the matched value is of type `NonEmptyEnum5`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~             _ if false => {}
+LL ~             _ if false => {},
 LL +             _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/floats.stderr b/tests/ui/pattern/usefulness/floats.stderr
index c926e50b358..d66d4ba298b 100644
--- a/tests/ui/pattern/usefulness/floats.stderr
+++ b/tests/ui/pattern/usefulness/floats.stderr
@@ -7,7 +7,7 @@ LL |     match 0.0 {
    = note: the matched value is of type `f64`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~       0.0..=1.0 => {}
+LL ~       0.0..=1.0 => {},
 LL +       _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/guards.stderr b/tests/ui/pattern/usefulness/guards.stderr
index 0c1563c160c..fc6748958de 100644
--- a/tests/ui/pattern/usefulness/guards.stderr
+++ b/tests/ui/pattern/usefulness/guards.stderr
@@ -7,7 +7,7 @@ LL |     match 0u8 {
    = note: the matched value is of type `u8`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         128 ..= 255 if true => {}
+LL ~         128 ..= 255 if true => {},
 LL +         128_u8..=u8::MAX => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
index f30ba05dff9..b585de20629 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/exhaustiveness.stderr
@@ -91,7 +91,7 @@ LL |     match 0i8 {
    = note: the matched value is of type `i8`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         1 ..= i8::MAX => {}
+LL ~         1 ..= i8::MAX => {},
 LL +         0_i8 => todo!()
    |
 
@@ -140,7 +140,7 @@ LL |     match (0u8, true) {
    = note: the matched value is of type `(u8, bool)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         (0 ..= 255, true) => {}
+LL ~         (0 ..= 255, true) => {},
 LL +         (126_u8..=127_u8, false) => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
index e3eb98ccdcd..0e0f0c3e11e 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/pointer-sized-int.deny.stderr
@@ -9,7 +9,7 @@ LL |     match 0usize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         0 ..= usize::MAX => {}
+LL ~         0 ..= usize::MAX => {},
 LL +         _ => todo!()
    |
 
@@ -24,7 +24,7 @@ LL |     match 0isize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         isize::MIN ..= isize::MAX => {}
+LL ~         isize::MIN ..= isize::MAX => {},
 LL +         _ => todo!()
    |
 
@@ -147,7 +147,7 @@ LL |     match 0isize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         1 ..= isize::MAX => {}
+LL ~         1 ..= isize::MAX => {},
 LL +         _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
index 30492c98206..b80411b26b0 100644
--- a/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
+++ b/tests/ui/pattern/usefulness/integer-ranges/precise_pointer_matching-message.stderr
@@ -9,7 +9,7 @@ LL |     match 0usize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `usize` matching
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         0..=usize::MAX => {}
+LL ~         0..=usize::MAX => {},
 LL +         _ => todo!()
    |
 
@@ -24,7 +24,7 @@ LL |     match 0isize {
    = help: add `#![feature(precise_pointer_size_matching)]` to the crate attributes to enable precise `isize` matching
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         isize::MIN..=isize::MAX => {}
+LL ~         isize::MIN..=isize::MAX => {},
 LL +         _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/issue-2111.stderr b/tests/ui/pattern/usefulness/issue-2111.stderr
index 01890b73cbd..7f7c5a0f19d 100644
--- a/tests/ui/pattern/usefulness/issue-2111.stderr
+++ b/tests/ui/pattern/usefulness/issue-2111.stderr
@@ -7,7 +7,7 @@ LL |     match (a, b) {
    = note: the matched value is of type `(Option<usize>, Option<usize>)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         (Some(_), None) | (None, Some(_)) => {}
+LL ~         (Some(_), None) | (None, Some(_)) => {},
 LL +         (None, None) | (Some(_), Some(_)) => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/issue-30240.stderr b/tests/ui/pattern/usefulness/issue-30240.stderr
index 759fdeafe4e..ff755d681ac 100644
--- a/tests/ui/pattern/usefulness/issue-30240.stderr
+++ b/tests/ui/pattern/usefulness/issue-30240.stderr
@@ -7,7 +7,7 @@ LL |     match "world" {
    = note: the matched value is of type `&str`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         "hello" => {}
+LL ~         "hello" => {},
 LL +         &_ => todo!()
    |
 
@@ -20,7 +20,7 @@ LL |     match "world" {
    = note: the matched value is of type `&str`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         "hello" => {}
+LL ~         "hello" => {},
 LL +         &_ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/issue-35609.stderr b/tests/ui/pattern/usefulness/issue-35609.stderr
index 12113957d63..6d5e2f410bc 100644
--- a/tests/ui/pattern/usefulness/issue-35609.stderr
+++ b/tests/ui/pattern/usefulness/issue-35609.stderr
@@ -7,7 +7,7 @@ LL |     match (A, ()) {
    = note: the matched value is of type `(Enum, ())`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~         (A, _) => {}
+LL ~         (A, _) => {},
 LL +         _ => todo!()
    |
 
@@ -20,7 +20,7 @@ LL |     match (A, A) {
    = note: the matched value is of type `(Enum, Enum)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~         (_, A) => {}
+LL ~         (_, A) => {},
 LL +         _ => todo!()
    |
 
@@ -33,7 +33,7 @@ LL |     match ((A, ()), ()) {
    = note: the matched value is of type `((Enum, ()), ())`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~         ((A, ()), _) => {}
+LL ~         ((A, ()), _) => {},
 LL +         _ => todo!()
    |
 
@@ -46,7 +46,7 @@ LL |     match ((A, ()), A) {
    = note: the matched value is of type `((Enum, ()), Enum)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~         ((A, ()), _) => {}
+LL ~         ((A, ()), _) => {},
 LL +         _ => todo!()
    |
 
@@ -59,7 +59,7 @@ LL |     match ((A, ()), ()) {
    = note: the matched value is of type `((Enum, ()), ())`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~         ((A, _), _) => {}
+LL ~         ((A, _), _) => {},
 LL +         _ => todo!()
    |
 
@@ -77,7 +77,7 @@ LL | struct S(Enum, ());
    = note: the matched value is of type `S`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~         S(A, _) => {}
+LL ~         S(A, _) => {},
 LL +         _ => todo!()
    |
 
@@ -95,7 +95,7 @@ LL | struct Sd { x: Enum, y: () }
    = note: the matched value is of type `Sd`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~         Sd { x: A, y: _ } => {}
+LL ~         Sd { x: A, y: _ } => {},
 LL +         _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/issue-3601.stderr b/tests/ui/pattern/usefulness/issue-3601.stderr
index 59d7bcd4b5e..2f6b167d4f8 100644
--- a/tests/ui/pattern/usefulness/issue-3601.stderr
+++ b/tests/ui/pattern/usefulness/issue-3601.stderr
@@ -9,7 +9,7 @@ note: `Box<ElementKind>` defined here
    = note: the matched value is of type `Box<ElementKind>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~             box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true }
+LL ~             box ElementKind::HTMLImageElement(ref d) if d.image.is_some() => { true },
 LL +             box _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/issue-50900.stderr b/tests/ui/pattern/usefulness/issue-50900.stderr
index 348246d28aa..7880c892567 100644
--- a/tests/ui/pattern/usefulness/issue-50900.stderr
+++ b/tests/ui/pattern/usefulness/issue-50900.stderr
@@ -12,7 +12,7 @@ LL | pub struct Tag(pub Context, pub u16);
    = note: the matched value is of type `Tag`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         Tag::ExifIFDPointer => {}
+LL ~         Tag::ExifIFDPointer => {},
 LL +         Tag(Context::Exif, _) => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/issue-56379.stderr b/tests/ui/pattern/usefulness/issue-56379.stderr
index 6eed6bfae4c..b3e40b99239 100644
--- a/tests/ui/pattern/usefulness/issue-56379.stderr
+++ b/tests/ui/pattern/usefulness/issue-56379.stderr
@@ -18,7 +18,7 @@ LL |     C(bool),
    = note: the matched value is of type `Foo`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         Foo::C(true) => {}
+LL ~         Foo::C(true) => {},
 LL +         Foo::A(false) | Foo::B(false) | Foo::C(false) => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
index a90f32f7aeb..3c482eef210 100644
--- a/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
+++ b/tests/ui/pattern/usefulness/match-byte-array-patterns-2.stderr
@@ -7,7 +7,7 @@ LL |     match buf {
    = note: the matched value is of type `&[u8; 4]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         b"AAAA" => {}
+LL ~         b"AAAA" => {},
 LL +         &[0_u8..=64_u8, _, _, _] | &[66_u8..=u8::MAX, _, _, _] => todo!()
    |
 
@@ -20,7 +20,7 @@ LL |     match buf {
    = note: the matched value is of type `&[u8]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern as shown, or multiple match arms
    |
-LL ~         b"AAAA" => {}
+LL ~         b"AAAA" => {},
 LL +         _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/match-privately-empty.stderr b/tests/ui/pattern/usefulness/match-privately-empty.stderr
index 86f75d15cfd..45352f09417 100644
--- a/tests/ui/pattern/usefulness/match-privately-empty.stderr
+++ b/tests/ui/pattern/usefulness/match-privately-empty.stderr
@@ -12,7 +12,7 @@ note: `Option<Private>` defined here
    = note: the matched value is of type `Option<Private>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         }) => {}
+LL ~         }) => {},
 LL +         Some(Private { misc: true, .. }) => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/match-slice-patterns.stderr b/tests/ui/pattern/usefulness/match-slice-patterns.stderr
index 961dd590119..63d1f38e9db 100644
--- a/tests/ui/pattern/usefulness/match-slice-patterns.stderr
+++ b/tests/ui/pattern/usefulness/match-slice-patterns.stderr
@@ -7,7 +7,7 @@ LL |     match list {
    = note: the matched value is of type `&[Option<()>]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         &[.., Some(_), _] => {}
+LL ~         &[.., Some(_), _] => {},
 LL ~         &[_, Some(_), .., None, _] => todo!(),
    |
 
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
index 769d4070fb5..8489e2f14b8 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
+++ b/tests/ui/pattern/usefulness/non-exhaustive-defined-here.stderr
@@ -18,7 +18,7 @@ LL |     C
    = note: the matched value is of type `E`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         E::A => {}
+LL ~         E::A => {},
 LL +         E::B | E::C => todo!()
    |
 
@@ -44,8 +44,8 @@ LL |     C
    = note: the matched value is of type `E`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let E::A = e { todo!() }
-   |     ++              ~~~~~~~~~~~
+LL |     if let E::A = e { todo!() };
+   |     ++              +++++++++++
 
 error[E0004]: non-exhaustive patterns: `&E::B` and `&E::C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:50:11
@@ -67,7 +67,7 @@ LL |     C
    = note: the matched value is of type `&E`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         E::A => {}
+LL ~         E::A => {},
 LL +         &E::B | &E::C => todo!()
    |
 
@@ -93,8 +93,8 @@ LL |     C
    = note: the matched value is of type `&E`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let E::A = e { todo!() }
-   |     ++              ~~~~~~~~~~~
+LL |     if let E::A = e { todo!() };
+   |     ++              +++++++++++
 
 error[E0004]: non-exhaustive patterns: `&&mut &E::B` and `&&mut &E::C` not covered
   --> $DIR/non-exhaustive-defined-here.rs:66:11
@@ -116,7 +116,7 @@ LL |     C
    = note: the matched value is of type `&&mut &E`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         E::A => {}
+LL ~         E::A => {},
 LL +         &&mut &E::B | &&mut &E::C => todo!()
    |
 
@@ -142,8 +142,8 @@ LL |     C
    = note: the matched value is of type `&&mut &E`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let E::A = e { todo!() }
-   |     ++              ~~~~~~~~~~~
+LL |     if let E::A = e { todo!() };
+   |     ++              +++++++++++
 
 error[E0004]: non-exhaustive patterns: `Opt::None` not covered
   --> $DIR/non-exhaustive-defined-here.rs:92:11
@@ -162,7 +162,7 @@ LL |     None,
    = note: the matched value is of type `Opt`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         Opt::Some(ref _x) => {}
+LL ~         Opt::Some(ref _x) => {},
 LL +         Opt::None => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
index 44f32742110..98e417a17f8 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
+++ b/tests/ui/pattern/usefulness/non-exhaustive-match-nested.stderr
@@ -25,7 +25,7 @@ LL | enum T { A(U), B }
    = note: the matched value is of type `T`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         T::B => { panic!("goodbye"); }
+LL ~         T::B => { panic!("goodbye"); },
 LL +         T::A(U::C) => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr
index e2260f50bfe..e59e8885e1a 100644
--- a/tests/ui/pattern/usefulness/non-exhaustive-match.stderr
+++ b/tests/ui/pattern/usefulness/non-exhaustive-match.stderr
@@ -24,7 +24,7 @@ LL |     match true {
    = note: the matched value is of type `bool`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~       true => {}
+LL ~       true => {},
 LL +       false => todo!()
    |
 
@@ -42,7 +42,7 @@ note: `Option<i32>` defined here
    = note: the matched value is of type `Option<i32>`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~       None => {}
+LL ~       None => {},
 LL +       Some(_) => todo!()
    |
 
@@ -55,7 +55,7 @@ LL |     match (2, 3, 4) {
    = note: the matched value is of type `(i32, i32, i32)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~       (_, _, 4) => {}
+LL ~       (_, _, 4) => {},
 LL +       (_, _, i32::MIN..=3_i32) | (_, _, 5_i32..=i32::MAX) => todo!()
    |
 
@@ -68,7 +68,7 @@ LL |     match (T::A, T::A) {
    = note: the matched value is of type `(T, T)`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~       (T::B, T::A) => {}
+LL ~       (T::B, T::A) => {},
 LL +       (T::A, T::A) | (T::B, T::B) => todo!()
    |
 
@@ -86,7 +86,7 @@ LL | enum T { A, B }
    = note: the matched value is of type `T`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~       T::A => {}
+LL ~       T::A => {},
 LL +       T::B => todo!()
    |
 
@@ -99,7 +99,7 @@ LL |     match *vec {
    = note: the matched value is of type `[Option<isize>]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [None] => {}
+LL ~         [None] => {},
 LL +         [] => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr
index c518de47740..beb51a4d450 100644
--- a/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr
+++ b/tests/ui/pattern/usefulness/refutable-pattern-errors.stderr
@@ -17,8 +17,8 @@ LL |     let (1, (Some(1), 2..=3)) = (1, (None, 2));
    = note: the matched value is of type `(i32, (Option<i32>, i32))`
 help: you might want to use `if let` to ignore the variants that aren't matched
    |
-LL |     if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() }
-   |     ++                                            ~~~~~~~~~~~
+LL |     if let (1, (Some(1), 2..=3)) = (1, (None, 2)) { todo!() };
+   |     ++                                            +++++++++++
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
index 55f0b2319fb..ab3f6f69fb1 100644
--- a/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
+++ b/tests/ui/pattern/usefulness/refutable-pattern-in-fn-arg.stderr
@@ -5,6 +5,10 @@ LL |     let f = |3: isize| println!("hello");
    |              ^ pattern `_` not covered
    |
    = note: the matched value is of type `isize`
+help: alternatively, you could prepend the pattern with an underscore to define a new named variable; identifiers cannot begin with digits
+   |
+LL |     let f = |_3: isize| println!("hello");
+   |              +
 
 error: aborting due to previous error
 
diff --git a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
index 5d1e170ae6c..fb6ecda3c4d 100644
--- a/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
+++ b/tests/ui/pattern/usefulness/slice-patterns-exhaustiveness.stderr
@@ -7,7 +7,7 @@ LL |     match s2 {
    = note: the matched value is of type `&[bool; 2]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [true, .., true] => {}
+LL ~         [true, .., true] => {},
 LL +         &[false, _] => todo!()
    |
 
@@ -20,7 +20,7 @@ LL |     match s3 {
    = note: the matched value is of type `&[bool; 3]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [true, .., true] => {}
+LL ~         [true, .., true] => {},
 LL +         &[false, ..] => todo!()
    |
 
@@ -33,7 +33,7 @@ LL |     match s10 {
    = note: the matched value is of type `&[bool; 10]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [true, .., true] => {}
+LL ~         [true, .., true] => {},
 LL +         &[false, ..] => todo!()
    |
 
@@ -46,7 +46,7 @@ LL |     match s2 {
    = note: the matched value is of type `&[bool; 2]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [.., false] => {}
+LL ~         [.., false] => {},
 LL +         &[false, true] => todo!()
    |
 
@@ -59,7 +59,7 @@ LL |     match s3 {
    = note: the matched value is of type `&[bool; 3]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [.., false] => {}
+LL ~         [.., false] => {},
 LL +         &[false, .., true] => todo!()
    |
 
@@ -72,7 +72,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [.., false] => {}
+LL ~         [.., false] => {},
 LL +         &[false, .., true] => todo!()
    |
 
@@ -85,7 +85,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [] => {}
+LL ~         [] => {},
 LL +         &[_, ..] => todo!()
    |
 
@@ -98,7 +98,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [_] => {}
+LL ~         [_] => {},
 LL +         &[_, _, ..] => todo!()
    |
 
@@ -111,7 +111,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [true, ..] => {}
+LL ~         [true, ..] => {},
 LL +         &[false, ..] => todo!()
    |
 
@@ -124,7 +124,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [true, ..] => {}
+LL ~         [true, ..] => {},
 LL +         &[false, _, ..] => todo!()
    |
 
@@ -137,7 +137,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [.., true] => {}
+LL ~         [.., true] => {},
 LL +         &[_, .., false] => todo!()
    |
 
@@ -150,7 +150,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [.., false] => {}
+LL ~         [.., false] => {},
 LL +         &[_, _, .., true] => todo!()
    |
 
@@ -163,7 +163,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [false, .., false] => {}
+LL ~         [false, .., false] => {},
 LL +         &[true, _, .., _] => todo!()
    |
 
@@ -176,7 +176,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         &[true] => {}
+LL ~         &[true] => {},
 LL +         &[] | &[_, _, ..] => todo!()
    |
 
@@ -189,7 +189,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         CONST => {}
+LL ~         CONST => {},
 LL +         &[] | &[_, _, ..] => todo!()
    |
 
@@ -202,7 +202,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         &[false] => {}
+LL ~         &[false] => {},
 LL +         &[] | &[_, _, ..] => todo!()
    |
 
@@ -215,7 +215,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         CONST => {}
+LL ~         CONST => {},
 LL +         &[] | &[_, _, ..] => todo!()
    |
 
@@ -228,7 +228,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         CONST => {}
+LL ~         CONST => {},
 LL +         &[_, _, ..] => todo!()
    |
 
@@ -241,7 +241,7 @@ LL |     match s {
    = note: the matched value is of type `&[bool]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         &[_, _, ..] => {}
+LL ~         &[_, _, ..] => {},
 LL +         &[false] => todo!()
    |
 
@@ -254,7 +254,7 @@ LL |     match s1 {
    = note: the matched value is of type `&[bool; 1]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         CONST1 => {}
+LL ~         CONST1 => {},
 LL +         &[false] => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr
index 7b8588a3c73..f944c25a905 100644
--- a/tests/ui/pattern/usefulness/stable-gated-patterns.stderr
+++ b/tests/ui/pattern/usefulness/stable-gated-patterns.stderr
@@ -15,7 +15,7 @@ LL |     Stable2,
    = note: the matched value is of type `UnstableEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern, a match arm with multiple or-patterns as shown, or multiple match arms
    |
-LL ~         UnstableEnum::Stable => {}
+LL ~         UnstableEnum::Stable => {},
 LL +         UnstableEnum::Stable2 | _ => todo!()
    |
 
@@ -33,7 +33,7 @@ LL | pub enum UnstableEnum {
    = note: the matched value is of type `UnstableEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         UnstableEnum::Stable2 => {}
+LL ~         UnstableEnum::Stable2 => {},
 LL +         _ => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
index 85c97be29d6..22425aa0dd4 100644
--- a/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
+++ b/tests/ui/pattern/usefulness/struct-like-enum-nonexhaustive.stderr
@@ -14,7 +14,7 @@ LL |     B { x: Option<isize> },
    = note: the matched value is of type `A`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         A::B { x: None } => {}
+LL ~         A::B { x: None } => {},
 LL +         A::B { x: Some(_) } => todo!()
    |
 
diff --git a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr
index 6dc9a405839..d776249b231 100644
--- a/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr
+++ b/tests/ui/pattern/usefulness/unstable-gated-patterns.stderr
@@ -15,7 +15,7 @@ LL |     Unstable,
    = note: the matched value is of type `UnstableEnum`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         UnstableEnum::Stable2 => {}
+LL ~         UnstableEnum::Stable2 => {},
 LL +         UnstableEnum::Unstable => todo!()
    |
 
diff --git a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs
index d02caff1feb..206f05d0d3c 100644
--- a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs
+++ b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.rs
@@ -4,10 +4,8 @@ fn main() {
     match 0u8 {
         251..257 => {}
         //~^ ERROR literal out of range
-        //~| ERROR literal out of range
         251..=256 => {}
         //~^ ERROR literal out of range
-        //~| ERROR literal out of range
         _ => {}
     }
 }
diff --git a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr
index 7b8309b9bc2..4f3f9d1eb3a 100644
--- a/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr
+++ b/tests/ui/range/range-pattern-out-of-bounds-issue-68972.stderr
@@ -5,22 +5,10 @@ LL |         251..257 => {}
    |              ^^^ this value doesn't fit in `u8` whose maximum value is `255`
 
 error: literal out of range for `u8`
-  --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:8:15
+  --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:7:15
    |
 LL |         251..=256 => {}
    |               ^^^ this value doesn't fit in `u8` whose maximum value is `255`
 
-error: literal out of range for `u8`
-  --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:5:14
-   |
-LL |         251..257 => {}
-   |              ^^^ this value doesn't fit in `u8` whose maximum value is `255`
-
-error: literal out of range for `u8`
-  --> $DIR/range-pattern-out-of-bounds-issue-68972.rs:8:15
-   |
-LL |         251..=256 => {}
-   |               ^^^ this value doesn't fit in `u8` whose maximum value is `255`
-
-error: aborting due to 4 previous errors
+error: aborting due to 2 previous errors
 
diff --git a/tests/ui/rfc-2005-default-binding-mode/slice.stderr b/tests/ui/rfc-2005-default-binding-mode/slice.stderr
index 60c1f5420f6..5b51dc5acc4 100644
--- a/tests/ui/rfc-2005-default-binding-mode/slice.stderr
+++ b/tests/ui/rfc-2005-default-binding-mode/slice.stderr
@@ -7,7 +7,7 @@ LL |     match sl {
    = note: the matched value is of type `&[u8]`
 help: ensure that all possible cases are being handled by adding a match arm with a wildcard pattern or an explicit pattern as shown
    |
-LL ~         [first, remainder @ ..] => {}
+LL ~         [first, remainder @ ..] => {},
 LL ~         &[] => todo!(),
    |
 
diff --git a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
index 520a90322c1..923394474b2 100644
--- a/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
+++ b/tests/ui/rfc-2008-non-exhaustive/omitted-patterns.stderr
@@ -188,7 +188,7 @@ error[E0005]: refutable pattern in local binding
   --> $DIR/omitted-patterns.rs:194:9
    |
 LL |     let local_refutable @ NonExhaustiveEnum::Unit = NonExhaustiveEnum::Unit;
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ pattern `_` not covered
+   |         ^^^^^^^^^^^^^^^ pattern `_` not covered
    |
    = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
    = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
index 15f08486f0f..af47ba8baa3 100644
--- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
+++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.rs
@@ -2,10 +2,9 @@ fn main() {
     let A = 3;
     //~^ ERROR refutable pattern in local binding
     //~| patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
-    //~| missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
+    //~| missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable
     //~| HELP introduce a variable instead
-    //~| SUGGESTION a_var
+    //~| SUGGESTION A_var
 
     const A: i32 = 2;
-    //~^ constant defined here
 }
diff --git a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
index 1c1cab25fbf..9ee3e6eb2c8 100644
--- a/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
+++ b/tests/ui/suggestions/const-pat-non-exaustive-let-new-var.stderr
@@ -5,12 +5,11 @@ LL |     let A = 3;
    |         ^
    |         |
    |         patterns `i32::MIN..=1_i32` and `3_i32..=i32::MAX` not covered
-   |         missing patterns are not covered because `a` is interpreted as a constant pattern, not a new variable
-   |         help: introduce a variable instead: `a_var`
-...
-LL |     const A: i32 = 2;
-   |     ------------ constant defined here
+   |         missing patterns are not covered because `A` is interpreted as a constant pattern, not a new variable
+   |         help: introduce a variable instead: `A_var`
    |
+   = note: `let` bindings require an "irrefutable pattern", like a `struct` or an `enum` with only one variant
+   = note: for more information, visit https://doc.rust-lang.org/book/ch18-02-refutability.html
    = note: the matched value is of type `i32`
 
 error: aborting due to previous error
diff --git a/tests/ui/suggestions/ref-pattern-binding.stderr b/tests/ui/suggestions/ref-pattern-binding.stderr
index 7b194259349..69ce5d440af 100644
--- a/tests/ui/suggestions/ref-pattern-binding.stderr
+++ b/tests/ui/suggestions/ref-pattern-binding.stderr
@@ -2,9 +2,8 @@ error: borrow of moved value
   --> $DIR/ref-pattern-binding.rs:10:9
    |
 LL |     let _moved @ ref _from = String::from("foo");
-   |         ------^^^---------
-   |         |        |
-   |         |        value borrowed here after move
+   |         ^^^^^^   --------- value borrowed here after move
+   |         |
    |         value moved into `_moved` here
    |         move occurs because `_moved` has type `String` which does not implement the `Copy` trait
    |
@@ -17,27 +16,24 @@ error: cannot move out of value because it is borrowed
   --> $DIR/ref-pattern-binding.rs:11:9
    |
 LL |     let ref _moved @ _from = String::from("foo");
-   |         ----------^^^-----
-   |         |            |
-   |         |            value is moved into `_from` here
+   |         ^^^^^^^^^^   ----- value is moved into `_from` here
+   |         |
    |         value is borrowed by `_moved` here
 
 error: cannot move out of value because it is borrowed
   --> $DIR/ref-pattern-binding.rs:15:9
    |
 LL |     let ref _moved @ S { f } = S { f: String::from("foo") };
-   |         ----------^^^^^^^-^^
-   |         |                |
-   |         |                value is moved into `f` here
+   |         ^^^^^^^^^^       - value is moved into `f` here
+   |         |
    |         value is borrowed by `_moved` here
 
 error: borrow of moved value
   --> $DIR/ref-pattern-binding.rs:18:9
    |
 LL |     let _moved @ S { ref f } = S { f: String::from("foo") };
-   |         ------^^^^^^^-----^^
-   |         |            |
-   |         |            value borrowed here after move
+   |         ^^^^^^       ----- value borrowed here after move
+   |         |
    |         value moved into `_moved` here
    |         move occurs because `_moved` has type `S` which does not implement the `Copy` trait
    |