diff --git a/Cargo.lock b/Cargo.lock
index 8a2c6536d08c8..79ff8f8bc7f36 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -49,18 +49,9 @@ dependencies = [
 
 [[package]]
 name = "aho-corasick"
-version = "0.7.20"
+version = "1.1.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "cc936419f96fa211c1b9166887b38e5e40b19958e5b895be7c1f93adec7071ac"
-dependencies = [
- "memchr",
-]
-
-[[package]]
-name = "aho-corasick"
-version = "1.0.2"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "43f6cb1bf222025340178f382c426f13757b2960e89779dfcb319c32542a5a41"
+checksum = "b2969dcb958b36655471fc61f7e416fa76033bdd4bfed0678d8fee1e2d07a1f0"
 dependencies = [
  "memchr",
 ]
@@ -319,13 +310,12 @@ dependencies = [
 
 [[package]]
 name = "bstr"
-version = "1.5.0"
+version = "1.9.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "a246e68bb43f6cd9db24bea052a53e40405417c5fb372e3d1a8a7f770a564ef5"
+checksum = "c48f0051a4b4c5e0b6d365cd04af53aeaa209e3cc15ec2cdb69e73cc87fbd0dc"
 dependencies = [
  "memchr",
- "once_cell",
- "regex-automata 0.1.10",
+ "regex-automata 0.4.3",
  "serde",
 ]
 
@@ -596,7 +586,7 @@ dependencies = [
 name = "clippy_dev"
 version = "0.0.1"
 dependencies = [
- "aho-corasick 1.0.2",
+ "aho-corasick",
  "clap",
  "indoc",
  "itertools",
@@ -1597,15 +1587,15 @@ checksum = "d2fabcfbdc87f4758337ca535fb41a6d701b65693ce38287d856d1674551ec9b"
 
 [[package]]
 name = "globset"
-version = "0.4.10"
+version = "0.4.14"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "029d74589adefde59de1a0c4f4732695c32805624aec7b68d91503d4dba79afc"
+checksum = "57da3b9b5b85bd66f31093f8c408b90a74431672542466497dcbdfdc02034be1"
 dependencies = [
- "aho-corasick 0.7.20",
+ "aho-corasick",
  "bstr",
- "fnv",
  "log",
- "regex",
+ "regex-automata 0.4.3",
+ "regex-syntax 0.8.2",
 ]
 
 [[package]]
@@ -1944,17 +1934,16 @@ checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed"
 
 [[package]]
 name = "ignore"
-version = "0.4.20"
+version = "0.4.22"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "dbe7873dab538a9a44ad79ede1faf5f30d49f9a5c883ddbab48bce81b64b7492"
+checksum = "b46810df39e66e925525d6e38ce1e7f6e1d208f72dc39757880fcb66e2c58af1"
 dependencies = [
+ "crossbeam-deque",
  "globset",
- "lazy_static",
  "log",
  "memchr",
- "regex",
+ "regex-automata 0.4.3",
  "same-file",
- "thread_local",
  "walkdir",
  "winapi-util",
 ]
@@ -2274,9 +2263,9 @@ dependencies = [
 
 [[package]]
 name = "log"
-version = "0.4.19"
+version = "0.4.20"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "b06a4cde4c0f271a446782e3eff8de789548ce57dbc8eca9292c27f4a42004b4"
+checksum = "b5e6163cb8c49088c2c36f57875e58ccd8c87c7427f7fbd50ea6710b2f3f2e8f"
 
 [[package]]
 name = "lzma-sys"
@@ -2378,9 +2367,9 @@ dependencies = [
 
 [[package]]
 name = "memchr"
-version = "2.5.0"
+version = "2.7.1"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "2dffe52ecf27772e601905b7522cb4ef790d2cc203488bbd0e2fe85fcb74566d"
+checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149"
 dependencies = [
  "compiler_builtins",
  "rustc-std-workspace-core",
@@ -2490,9 +2479,6 @@ dependencies = [
 [[package]]
 name = "miropt-test-tools"
 version = "0.1.0"
-dependencies = [
- "regex",
-]
 
 [[package]]
 name = "native-tls"
@@ -3153,13 +3139,14 @@ dependencies = [
 
 [[package]]
 name = "regex"
-version = "1.8.4"
+version = "1.10.2"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "d0ab3ca65655bb1e41f2a8c8cd662eb4fb035e67c3f78da1d61dffe89d07300f"
+checksum = "380b951a9c5e80ddfd6136919eef32310721aa4aacd4889a8d39124b026ab343"
 dependencies = [
- "aho-corasick 1.0.2",
+ "aho-corasick",
  "memchr",
- "regex-syntax 0.7.2",
+ "regex-automata 0.4.3",
+ "regex-syntax 0.8.2",
 ]
 
 [[package]]
@@ -3181,16 +3168,21 @@ dependencies = [
 ]
 
 [[package]]
-name = "regex-syntax"
-version = "0.6.29"
+name = "regex-automata"
+version = "0.4.3"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
+checksum = "5f804c7828047e88b2d32e2d7fe5a105da8ee3264f01902f796c8e067dc2483f"
+dependencies = [
+ "aho-corasick",
+ "memchr",
+ "regex-syntax 0.8.2",
+]
 
 [[package]]
 name = "regex-syntax"
-version = "0.7.2"
+version = "0.6.29"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "436b050e76ed2903236f032a59761c1eb99e1b0aead2c257922771dab1fc8c78"
+checksum = "f162c6dd7b008981e4d40210aca20b4bd0f9b60ca9271061b07f78537722f2e1"
 
 [[package]]
 name = "regex-syntax"
@@ -5940,9 +5932,9 @@ checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f"
 
 [[package]]
 name = "walkdir"
-version = "2.3.3"
+version = "2.4.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
-checksum = "36df944cda56c7d8d8b7496af378e6b16de9284591917d307c9b4d313c44e698"
+checksum = "d71d857dc86794ca4c280d616f7da00d2dbfd8cd788846559a6813e6aa4b54ee"
 dependencies = [
  "same-file",
  "winapi-util",
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/check.rs b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
index 89c65d9232586..5ff81615552bf 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/check.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/check.rs
@@ -20,7 +20,7 @@ use std::mem;
 use std::ops::{ControlFlow, Deref};
 
 use super::ops::{self, NonConstOp, Status};
-use super::qualifs::{self, CustomEq, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
+use super::qualifs::{self, HasMutInterior, NeedsDrop, NeedsNonConstDrop};
 use super::resolver::FlowSensitiveAnalysis;
 use super::{ConstCx, Qualif};
 use crate::const_eval::is_unstable_const_fn;
@@ -149,37 +149,10 @@ impl<'mir, 'tcx> Qualifs<'mir, 'tcx> {
 
         let return_loc = ccx.body.terminator_loc(return_block);
 
-        let custom_eq = match ccx.const_kind() {
-            // We don't care whether a `const fn` returns a value that is not structurally
-            // matchable. Functions calls are opaque and always use type-based qualification, so
-            // this value should never be used.
-            hir::ConstContext::ConstFn => true,
-
-            // If we know that all values of the return type are structurally matchable, there's no
-            // need to run dataflow.
-            // Opaque types do not participate in const generics or pattern matching, so we can safely count them out.
-            _ if ccx.body.return_ty().has_opaque_types()
-                || !CustomEq::in_any_value_of_ty(ccx, ccx.body.return_ty()) =>
-            {
-                false
-            }
-
-            hir::ConstContext::Const { .. } | hir::ConstContext::Static(_) => {
-                let mut cursor = FlowSensitiveAnalysis::new(CustomEq, ccx)
-                    .into_engine(ccx.tcx, ccx.body)
-                    .iterate_to_fixpoint()
-                    .into_results_cursor(ccx.body);
-
-                cursor.seek_after_primary_effect(return_loc);
-                cursor.get().contains(RETURN_PLACE)
-            }
-        };
-
         ConstQualifs {
             needs_drop: self.needs_drop(ccx, RETURN_PLACE, return_loc),
             needs_non_const_drop: self.needs_non_const_drop(ccx, RETURN_PLACE, return_loc),
             has_mut_interior: self.has_mut_interior(ccx, RETURN_PLACE, return_loc),
-            custom_eq,
             tainted_by_errors,
         }
     }
diff --git a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
index 1efa52df5817b..67fef20807910 100644
--- a/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
+++ b/compiler/rustc_const_eval/src/transform/check_consts/qualifs.rs
@@ -10,7 +10,7 @@ use rustc_middle::mir::*;
 use rustc_middle::traits::BuiltinImplSource;
 use rustc_middle::ty::{self, AdtDef, GenericArgsRef, Ty};
 use rustc_trait_selection::traits::{
-    self, ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
+    ImplSource, Obligation, ObligationCause, ObligationCtxt, SelectionContext,
 };
 
 use super::ConstCx;
@@ -24,7 +24,6 @@ pub fn in_any_value_of_ty<'tcx>(
         has_mut_interior: HasMutInterior::in_any_value_of_ty(cx, ty),
         needs_drop: NeedsDrop::in_any_value_of_ty(cx, ty),
         needs_non_const_drop: NeedsNonConstDrop::in_any_value_of_ty(cx, ty),
-        custom_eq: CustomEq::in_any_value_of_ty(cx, ty),
         tainted_by_errors,
     }
 }
@@ -213,35 +212,6 @@ impl Qualif for NeedsNonConstDrop {
     }
 }
 
-/// A constant that cannot be used as part of a pattern in a `match` expression.
-pub struct CustomEq;
-
-impl Qualif for CustomEq {
-    const ANALYSIS_NAME: &'static str = "flow_custom_eq";
-
-    fn in_qualifs(qualifs: &ConstQualifs) -> bool {
-        qualifs.custom_eq
-    }
-
-    fn in_any_value_of_ty<'tcx>(cx: &ConstCx<'_, 'tcx>, ty: Ty<'tcx>) -> bool {
-        // If *any* component of a composite data type does not implement `Structural{Partial,}Eq`,
-        // we know that at least some values of that type are not structural-match. I say "some"
-        // because that component may be part of an enum variant (e.g.,
-        // `Option::<NonStructuralMatchTy>::Some`), in which case some values of this type may be
-        // structural-match (`Option::None`).
-        traits::search_for_structural_match_violation(cx.body.span, cx.tcx, ty).is_some()
-    }
-
-    fn in_adt_inherently<'tcx>(
-        cx: &ConstCx<'_, 'tcx>,
-        def: AdtDef<'tcx>,
-        args: GenericArgsRef<'tcx>,
-    ) -> bool {
-        let ty = Ty::new_adt(cx.tcx, def, args);
-        !ty.is_structural_eq_shallow(cx.tcx)
-    }
-}
-
 // FIXME: Use `mir::visit::Visitor` for the `in_*` functions if/when it supports early return.
 
 /// Returns `true` if this `Rvalue` contains qualif `Q`.
diff --git a/compiler/rustc_hir_typeck/src/method/suggest.rs b/compiler/rustc_hir_typeck/src/method/suggest.rs
index 904961d9eba26..adf754094a110 100644
--- a/compiler/rustc_hir_typeck/src/method/suggest.rs
+++ b/compiler/rustc_hir_typeck/src/method/suggest.rs
@@ -540,6 +540,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         let mut bound_spans: SortedMap<Span, Vec<String>> = Default::default();
         let mut restrict_type_params = false;
+        let mut suggested_derive = false;
         let mut unsatisfied_bounds = false;
         if item_name.name == sym::count && self.is_slice_ty(rcvr_ty, span) {
             let msg = "consider using `len` instead";
@@ -554,6 +555,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     "`count` is defined on `{iterator_trait}`, which `{rcvr_ty}` does not implement"
                 ));
             }
+        } else if !unsatisfied_predicates.is_empty() && matches!(rcvr_ty.kind(), ty::Param(_)) {
+            // We special case the situation where we are looking for `_` in
+            // `<TypeParam as _>::method` because otherwise the machinery will look for blanket
+            // implementations that have unsatisfied trait bounds to suggest, leading us to claim
+            // things like "we're looking for a trait with method `cmp`, both `Iterator` and `Ord`
+            // have one, in order to implement `Ord` you need to restrict `TypeParam: FnPtr` so
+            // that `impl<T: FnPtr> Ord for T` can apply", which is not what we want. We have a type
+            // parameter, we want to directly say "`Ord::cmp` and `Iterator::cmp` exist, restrict
+            // `TypeParam: Ord` or `TypeParam: Iterator`"". That is done further down when calling
+            // `self.suggest_traits_to_import`, so we ignore the `unsatisfied_predicates`
+            // suggestions.
         } else if !unsatisfied_predicates.is_empty() {
             let mut type_params = FxIndexMap::default();
 
@@ -916,20 +928,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 .enumerate()
                 .collect::<Vec<(usize, String)>>();
 
-            for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
-                restrict_type_params = true;
-                // #74886: Sort here so that the output is always the same.
-                let obligations = obligations.into_sorted_stable_ord();
-                err.span_suggestion_verbose(
-                    span,
-                    format!(
-                        "consider restricting the type parameter{s} to satisfy the \
-                         trait bound{s}",
-                        s = pluralize!(obligations.len())
-                    ),
-                    format!("{} {}", add_where_or_comma, obligations.join(", ")),
-                    Applicability::MaybeIncorrect,
-                );
+            if !matches!(rcvr_ty.peel_refs().kind(), ty::Param(_)) {
+                for ((span, add_where_or_comma), obligations) in type_params.into_iter() {
+                    restrict_type_params = true;
+                    // #74886: Sort here so that the output is always the same.
+                    let obligations = obligations.into_sorted_stable_ord();
+                    err.span_suggestion_verbose(
+                        span,
+                        format!(
+                            "consider restricting the type parameter{s} to satisfy the trait \
+                             bound{s}",
+                            s = pluralize!(obligations.len())
+                        ),
+                        format!("{} {}", add_where_or_comma, obligations.join(", ")),
+                        Applicability::MaybeIncorrect,
+                    );
+                }
             }
 
             bound_list.sort_by(|(_, a), (_, b)| a.cmp(b)); // Sort alphabetically.
@@ -977,7 +991,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         "the following trait bounds were not satisfied:\n{bound_list}"
                     ));
                 }
-                self.suggest_derive(&mut err, unsatisfied_predicates);
+                suggested_derive = self.suggest_derive(&mut err, unsatisfied_predicates);
 
                 unsatisfied_bounds = true;
             }
@@ -1200,7 +1214,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             );
         }
 
-        if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params {
+        if rcvr_ty.is_numeric() && rcvr_ty.is_fresh() || restrict_type_params || suggested_derive {
         } else {
             self.suggest_traits_to_import(
                 &mut err,
@@ -1210,7 +1224,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 args.map(|args| args.len() + 1),
                 source,
                 no_match_data.out_of_scope_traits.clone(),
-                unsatisfied_predicates,
                 static_candidates,
                 unsatisfied_bounds,
                 expected.only_has_type(self),
@@ -1325,7 +1338,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             }
         }
         self.note_derefed_ty_has_method(&mut err, source, rcvr_ty, item_name, expected);
-        return Some(err);
+        Some(err)
     }
 
     fn note_candidates_on_method_error(
@@ -2470,7 +2483,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             Option<ty::Predicate<'tcx>>,
             Option<ObligationCause<'tcx>>,
         )],
-    ) {
+    ) -> bool {
         let mut derives = self.note_predicate_source_and_get_derives(err, unsatisfied_predicates);
         derives.sort();
         derives.dedup();
@@ -2495,6 +2508,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 Applicability::MaybeIncorrect,
             );
         }
+        !derives_grouped.is_empty()
     }
 
     fn note_derefed_ty_has_method(
@@ -2697,11 +2711,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         inputs_len: Option<usize>,
         source: SelfSource<'tcx>,
         valid_out_of_scope_traits: Vec<DefId>,
-        unsatisfied_predicates: &[(
-            ty::Predicate<'tcx>,
-            Option<ty::Predicate<'tcx>>,
-            Option<ObligationCause<'tcx>>,
-        )],
         static_candidates: &[CandidateSource],
         unsatisfied_bounds: bool,
         return_type: Option<Ty<'tcx>>,
@@ -2918,19 +2927,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                 // this isn't perfect (that is, there are cases when
                 // implementing a trait would be legal but is rejected
                 // here).
-                unsatisfied_predicates.iter().all(|(p, _, _)| {
-                    match p.kind().skip_binder() {
-                        // Hide traits if they are present in predicates as they can be fixed without
-                        // having to implement them.
-                        ty::PredicateKind::Clause(ty::ClauseKind::Trait(t)) => {
-                            t.def_id() == info.def_id
-                        }
-                        ty::PredicateKind::Clause(ty::ClauseKind::Projection(p)) => {
-                            p.projection_ty.def_id == info.def_id
-                        }
-                        _ => false,
-                    }
-                }) && (type_is_local || info.def_id.is_local())
+                (type_is_local || info.def_id.is_local())
                     && !self.tcx.trait_is_auto(info.def_id)
                     && self
                         .associated_value(info.def_id, item_name)
diff --git a/compiler/rustc_lint/src/context/diagnostics.rs b/compiler/rustc_lint/src/context/diagnostics.rs
index eb42730f69a4d..0fa61c5d87e77 100644
--- a/compiler/rustc_lint/src/context/diagnostics.rs
+++ b/compiler/rustc_lint/src/context/diagnostics.rs
@@ -188,6 +188,23 @@ pub(super) fn builtin(
             #[allow(rustc::potential_query_instability)]
             let possibilities: Vec<Symbol> =
                 sess.parse_sess.check_config.expecteds.keys().copied().collect();
+
+            let mut names_possibilities: Vec<_> = if value.is_none() {
+                // We later sort and display all the possibilities, so the order here does not matter.
+                #[allow(rustc::potential_query_instability)]
+                sess.parse_sess
+                    .check_config
+                    .expecteds
+                    .iter()
+                    .filter_map(|(k, v)| match v {
+                        ExpectedValues::Some(v) if v.contains(&Some(name)) => Some(k),
+                        _ => None,
+                    })
+                    .collect()
+            } else {
+                Vec::new()
+            };
+
             let is_from_cargo = std::env::var_os("CARGO").is_some();
             let mut is_feature_cfg = name == sym::feature;
 
@@ -262,17 +279,30 @@ pub(super) fn builtin(
                 }
 
                 is_feature_cfg |= best_match == sym::feature;
-            } else if !possibilities.is_empty() {
-                let mut possibilities =
-                    possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
-                possibilities.sort();
-                let possibilities = possibilities.join("`, `");
+            } else {
+                if !names_possibilities.is_empty() && names_possibilities.len() <= 3 {
+                    names_possibilities.sort();
+                    for cfg_name in names_possibilities.iter() {
+                        db.span_suggestion(
+                            name_span,
+                            "found config with similar value",
+                            format!("{cfg_name} = \"{name}\""),
+                            Applicability::MaybeIncorrect,
+                        );
+                    }
+                }
+                if !possibilities.is_empty() {
+                    let mut possibilities =
+                        possibilities.iter().map(Symbol::as_str).collect::<Vec<_>>();
+                    possibilities.sort();
+                    let possibilities = possibilities.join("`, `");
 
-                // The list of expected names can be long (even by default) and
-                // so the diagnostic produced can take a lot of space. To avoid
-                // cloging the user output we only want to print that diagnostic
-                // once.
-                db.help_once(format!("expected names are: `{possibilities}`"));
+                    // The list of expected names can be long (even by default) and
+                    // so the diagnostic produced can take a lot of space. To avoid
+                    // cloging the user output we only want to print that diagnostic
+                    // once.
+                    db.help_once(format!("expected names are: `{possibilities}`"));
+                }
             }
 
             let inst = if let Some((value, _value_span)) = value {
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index 1d9ce10bcaf38..2254eed6382ae 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -516,6 +516,11 @@ fn register_builtins(store: &mut LintStore) {
         "converted into hard error, see PR #118649 \
          <https://github.com/rust-lang/rust/pull/118649> for more information",
     );
+    store.register_removed(
+        "nontrivial_structural_match",
+        "no longer needed, see RFC #3535 \
+         <https://rust-lang.github.io/rfcs/3535-constants-in-patterns.html> for more information",
+    );
 }
 
 fn register_internals(store: &mut LintStore) {
diff --git a/compiler/rustc_lint_defs/src/builtin.rs b/compiler/rustc_lint_defs/src/builtin.rs
index e6d837ecd92bd..18a134b05c309 100644
--- a/compiler/rustc_lint_defs/src/builtin.rs
+++ b/compiler/rustc_lint_defs/src/builtin.rs
@@ -3,6 +3,9 @@
 //! These are the built-in lints that are emitted direct in the main
 //! compiler code, rather than using their own custom pass. Those
 //! lints are all available in `rustc_lint::builtin`.
+//!
+//! When removing a lint, make sure to also add a call to `register_removed` in
+//! compiler/rustc_lint/src/lib.rs.
 
 use crate::{declare_lint, declare_lint_pass, FutureIncompatibilityReason};
 use rustc_span::edition::Edition;
@@ -67,7 +70,6 @@ declare_lint_pass! {
         MUST_NOT_SUSPEND,
         NAMED_ARGUMENTS_USED_POSITIONALLY,
         NON_EXHAUSTIVE_OMITTED_PATTERNS,
-        NONTRIVIAL_STRUCTURAL_MATCH,
         ORDER_DEPENDENT_TRAIT_OBJECTS,
         OVERLAPPING_RANGE_ENDPOINTS,
         PATTERNS_IN_FNS_WITHOUT_BODY,
@@ -2330,8 +2332,8 @@ declare_lint! {
     Warn,
     "constant used in pattern contains value of non-structural-match type in a field or a variant",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
-        reference: "issue #62411 <https://github.com/rust-lang/rust/issues/62411>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #120362 <https://github.com/rust-lang/rust/issues/120362>",
     };
 }
 
@@ -2386,47 +2388,8 @@ declare_lint! {
     Warn,
     "pointers are not structural-match",
     @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
-        reference: "issue #62411 <https://github.com/rust-lang/rust/issues/70861>",
-    };
-}
-
-declare_lint! {
-    /// The `nontrivial_structural_match` lint detects constants that are used in patterns,
-    /// whose type is not structural-match and whose initializer body actually uses values
-    /// that are not structural-match. So `Option<NotStructuralMatch>` is ok if the constant
-    /// is just `None`.
-    ///
-    /// ### Example
-    ///
-    /// ```rust,compile_fail
-    /// #![deny(nontrivial_structural_match)]
-    ///
-    /// #[derive(Copy, Clone, Debug)]
-    /// struct NoDerive(u32);
-    /// impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-    /// impl Eq for NoDerive { }
-    /// fn main() {
-    ///     const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
-    ///     match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
-    /// }
-    /// ```
-    ///
-    /// {{produces}}
-    ///
-    /// ### Explanation
-    ///
-    /// Previous versions of Rust accepted constants in patterns, even if those constants' types
-    /// did not have `PartialEq` derived. Thus the compiler falls back to runtime execution of
-    /// `PartialEq`, which can report that two constants are not equal even if they are
-    /// bit-equivalent.
-    pub NONTRIVIAL_STRUCTURAL_MATCH,
-    Warn,
-    "constant used in pattern of non-structural-match type and the constant's initializer \
-    expression contains values of non-structural-match types",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseErrorDontReportInDeps,
-        reference: "issue #73448 <https://github.com/rust-lang/rust/issues/73448>",
+        reason: FutureIncompatibilityReason::FutureReleaseErrorReportInDeps,
+        reference: "issue #120362 <https://github.com/rust-lang/rust/issues/120362>",
     };
 }
 
diff --git a/compiler/rustc_middle/src/mir/query.rs b/compiler/rustc_middle/src/mir/query.rs
index 98642adc19090..90b6df1dd1f5e 100644
--- a/compiler/rustc_middle/src/mir/query.rs
+++ b/compiler/rustc_middle/src/mir/query.rs
@@ -189,7 +189,7 @@ pub struct BorrowCheckResult<'tcx> {
 
 /// The result of the `mir_const_qualif` query.
 ///
-/// Each field (except `error_occurred`) corresponds to an implementer of the `Qualif` trait in
+/// Each field (except `tainted_by_errors`) corresponds to an implementer of the `Qualif` trait in
 /// `rustc_const_eval/src/transform/check_consts/qualifs.rs`. See that file for more information on each
 /// `Qualif`.
 #[derive(Clone, Copy, Debug, Default, TyEncodable, TyDecodable, HashStable)]
@@ -197,7 +197,6 @@ pub struct ConstQualifs {
     pub has_mut_interior: bool,
     pub needs_drop: bool,
     pub needs_non_const_drop: bool,
-    pub custom_eq: bool,
     pub tainted_by_errors: Option<ErrorGuaranteed>,
 }
 
diff --git a/compiler/rustc_mir_build/src/build/matches/simplify.rs b/compiler/rustc_mir_build/src/build/matches/simplify.rs
index 065c93e86a866..541a3129950ef 100644
--- a/compiler/rustc_mir_build/src/build/matches/simplify.rs
+++ b/compiler/rustc_mir_build/src/build/matches/simplify.rs
@@ -40,43 +40,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
         &mut self,
         candidate: &mut Candidate<'pat, 'tcx>,
     ) -> bool {
-        // repeatedly simplify match pairs until fixed point is reached
         debug!("{candidate:#?}");
-
-        // existing_bindings and new_bindings exists to keep the semantics in order.
-        // Reversing the binding order for bindings after `@` changes the binding order in places
-        // it shouldn't be changed, for example `let (Some(a), Some(b)) = (x, y)`
+        // In order to please the borrow checker, in a pattern like `x @ pat` we must lower the
+        // bindings in `pat` before `x`. E.g. (#69971):
+        //
+        // struct NonCopyStruct {
+        //     copy_field: u32,
+        // }
+        //
+        // fn foo1(x: NonCopyStruct) {
+        //     let y @ NonCopyStruct { copy_field: z } = x;
+        //     // the above should turn into
+        //     let z = x.copy_field;
+        //     let y = x;
+        // }
         //
-        // To avoid this, the binding occurs in the following manner:
-        // * the bindings for one iteration of the following loop occurs in order (i.e. left to
-        // right)
-        // * the bindings from the previous iteration of the loop is prepended to the bindings from
-        // the current iteration (in the implementation this is done by mem::swap and extend)
-        // * after all iterations, these new bindings are then appended to the bindings that were
-        // preexisting (i.e. `candidate.binding` when the function was called).
+        // We can't just reverse the binding order, because we must preserve pattern-order
+        // otherwise, e.g. in `let (Some(a), Some(b)) = (x, y)`. Our rule then is: deepest-first,
+        // and bindings at the same depth stay in source order.
+        //
+        // To do this, every time around the loop we prepend the newly found bindings to the
+        // bindings we already had.
         //
         // example:
         // candidate.bindings = [1, 2, 3]
-        // binding in iter 1: [4, 5]
-        // binding in iter 2: [6, 7]
+        // bindings in iter 1: [4, 5]
+        // bindings in iter 2: [6, 7]
         //
-        // final binding: [1, 2, 3, 6, 7, 4, 5]
-        let mut existing_bindings = mem::take(&mut candidate.bindings);
-        let mut new_bindings = Vec::new();
+        // final bindings: [6, 7, 4, 5, 1, 2, 3]
+        let mut accumulated_bindings = mem::take(&mut candidate.bindings);
+        // Repeatedly simplify match pairs until fixed point is reached
         loop {
-            let match_pairs = mem::take(&mut candidate.match_pairs);
-
-            if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] =
-                &*match_pairs
-            {
-                existing_bindings.extend_from_slice(&new_bindings);
-                mem::swap(&mut candidate.bindings, &mut existing_bindings);
-                candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
-                return true;
-            }
-
             let mut changed = false;
-            for match_pair in match_pairs {
+            for match_pair in mem::take(&mut candidate.match_pairs) {
                 match self.simplify_match_pair(match_pair, candidate) {
                     Ok(()) => {
                         changed = true;
@@ -86,36 +82,39 @@ impl<'a, 'tcx> Builder<'a, 'tcx> {
                     }
                 }
             }
-            // Avoid issue #69971: the binding order should be right to left if there are more
-            // bindings after `@` to please the borrow checker
-            // Ex
-            // struct NonCopyStruct {
-            //     copy_field: u32,
-            // }
-            //
-            // fn foo1(x: NonCopyStruct) {
-            //     let y @ NonCopyStruct { copy_field: z } = x;
-            //     // the above should turn into
-            //     let z = x.copy_field;
-            //     let y = x;
-            // }
-            candidate.bindings.extend_from_slice(&new_bindings);
-            mem::swap(&mut candidate.bindings, &mut new_bindings);
+
+            // This does: accumulated_bindings = candidate.bindings.take() ++ accumulated_bindings
+            candidate.bindings.extend_from_slice(&accumulated_bindings);
+            mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
             candidate.bindings.clear();
 
             if !changed {
-                existing_bindings.extend_from_slice(&new_bindings);
-                mem::swap(&mut candidate.bindings, &mut existing_bindings);
-                // Move or-patterns to the end, because they can result in us
-                // creating additional candidates, so we want to test them as
-                // late as possible.
-                candidate
-                    .match_pairs
-                    .sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
-                debug!(simplified = ?candidate, "simplify_candidate");
-                return false; // if we were not able to simplify any, done.
+                // If we were not able to simplify anymore, done.
+                break;
             }
         }
+
+        // Store computed bindings back in `candidate`.
+        mem::swap(&mut candidate.bindings, &mut accumulated_bindings);
+
+        let did_expand_or =
+            if let [MatchPair { pattern: Pat { kind: PatKind::Or { pats }, .. }, place }] =
+                &*candidate.match_pairs
+            {
+                candidate.subcandidates = self.create_or_subcandidates(candidate, place, pats);
+                candidate.match_pairs.clear();
+                true
+            } else {
+                false
+            };
+
+        // Move or-patterns to the end, because they can result in us
+        // creating additional candidates, so we want to test them as
+        // late as possible.
+        candidate.match_pairs.sort_by_key(|pair| matches!(pair.pattern.kind, PatKind::Or { .. }));
+        debug!(simplified = ?candidate, "simplify_candidate");
+
+        did_expand_or
     }
 
     /// Given `candidate` that has a single or-pattern for its match-pairs,
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 22305f03a769d..1c3ffe23879f1 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
@@ -1,5 +1,4 @@
 use rustc_hir as hir;
-use rustc_hir::def_id::DefId;
 use rustc_index::Idx;
 use rustc_infer::infer::{InferCtxt, TyCtxtInferExt};
 use rustc_infer::traits::Obligation;
@@ -16,8 +15,8 @@ use std::cell::Cell;
 
 use super::PatCtxt;
 use crate::errors::{
-    FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch,
-    NontrivialStructuralMatch, PointerPattern, TypeNotStructural, UnionPattern, UnsizedPattern,
+    FloatPattern, IndirectStructuralMatch, InvalidPattern, NonPartialEqMatch, PointerPattern,
+    TypeNotStructural, UnionPattern, UnsizedPattern,
 };
 
 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
@@ -32,11 +31,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         cv: mir::Const<'tcx>,
         id: hir::HirId,
         span: Span,
-        check_body_for_struct_match_violation: Option<DefId>,
     ) -> Box<Pat<'tcx>> {
         let infcx = self.tcx.infer_ctxt().build();
         let mut convert = ConstToPat::new(self, id, span, infcx);
-        convert.to_pat(cv, check_body_for_struct_match_violation)
+        convert.to_pat(cv)
     }
 }
 
@@ -102,11 +100,7 @@ impl<'tcx> ConstToPat<'tcx> {
         ty.is_structural_eq_shallow(self.infcx.tcx)
     }
 
-    fn to_pat(
-        &mut self,
-        cv: mir::Const<'tcx>,
-        check_body_for_struct_match_violation: Option<DefId>,
-    ) -> Box<Pat<'tcx>> {
+    fn to_pat(&mut self, cv: mir::Const<'tcx>) -> Box<Pat<'tcx>> {
         trace!(self.treat_byte_string_as_slice);
         // This method is just a wrapper handling a validity check; the heavy lifting is
         // performed by the recursive `recur` method, which is not meant to be
@@ -115,14 +109,6 @@ impl<'tcx> ConstToPat<'tcx> {
         // once indirect_structural_match is a full fledged error, this
         // level of indirection can be eliminated
 
-        let mir_structural_match_violation = check_body_for_struct_match_violation.map(|def_id| {
-            // `mir_const_qualif` must be called with the `DefId` of the item where the const is
-            // defined, not where it is declared. The difference is significant for associated
-            // constants.
-            self.tcx().mir_const_qualif(def_id).custom_eq
-        });
-        debug!(?check_body_for_struct_match_violation, ?mir_structural_match_violation);
-
         let have_valtree =
             matches!(cv, mir::Const::Ty(c) if matches!(c.kind(), ty::ConstKind::Value(_)));
         let inlined_const_as_pat = match cv {
@@ -136,15 +122,15 @@ impl<'tcx> ConstToPat<'tcx> {
                 | ty::ConstKind::Expr(_) => {
                     span_bug!(self.span, "unexpected const in `to_pat`: {:?}", c.kind())
                 }
-                ty::ConstKind::Value(valtree) => self
-                    .recur(valtree, cv.ty(), mir_structural_match_violation.unwrap_or(false))
-                    .unwrap_or_else(|_: FallbackToOpaqueConst| {
+                ty::ConstKind::Value(valtree) => {
+                    self.recur(valtree, cv.ty()).unwrap_or_else(|_: FallbackToOpaqueConst| {
                         Box::new(Pat {
                             span: self.span,
                             ty: cv.ty(),
                             kind: PatKind::Constant { value: cv },
                         })
-                    }),
+                    })
+                }
             },
             mir::Const::Unevaluated(_, _) => {
                 span_bug!(self.span, "unevaluated const in `to_pat`: {cv:?}")
@@ -159,7 +145,12 @@ impl<'tcx> ConstToPat<'tcx> {
         if self.saw_const_match_error.get().is_none() {
             // If we were able to successfully convert the const to some pat (possibly with some
             // lints, but no errors), double-check that all types in the const implement
-            // `Structural` and `PartialEq`.
+            // `PartialEq`. Even if we have a valtree, we may have found something
+            // in there with non-structural-equality, meaning we match using `PartialEq`
+            // and we hence have to check that that impl exists.
+            // This is all messy but not worth cleaning up: at some point we'll emit
+            // a hard error when we don't have a valtree or when we find something in
+            // the valtree that is not structural; then this can all be made a lot simpler.
 
             let structural =
                 traits::search_for_structural_match_violation(self.span, self.tcx(), cv.ty());
@@ -169,19 +160,12 @@ impl<'tcx> ConstToPat<'tcx> {
                 structural
             );
 
-            // This can occur because const qualification treats all associated constants as
-            // opaque, whereas `search_for_structural_match_violation` tries to monomorphize them
-            // before it runs.
-            //
-            // FIXME(#73448): Find a way to bring const qualification into parity with
-            // `search_for_structural_match_violation`.
-            if structural.is_none() && mir_structural_match_violation.unwrap_or(false) {
-                warn!("MIR const-checker found novel structural match violation. See #73448.");
-                return inlined_const_as_pat;
-            }
-
             if let Some(non_sm_ty) = structural {
                 if !self.type_has_partial_eq_impl(cv.ty()) {
+                    // This is reachable and important even if we have a valtree: there might be
+                    // non-structural things in a valtree, in which case we fall back to `PartialEq`
+                    // comparison, in which case we better make sure the trait is implemented for
+                    // each inner type (and not just for the surrounding type).
                     let e = if let ty::Adt(def, ..) = non_sm_ty.kind() {
                         if def.is_union() {
                             let err = UnionPattern { span: self.span };
@@ -200,35 +184,18 @@ impl<'tcx> ConstToPat<'tcx> {
                     // We errored. Signal that in the pattern, so that follow up errors can be silenced.
                     let kind = PatKind::Error(e);
                     return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
-                } else if let ty::Adt(..) = cv.ty().kind()
-                    && matches!(cv, mir::Const::Val(..))
-                {
-                    // This branch is only entered when the current `cv` is `mir::Const::Val`.
-                    // This is because `mir::Const::ty` has already been handled by `Self::recur`
-                    // and the invalid types may be ignored.
+                } else if !have_valtree {
+                    // Not being structural prevented us from constructing a valtree,
+                    // so this is definitely a case we want to reject.
                     let err = TypeNotStructural { span: self.span, non_sm_ty };
                     let e = self.tcx().dcx().emit_err(err);
                     let kind = PatKind::Error(e);
                     return Box::new(Pat { span: self.span, ty: cv.ty(), kind });
-                } else if !self.saw_const_match_lint.get() {
-                    if let Some(mir_structural_match_violation) = mir_structural_match_violation {
-                        match non_sm_ty.kind() {
-                            ty::Adt(..) if mir_structural_match_violation => {
-                                self.tcx().emit_node_span_lint(
-                                    lint::builtin::INDIRECT_STRUCTURAL_MATCH,
-                                    self.id,
-                                    self.span,
-                                    IndirectStructuralMatch { non_sm_ty },
-                                );
-                            }
-                            _ => {
-                                debug!(
-                                    "`search_for_structural_match_violation` found one, but `CustomEq` was \
-                                  not in the qualifs for that `const`"
-                                );
-                            }
-                        }
-                    }
+                } else {
+                    // This could be a violation in an inactive enum variant.
+                    // Since we have a valtree, we trust that we have traversed the full valtree and
+                    // complained about structural match violations there, so we don't
+                    // have to check anything any more.
                 }
             } else if !have_valtree && !self.saw_const_match_lint.get() {
                 // The only way valtree construction can fail without the structural match
@@ -298,7 +265,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 let field = FieldIdx::new(idx);
                 // Patterns can only use monomorphic types.
                 let ty = self.tcx().normalize_erasing_regions(self.param_env, ty);
-                Ok(FieldPat { field, pattern: self.recur(val, ty, false)? })
+                Ok(FieldPat { field, pattern: self.recur(val, ty)? })
             })
             .collect()
     }
@@ -309,7 +276,6 @@ impl<'tcx> ConstToPat<'tcx> {
         &self,
         cv: ValTree<'tcx>,
         ty: Ty<'tcx>,
-        mir_structural_match_violation: bool,
     ) -> Result<Box<Pat<'tcx>>, FallbackToOpaqueConst> {
         let id = self.id;
         let span = self.span;
@@ -404,7 +370,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 prefix: cv
                     .unwrap_branch()
                     .iter()
-                    .map(|val| self.recur(*val, *elem_ty, false))
+                    .map(|val| self.recur(*val, *elem_ty))
                     .collect::<Result<_, _>>()?,
                 slice: None,
                 suffix: Box::new([]),
@@ -413,7 +379,7 @@ impl<'tcx> ConstToPat<'tcx> {
                 prefix: cv
                     .unwrap_branch()
                     .iter()
-                    .map(|val| self.recur(*val, *elem_ty, false))
+                    .map(|val| self.recur(*val, *elem_ty))
                     .collect::<Result<_, _>>()?,
                 slice: None,
                 suffix: Box::new([]),
@@ -480,7 +446,7 @@ impl<'tcx> ConstToPat<'tcx> {
                             _ => *pointee_ty,
                         };
                         // References have the same valtree representation as their pointee.
-                        let subpattern = self.recur(cv, pointee_ty, false)?;
+                        let subpattern = self.recur(cv, pointee_ty)?;
                         self.behind_reference.set(old);
                         PatKind::Deref { subpattern }
                     }
@@ -505,25 +471,6 @@ impl<'tcx> ConstToPat<'tcx> {
             }
         };
 
-        if self.saw_const_match_error.get().is_none()
-            && !self.saw_const_match_lint.get()
-            && mir_structural_match_violation
-            // FIXME(#73448): Find a way to bring const qualification into parity with
-            // `search_for_structural_match_violation` and then remove this condition.
-
-            // Obtain the actual type that isn't annotated. If we just looked at `cv.ty` we
-            // could get `Option<NonStructEq>`, even though `Option` is annotated with derive.
-            && let Some(non_sm_ty) = traits::search_for_structural_match_violation(span, tcx, ty)
-        {
-            self.saw_const_match_lint.set(true);
-            tcx.emit_node_span_lint(
-                lint::builtin::NONTRIVIAL_STRUCTURAL_MATCH,
-                id,
-                span,
-                NontrivialStructuralMatch { non_sm_ty },
-            );
-        }
-
         Ok(Box::new(Pat { span, ty, kind }))
     }
 }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index 2190ad14b5511..1a5cf13e28978 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -542,7 +542,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
 
         match const_value {
             Ok(const_) => {
-                let pattern = self.const_to_pat(const_, id, span, Some(instance.def_id()));
+                let pattern = self.const_to_pat(const_, id, span);
 
                 if !is_associated_const {
                     return pattern;
@@ -612,7 +612,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         };
         if let Some(lit_input) = lit_input {
             match tcx.at(expr.span).lit_to_const(lit_input) {
-                Ok(c) => return self.const_to_pat(Const::Ty(c), id, span, None).kind,
+                Ok(c) => return self.const_to_pat(Const::Ty(c), id, span).kind,
                 // If an error occurred, ignore that it's a literal
                 // and leave reporting the error up to const eval of
                 // the unevaluated constant below.
@@ -635,17 +635,13 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         if let Ok(Some(valtree)) =
             self.tcx.const_eval_resolve_for_typeck(self.param_env, ct, Some(span))
         {
-            let subpattern = self.const_to_pat(
-                Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)),
-                id,
-                span,
-                None,
-            );
+            let subpattern =
+                self.const_to_pat(Const::Ty(ty::Const::new_value(self.tcx, valtree, ty)), id, span);
             PatKind::InlineConstant { subpattern, def: def_id }
         } else {
             // If that fails, convert it to an opaque constant pattern.
             match tcx.const_eval_resolve(self.param_env, uneval, Some(span)) {
-                Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span, None).kind,
+                Ok(val) => self.const_to_pat(mir::Const::Val(val, ty), id, span).kind,
                 Err(ErrorHandled::TooGeneric(_)) => {
                     // If we land here it means the const can't be evaluated because it's `TooGeneric`.
                     let e = self.tcx.dcx().emit_err(ConstPatternDependsOnGenericParameter { span });
@@ -681,9 +677,7 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         let lit_input =
             LitToConstInput { lit: &lit.node, ty: self.typeck_results.expr_ty(expr), neg };
         match self.tcx.at(expr.span).lit_to_const(lit_input) {
-            Ok(constant) => {
-                self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span, None).kind
-            }
+            Ok(constant) => self.const_to_pat(Const::Ty(constant), expr.hir_id, lit.span).kind,
             Err(LitToConstError::Reported(e)) => PatKind::Error(e),
             Err(LitToConstError::TypeError) => bug!("lower_lit: had type error"),
         }
diff --git a/library/core/src/num/nonzero.rs b/library/core/src/num/nonzero.rs
index 1124719fc8df1..8cbbc2aa1a24c 100644
--- a/library/core/src/num/nonzero.rs
+++ b/library/core/src/num/nonzero.rs
@@ -35,7 +35,7 @@ mod private {
 pub trait ZeroablePrimitive: Sized + Copy + private::Sealed {}
 
 macro_rules! impl_zeroable_primitive {
-    ($NonZero:ident ( $primitive:ty )) => {
+    ($primitive:ty) => {
         #[unstable(
             feature = "nonzero_internals",
             reason = "implementation detail which may disappear or be replaced at any time",
@@ -52,18 +52,18 @@ macro_rules! impl_zeroable_primitive {
     };
 }
 
-impl_zeroable_primitive!(NonZeroU8(u8));
-impl_zeroable_primitive!(NonZeroU16(u16));
-impl_zeroable_primitive!(NonZeroU32(u32));
-impl_zeroable_primitive!(NonZeroU64(u64));
-impl_zeroable_primitive!(NonZeroU128(u128));
-impl_zeroable_primitive!(NonZeroUsize(usize));
-impl_zeroable_primitive!(NonZeroI8(i8));
-impl_zeroable_primitive!(NonZeroI16(i16));
-impl_zeroable_primitive!(NonZeroI32(i32));
-impl_zeroable_primitive!(NonZeroI64(i64));
-impl_zeroable_primitive!(NonZeroI128(i128));
-impl_zeroable_primitive!(NonZeroIsize(isize));
+impl_zeroable_primitive!(u8);
+impl_zeroable_primitive!(u16);
+impl_zeroable_primitive!(u32);
+impl_zeroable_primitive!(u64);
+impl_zeroable_primitive!(u128);
+impl_zeroable_primitive!(usize);
+impl_zeroable_primitive!(i8);
+impl_zeroable_primitive!(i16);
+impl_zeroable_primitive!(i32);
+impl_zeroable_primitive!(i64);
+impl_zeroable_primitive!(i128);
+impl_zeroable_primitive!(isize);
 
 /// A value that is known not to equal zero.
 ///
@@ -83,6 +83,90 @@ impl_zeroable_primitive!(NonZeroIsize(isize));
 #[rustc_diagnostic_item = "NonZero"]
 pub struct NonZero<T: ZeroablePrimitive>(T);
 
+impl<T> NonZero<T>
+where
+    T: ZeroablePrimitive,
+{
+    /// Creates a non-zero if the given value is not zero.
+    #[stable(feature = "nonzero", since = "1.28.0")]
+    #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")]
+    #[rustc_allow_const_fn_unstable(const_refs_to_cell)]
+    #[must_use]
+    #[inline]
+    pub const fn new(n: T) -> Option<Self> {
+        // SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
+        //         the same layout and size as `T`, with `0` representing `None`.
+        unsafe { crate::mem::transmute_copy(&n) }
+    }
+
+    /// Creates a non-zero without checking whether the value is non-zero.
+    /// This results in undefined behaviour if the value is zero.
+    ///
+    /// # Safety
+    ///
+    /// The value must not be zero.
+    #[stable(feature = "nonzero", since = "1.28.0")]
+    #[rustc_const_stable(feature = "nonzero", since = "1.28.0")]
+    #[must_use]
+    #[inline]
+    pub const unsafe fn new_unchecked(n: T) -> Self {
+        match Self::new(n) {
+            Some(n) => n,
+            None => {
+                // SAFETY: The caller guarantees that `n` is non-zero, so this is unreachable.
+                unsafe {
+                    crate::intrinsics::assert_unsafe_precondition!(
+                        "NonZero::new_unchecked requires the argument to be non-zero",
+                        () => false
+                    );
+
+                    crate::hint::unreachable_unchecked()
+                }
+            }
+        }
+    }
+
+    /// Converts a reference to a non-zero mutable reference
+    /// if the referenced value is not zero.
+    #[unstable(feature = "nonzero_from_mut", issue = "106290")]
+    #[must_use]
+    #[inline]
+    pub fn from_mut(n: &mut T) -> Option<&mut Self> {
+        // SAFETY: Memory layout optimization guarantees that `Option<NonZero<T>>` has
+        //         the same layout and size as `T`, with `0` representing `None`.
+        let opt_n = unsafe { &mut *(n as *mut T as *mut Option<Self>) };
+
+        opt_n.as_mut()
+    }
+
+    /// Converts a mutable reference to a non-zero mutable reference
+    /// without checking whether the referenced value is non-zero.
+    /// This results in undefined behavior if the referenced value is zero.
+    ///
+    /// # Safety
+    ///
+    /// The referenced value must not be zero.
+    #[unstable(feature = "nonzero_from_mut", issue = "106290")]
+    #[must_use]
+    #[inline]
+    pub unsafe fn from_mut_unchecked(n: &mut T) -> &mut Self {
+        match Self::from_mut(n) {
+            Some(n) => n,
+            None => {
+                // SAFETY: The caller guarantees that `n` references a value that is non-zero, so this is unreachable.
+                unsafe {
+                    crate::intrinsics::assert_unsafe_precondition!(
+                      "NonZero::from_mut_unchecked requires the argument to dereference as non-zero",
+                        () => false
+                    );
+
+                    crate::hint::unreachable_unchecked()
+                }
+            }
+        }
+    }
+}
+
 macro_rules! impl_nonzero_fmt {
     ( #[$stability: meta] ( $( $Trait: ident ),+ ) for $Ty: ident ) => {
         $(
@@ -100,7 +184,6 @@ macro_rules! impl_nonzero_fmt {
 macro_rules! nonzero_integer {
     (
         #[$stability:meta]
-        #[$const_new_unchecked_stability:meta]
         Self = $Ty:ident,
         Primitive = $signedness:ident $Int:ident,
         $(UnsignedNonZero = $UnsignedNonZero:ident,)?
@@ -143,74 +226,6 @@ macro_rules! nonzero_integer {
         pub type $Ty = NonZero<$Int>;
 
         impl $Ty {
-            /// Creates a non-zero without checking whether the value is non-zero.
-            /// This results in undefined behaviour if the value is zero.
-            ///
-            /// # Safety
-            ///
-            /// The value must not be zero.
-            #[$stability]
-            #[$const_new_unchecked_stability]
-            #[must_use]
-            #[inline]
-            pub const unsafe fn new_unchecked(n: $Int) -> Self {
-                crate::panic::debug_assert_nounwind!(
-                    n != 0,
-                    concat!(stringify!($Ty), "::new_unchecked requires a non-zero argument")
-                );
-                // SAFETY: this is guaranteed to be safe by the caller.
-                unsafe {
-                    Self(n)
-                }
-            }
-
-            /// Creates a non-zero if the given value is not zero.
-            #[$stability]
-            #[rustc_const_stable(feature = "const_nonzero_int_methods", since = "1.47.0")]
-            #[must_use]
-            #[inline]
-            pub const fn new(n: $Int) -> Option<Self> {
-                if n != 0 {
-                    // SAFETY: we just checked that there's no `0`
-                    Some(unsafe { Self(n) })
-                } else {
-                    None
-                }
-            }
-
-            /// Converts a primitive mutable reference to a non-zero mutable reference
-            /// without checking whether the referenced value is non-zero.
-            /// This results in undefined behavior if `*n` is zero.
-            ///
-            /// # Safety
-            /// The referenced value must not be currently zero.
-            #[unstable(feature = "nonzero_from_mut", issue = "106290")]
-            #[must_use]
-            #[inline]
-            pub unsafe fn from_mut_unchecked(n: &mut $Int) -> &mut Self {
-                // SAFETY: Self is repr(transparent), and the value is assumed to be non-zero.
-                unsafe {
-                    let n_alias = &mut *n;
-                    core::intrinsics::assert_unsafe_precondition!(
-                        concat!(stringify!($Ty), "::from_mut_unchecked requires the argument to dereference as non-zero"),
-                        (n_alias: &mut $Int) => *n_alias != 0
-                    );
-                    &mut *(n as *mut $Int as *mut Self)
-                }
-            }
-
-            /// Converts a primitive mutable reference to a non-zero mutable reference
-            /// if the referenced integer is not zero.
-            #[unstable(feature = "nonzero_from_mut", issue = "106290")]
-            #[must_use]
-            #[inline]
-            pub fn from_mut(n: &mut $Int) -> Option<&mut Self> {
-                // SAFETY: Self is repr(transparent), and the value is non-zero.
-                // As long as the returned reference is alive,
-                // the user cannot `*n = 0` directly.
-                (*n != 0).then(|| unsafe { &mut *(n as *mut $Int as *mut Self) })
-            }
-
             /// Returns the value as a primitive type.
             #[$stability]
             #[inline]
@@ -724,7 +739,6 @@ macro_rules! nonzero_integer {
     (Self = $Ty:ident, Primitive = unsigned $Int:ident $(,)?) => {
         nonzero_integer! {
             #[stable(feature = "nonzero", since = "1.28.0")]
-            #[rustc_const_stable(feature = "nonzero", since = "1.28.0")]
             Self = $Ty,
             Primitive = unsigned $Int,
             UnsignedPrimitive = $Int,
@@ -735,7 +749,6 @@ macro_rules! nonzero_integer {
     (Self = $Ty:ident, Primitive = signed $Int:ident, $($rest:tt)*) => {
         nonzero_integer! {
             #[stable(feature = "signed_nonzero", since = "1.34.0")]
-            #[rustc_const_stable(feature = "signed_nonzero", since = "1.34.0")]
             Self = $Ty,
             Primitive = signed $Int,
             $($rest)*
diff --git a/library/proc_macro/src/bridge/client.rs b/library/proc_macro/src/bridge/client.rs
index 52a08cad9110f..9255c3abc8a02 100644
--- a/library/proc_macro/src/bridge/client.rs
+++ b/library/proc_macro/src/bridge/client.rs
@@ -3,6 +3,7 @@
 use super::*;
 
 use std::marker::PhantomData;
+use std::sync::atomic::AtomicU32;
 
 macro_rules! define_handles {
     (
@@ -12,8 +13,8 @@ macro_rules! define_handles {
         #[repr(C)]
         #[allow(non_snake_case)]
         pub struct HandleCounters {
-            $($oty: AtomicUsize,)*
-            $($ity: AtomicUsize,)*
+            $($oty: AtomicU32,)*
+            $($ity: AtomicU32,)*
         }
 
         impl HandleCounters {
@@ -21,8 +22,8 @@ macro_rules! define_handles {
             // a wrapper `fn` pointer, once `const fn` can reference `static`s.
             extern "C" fn get() -> &'static Self {
                 static COUNTERS: HandleCounters = HandleCounters {
-                    $($oty: AtomicUsize::new(1),)*
-                    $($ity: AtomicUsize::new(1),)*
+                    $($oty: AtomicU32::new(1),)*
+                    $($ity: AtomicU32::new(1),)*
                 };
                 &COUNTERS
             }
diff --git a/library/proc_macro/src/bridge/handle.rs b/library/proc_macro/src/bridge/handle.rs
index 00954107b7769..b3a763069974f 100644
--- a/library/proc_macro/src/bridge/handle.rs
+++ b/library/proc_macro/src/bridge/handle.rs
@@ -4,7 +4,7 @@ use std::collections::BTreeMap;
 use std::hash::Hash;
 use std::num::NonZeroU32;
 use std::ops::{Index, IndexMut};
-use std::sync::atomic::{AtomicUsize, Ordering};
+use std::sync::atomic::{AtomicU32, Ordering};
 
 use super::fxhash::FxHashMap;
 
@@ -13,12 +13,12 @@ pub(super) type Handle = NonZeroU32;
 /// A store that associates values of type `T` with numeric handles. A value can
 /// be looked up using its handle.
 pub(super) struct OwnedStore<T: 'static> {
-    counter: &'static AtomicUsize,
+    counter: &'static AtomicU32,
     data: BTreeMap<Handle, T>,
 }
 
 impl<T> OwnedStore<T> {
-    pub(super) fn new(counter: &'static AtomicUsize) -> Self {
+    pub(super) fn new(counter: &'static AtomicU32) -> Self {
         // Ensure the handle counter isn't 0, which would panic later,
         // when `NonZeroU32::new` (aka `Handle::new`) is called in `alloc`.
         assert_ne!(counter.load(Ordering::SeqCst), 0);
@@ -30,7 +30,7 @@ impl<T> OwnedStore<T> {
 impl<T> OwnedStore<T> {
     pub(super) fn alloc(&mut self, x: T) -> Handle {
         let counter = self.counter.fetch_add(1, Ordering::SeqCst);
-        let handle = Handle::new(counter as u32).expect("`proc_macro` handle counter overflowed");
+        let handle = Handle::new(counter).expect("`proc_macro` handle counter overflowed");
         assert!(self.data.insert(handle, x).is_none());
         handle
     }
@@ -60,7 +60,7 @@ pub(super) struct InternedStore<T: 'static> {
 }
 
 impl<T: Copy + Eq + Hash> InternedStore<T> {
-    pub(super) fn new(counter: &'static AtomicUsize) -> Self {
+    pub(super) fn new(counter: &'static AtomicU32) -> Self {
         InternedStore { owned: OwnedStore::new(counter), interner: FxHashMap::default() }
     }
 
diff --git a/library/proc_macro/src/bridge/mod.rs b/library/proc_macro/src/bridge/mod.rs
index 75bf3329786a4..55e24b6491c79 100644
--- a/library/proc_macro/src/bridge/mod.rs
+++ b/library/proc_macro/src/bridge/mod.rs
@@ -16,7 +16,6 @@ use std::mem;
 use std::ops::Bound;
 use std::ops::Range;
 use std::panic;
-use std::sync::atomic::AtomicUsize;
 use std::sync::Once;
 use std::thread;
 
diff --git a/src/tools/miropt-test-tools/Cargo.toml b/src/tools/miropt-test-tools/Cargo.toml
index 8589a44cf1bab..09b4c7d16dce3 100644
--- a/src/tools/miropt-test-tools/Cargo.toml
+++ b/src/tools/miropt-test-tools/Cargo.toml
@@ -4,4 +4,3 @@ version = "0.1.0"
 edition = "2021"
 
 [dependencies]
-regex = "1.0"
diff --git a/src/tools/miropt-test-tools/src/lib.rs b/src/tools/miropt-test-tools/src/lib.rs
index 7d60033c3e824..4317f23a82219 100644
--- a/src/tools/miropt-test-tools/src/lib.rs
+++ b/src/tools/miropt-test-tools/src/lib.rs
@@ -100,14 +100,19 @@ pub fn files_for_miropt_test(
             } else {
                 // Allow-list for file extensions that can be produced by MIR dumps.
                 // Other extensions can be added here, as needed by new dump flags.
-                let ext_re = regex::Regex::new(r#"(\.(mir|dot))$"#).unwrap();
-                let cap = ext_re.captures_iter(test_name).next().unwrap_or_else(|| {
-                    panic!("in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}")
-                });
-                let extension = cap.get(1).unwrap().as_str();
+                static ALLOWED_EXT: &[&str] = &["mir", "dot"];
+                let Some((test_name_wo_ext, test_name_ext)) = test_name.rsplit_once('.') else {
+                    panic!(
+                        "in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}, expected one of {ALLOWED_EXT:?}"
+                    )
+                };
+                if !ALLOWED_EXT.contains(&test_name_ext) {
+                    panic!(
+                        "in {testfile:?}:\nEMIT_MIR has an unrecognized extension: {test_name}, expected one of {ALLOWED_EXT:?}"
+                    )
+                }
 
-                expected_file =
-                    format!("{}{}{}", test_name.trim_end_matches(extension), suffix, extension,);
+                expected_file = format!("{}{}.{}", test_name_wo_ext, suffix, test_name_ext);
                 from_file = test_name.to_string();
                 assert!(test_names.next().is_none(), "two mir pass names specified for MIR dump");
                 to_file = None;
diff --git a/src/tools/tidy/src/style.rs b/src/tools/tidy/src/style.rs
index 8b0e80a94b0b3..bb5a796f19e2b 100644
--- a/src/tools/tidy/src/style.rs
+++ b/src/tools/tidy/src/style.rs
@@ -127,8 +127,10 @@ fn should_ignore(line: &str) -> bool {
     // Matches test annotations like `//~ ERROR text`.
     // This mirrors the regex in src/tools/compiletest/src/runtest.rs, please
     // update both if either are changed.
-    let re = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap();
-    re.is_match(line) || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a))
+    lazy_static::lazy_static! {
+        static ref ANNOTATION_RE: Regex = Regex::new("\\s*//(\\[.*\\])?~.*").unwrap();
+    }
+    ANNOTATION_RE.is_match(line) || ANNOTATIONS_TO_IGNORE.iter().any(|a| line.contains(a))
 }
 
 /// Returns `true` if `line` is allowed to be longer than the normal limit.
diff --git a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
index 7a374c5675ab9..8b427cff67780 100644
--- a/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt1.EarlyOtherwiseBranch.diff
@@ -51,13 +51,13 @@
 -     }
 - 
 -     bb3: {
-          StorageLive(_8);
-          _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           StorageLive(_9);
           _9 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
+          StorageLive(_8);
+          _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           _0 = const 0_u32;
-          StorageDead(_9);
           StorageDead(_8);
+          StorageDead(_9);
 -         goto -> bb4;
 +         goto -> bb3;
       }
diff --git a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
index 21f58a14a2b3f..b91a469225cd2 100644
--- a/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt2.EarlyOtherwiseBranch.diff
@@ -58,13 +58,13 @@
 - 
 -     bb4: {
 +     bb2: {
-          StorageLive(_9);
-          _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           StorageLive(_10);
           _10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
+          StorageLive(_9);
+          _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           _0 = const 0_u32;
-          StorageDead(_10);
           StorageDead(_9);
+          StorageDead(_10);
 -         goto -> bb6;
 +         goto -> bb4;
       }
diff --git a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
index e058c409cb596..cc16af721ca69 100644
--- a/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch.opt3.EarlyOtherwiseBranch.diff
@@ -51,13 +51,13 @@
 -     }
 - 
 -     bb3: {
-          StorageLive(_8);
-          _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           StorageLive(_9);
           _9 = (((_3.1: std::option::Option<bool>) as Some).0: bool);
+          StorageLive(_8);
+          _8 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           _0 = const 0_u32;
-          StorageDead(_9);
           StorageDead(_8);
+          StorageDead(_9);
 -         goto -> bb4;
 +         goto -> bb3;
       }
diff --git a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
index f98d68e6ffce3..eb8926d27ee87 100644
--- a/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_3_element_tuple.opt1.EarlyOtherwiseBranch.diff
@@ -69,16 +69,16 @@
   
 -     bb4: {
 +     bb3: {
-          StorageLive(_11);
-          _11 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
-          StorageLive(_12);
-          _12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
           StorageLive(_13);
           _13 = (((_4.2: std::option::Option<u32>) as Some).0: u32);
+          StorageLive(_12);
+          _12 = (((_4.1: std::option::Option<u32>) as Some).0: u32);
+          StorageLive(_11);
+          _11 = (((_4.0: std::option::Option<u32>) as Some).0: u32);
           _0 = const 0_u32;
-          StorageDead(_13);
-          StorageDead(_12);
           StorageDead(_11);
+          StorageDead(_12);
+          StorageDead(_13);
 -         goto -> bb5;
 +         goto -> bb4;
       }
diff --git a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
index 0c94794fa3ffe..79cf1c0e34ad5 100644
--- a/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_68867.try_sum.EarlyOtherwiseBranch.diff
@@ -116,12 +116,12 @@
       }
   
       bb6: {
-          StorageLive(_12);
-          _39 = deref_copy (_4.0: &ViewportPercentageLength);
-          _12 = (((*_39) as Vw).0: f32);
           StorageLive(_13);
-          _40 = deref_copy (_4.1: &ViewportPercentageLength);
-          _13 = (((*_40) as Vw).0: f32);
+          _39 = deref_copy (_4.1: &ViewportPercentageLength);
+          _13 = (((*_39) as Vw).0: f32);
+          StorageLive(_12);
+          _40 = deref_copy (_4.0: &ViewportPercentageLength);
+          _12 = (((*_40) as Vw).0: f32);
           StorageLive(_14);
           StorageLive(_15);
           _15 = _12;
@@ -132,18 +132,18 @@
           StorageDead(_15);
           _3 = ViewportPercentageLength::Vw(move _14);
           StorageDead(_14);
-          StorageDead(_13);
           StorageDead(_12);
+          StorageDead(_13);
           goto -> bb10;
       }
   
       bb7: {
-          StorageLive(_17);
-          _41 = deref_copy (_4.0: &ViewportPercentageLength);
-          _17 = (((*_41) as Vh).0: f32);
           StorageLive(_18);
-          _42 = deref_copy (_4.1: &ViewportPercentageLength);
-          _18 = (((*_42) as Vh).0: f32);
+          _41 = deref_copy (_4.1: &ViewportPercentageLength);
+          _18 = (((*_41) as Vh).0: f32);
+          StorageLive(_17);
+          _42 = deref_copy (_4.0: &ViewportPercentageLength);
+          _17 = (((*_42) as Vh).0: f32);
           StorageLive(_19);
           StorageLive(_20);
           _20 = _17;
@@ -154,18 +154,18 @@
           StorageDead(_20);
           _3 = ViewportPercentageLength::Vh(move _19);
           StorageDead(_19);
-          StorageDead(_18);
           StorageDead(_17);
+          StorageDead(_18);
           goto -> bb10;
       }
   
       bb8: {
-          StorageLive(_22);
-          _43 = deref_copy (_4.0: &ViewportPercentageLength);
-          _22 = (((*_43) as Vmin).0: f32);
           StorageLive(_23);
-          _44 = deref_copy (_4.1: &ViewportPercentageLength);
-          _23 = (((*_44) as Vmin).0: f32);
+          _43 = deref_copy (_4.1: &ViewportPercentageLength);
+          _23 = (((*_43) as Vmin).0: f32);
+          StorageLive(_22);
+          _44 = deref_copy (_4.0: &ViewportPercentageLength);
+          _22 = (((*_44) as Vmin).0: f32);
           StorageLive(_24);
           StorageLive(_25);
           _25 = _22;
@@ -176,18 +176,18 @@
           StorageDead(_25);
           _3 = ViewportPercentageLength::Vmin(move _24);
           StorageDead(_24);
-          StorageDead(_23);
           StorageDead(_22);
+          StorageDead(_23);
           goto -> bb10;
       }
   
       bb9: {
-          StorageLive(_27);
-          _45 = deref_copy (_4.0: &ViewportPercentageLength);
-          _27 = (((*_45) as Vmax).0: f32);
           StorageLive(_28);
-          _46 = deref_copy (_4.1: &ViewportPercentageLength);
-          _28 = (((*_46) as Vmax).0: f32);
+          _45 = deref_copy (_4.1: &ViewportPercentageLength);
+          _28 = (((*_45) as Vmax).0: f32);
+          StorageLive(_27);
+          _46 = deref_copy (_4.0: &ViewportPercentageLength);
+          _27 = (((*_46) as Vmax).0: f32);
           StorageLive(_29);
           StorageLive(_30);
           _30 = _27;
@@ -198,8 +198,8 @@
           StorageDead(_30);
           _3 = ViewportPercentageLength::Vmax(move _29);
           StorageDead(_29);
-          StorageDead(_28);
           StorageDead(_27);
+          StorageDead(_28);
           goto -> bb10;
       }
   
diff --git a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
index 09cdce718572e..af0337d0a7e71 100644
--- a/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
+++ b/tests/mir-opt/early_otherwise_branch_noopt.noopt1.EarlyOtherwiseBranch.diff
@@ -59,13 +59,13 @@
       }
   
       bb5: {
-          StorageLive(_9);
-          _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           StorageLive(_10);
           _10 = (((_3.1: std::option::Option<u32>) as Some).0: u32);
+          StorageLive(_9);
+          _9 = (((_3.0: std::option::Option<u32>) as Some).0: u32);
           _0 = const 0_u32;
-          StorageDead(_10);
           StorageDead(_9);
+          StorageDead(_10);
           goto -> bb8;
       }
   
diff --git a/tests/ui/box/unit/unique-object-noncopyable.stderr b/tests/ui/box/unit/unique-object-noncopyable.stderr
index 49547872d1a7b..8ea6edb48a7fc 100644
--- a/tests/ui/box/unit/unique-object-noncopyable.stderr
+++ b/tests/ui/box/unit/unique-object-noncopyable.stderr
@@ -12,6 +12,9 @@ LL |     let _z = y.clone();
            which is required by `Box<dyn Foo>: Clone`
            `dyn Foo: Clone`
            which is required by `Box<dyn Foo>: Clone`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following trait defines an item `clone`, perhaps you need to implement it:
+           candidate #1: `Clone`
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/box/unit/unique-pinned-nocopy.stderr b/tests/ui/box/unit/unique-pinned-nocopy.stderr
index d2bf72249c451..69428604b197f 100644
--- a/tests/ui/box/unit/unique-pinned-nocopy.stderr
+++ b/tests/ui/box/unit/unique-pinned-nocopy.stderr
@@ -10,9 +10,6 @@ LL |     let _j = i.clone();
    = note: the following trait bounds were not satisfied:
            `R: Clone`
            which is required by `Box<R>: Clone`
-   = help: items from traits can only be used if the trait is implemented and in scope
-   = note: the following trait defines an item `clone`, perhaps you need to implement it:
-           candidate #1: `Clone`
 help: consider annotating `R` with `#[derive(Clone)]`
    |
 LL + #[derive(Clone)]
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs
new file mode 100644
index 0000000000000..a6e68e1b7101c
--- /dev/null
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.rs
@@ -0,0 +1,12 @@
+// #120427
+// This test checks we won't suggest more than 3 span suggestions for cfg names
+//
+// check-pass
+// compile-flags: -Z unstable-options
+// compile-flags: --check-cfg=cfg(foo,values("value")) --check-cfg=cfg(bar,values("value")) --check-cfg=cfg(bee,values("value")) --check-cfg=cfg(cow,values("value"))
+
+#[cfg(value)]
+//~^ WARNING unexpected `cfg` condition name: `value`
+fn x() {}
+
+fn main() {}
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
new file mode 100644
index 0000000000000..82d471d715b83
--- /dev/null
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-duplicate.stderr
@@ -0,0 +1,13 @@
+warning: unexpected `cfg` condition name: `value`
+  --> $DIR/cfg-value-for-cfg-name-duplicate.rs:8:7
+   |
+LL | #[cfg(value)]
+   |       ^^^^^
+   |
+   = help: expected names are: `bar`, `bee`, `cow`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: to expect this configuration use `--check-cfg=cfg(value)`
+   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs
new file mode 100644
index 0000000000000..edde6244ed1a9
--- /dev/null
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.rs
@@ -0,0 +1,12 @@
+// #120427
+// This test checks that when a single cfg has a value for user's specified name
+//
+// check-pass
+// compile-flags: -Z unstable-options
+// compile-flags: --check-cfg=cfg(foo,values("my_value")) --check-cfg=cfg(bar,values("my_value"))
+
+#[cfg(my_value)]
+//~^ WARNING unexpected `cfg` condition name: `my_value`
+fn x() {}
+
+fn main() {}
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
new file mode 100644
index 0000000000000..b88ee71a156a2
--- /dev/null
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name-multiple.stderr
@@ -0,0 +1,21 @@
+warning: unexpected `cfg` condition name: `my_value`
+  --> $DIR/cfg-value-for-cfg-name-multiple.rs:8:7
+   |
+LL | #[cfg(my_value)]
+   |       ^^^^^^^^
+   |
+   = help: expected names are: `bar`, `debug_assertions`, `doc`, `doctest`, `foo`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: to expect this configuration use `--check-cfg=cfg(my_value)`
+   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+help: found config with similar value
+   |
+LL | #[cfg(foo = "my_value")]
+   |       ~~~~~~~~~~~~~~~~
+help: found config with similar value
+   |
+LL | #[cfg(bar = "my_value")]
+   |       ~~~~~~~~~~~~~~~~
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.rs b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs
new file mode 100644
index 0000000000000..7a0c345b7ca76
--- /dev/null
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.rs
@@ -0,0 +1,18 @@
+// #120427
+// This test checks that when a single cfg has a value for user's specified name
+// suggest to use `#[cfg(target_os = "linux")]` instead of `#[cfg(linux)]`
+//
+// check-pass
+// compile-flags: -Z unstable-options
+// compile-flags: --check-cfg=cfg()
+
+#[cfg(linux)]
+//~^ WARNING unexpected `cfg` condition name: `linux`
+fn x() {}
+
+// will not suggest if the cfg has a value
+#[cfg(linux = "os-name")]
+//~^ WARNING unexpected `cfg` condition name: `linux`
+fn y() {}
+
+fn main() {}
diff --git a/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
new file mode 100644
index 0000000000000..c044755142419
--- /dev/null
+++ b/tests/ui/check-cfg/cfg-value-for-cfg-name.stderr
@@ -0,0 +1,22 @@
+warning: unexpected `cfg` condition name: `linux`
+  --> $DIR/cfg-value-for-cfg-name.rs:9:7
+   |
+LL | #[cfg(linux)]
+   |       ^^^^^ help: found config with similar value: `target_os = "linux"`
+   |
+   = help: expected names are: `debug_assertions`, `doc`, `doctest`, `miri`, `overflow_checks`, `panic`, `proc_macro`, `relocation_model`, `sanitize`, `sanitizer_cfi_generalize_pointers`, `sanitizer_cfi_normalize_integers`, `target_abi`, `target_arch`, `target_endian`, `target_env`, `target_family`, `target_feature`, `target_has_atomic`, `target_has_atomic_equal_alignment`, `target_has_atomic_load_store`, `target_os`, `target_pointer_width`, `target_thread_local`, `target_vendor`, `test`, `unix`, `windows`
+   = help: to expect this configuration use `--check-cfg=cfg(linux)`
+   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+   = note: `#[warn(unexpected_cfgs)]` on by default
+
+warning: unexpected `cfg` condition name: `linux`
+  --> $DIR/cfg-value-for-cfg-name.rs:14:7
+   |
+LL | #[cfg(linux = "os-name")]
+   |       ^^^^^^^^^^^^^^^^^
+   |
+   = help: to expect this configuration use `--check-cfg=cfg(linux, values("os-name"))`
+   = note: see <https://doc.rust-lang.org/nightly/unstable-book/compiler-flags/check-cfg.html> for more information about checking conditional configuration
+
+warning: 2 warnings emitted
+
diff --git a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr
index c83ba41976bcd..8a2aaade66503 100644
--- a/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr
+++ b/tests/ui/closures/2229_closure_analysis/match/match-edge-cases_1.stderr
@@ -5,8 +5,19 @@ LL |             NUMBER_POINTER => (),
    |             ^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: `#[warn(pointer_structural_match)]` on by default
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/match-edge-cases_1.rs:29:13
+   |
+LL |             NUMBER_POINTER => (),
+   |             ^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
diff --git a/tests/ui/consts/const_in_pattern/accept_structural.rs b/tests/ui/consts/const_in_pattern/accept_structural.rs
index 1f56f581c0270..69b4e75c62236 100644
--- a/tests/ui/consts/const_in_pattern/accept_structural.rs
+++ b/tests/ui/consts/const_in_pattern/accept_structural.rs
@@ -63,4 +63,18 @@ fn main() {
 
     const ADDR_OF: &OND = &None;
     match &None { ADDR_OF => dbg!(ADDR_OF),  _ => panic!("whoops"), };
+
+    // These ones are more subtle: the final value is fine, but statically analyzing the expression
+    // that computes the value would likely (incorrectly) have us conclude that this may match on
+    // values that do not have structural equality.
+    const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
+    match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
+
+    const fn build() -> Option<NoDerive> { None }
+    const CALL: Option<NoDerive> = build();
+    match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
+
+    impl NoDerive { const fn none() -> Option<NoDerive> { None } }
+    const METHOD_CALL: Option<NoDerive> = NoDerive::none();
+    match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
 }
diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs
index a38731ceb8a86..ac89b7925ffec 100644
--- a/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs
+++ b/tests/ui/consts/const_in_pattern/custom-eq-branch-pass.rs
@@ -12,6 +12,7 @@ impl PartialEq for CustomEq {
 }
 
 #[derive(PartialEq, Eq)]
+#[allow(unused)]
 enum Foo {
     Bar,
     Baz,
@@ -21,7 +22,7 @@ enum Foo {
 const BAR_BAZ: Foo = if 42 == 42 {
     Foo::Bar
 } else {
-    Foo::Baz
+    Foo::Qux(CustomEq) // dead arm
 };
 
 fn main() {
diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs
deleted file mode 100644
index 34b1422dfb3cb..0000000000000
--- a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.rs
+++ /dev/null
@@ -1,38 +0,0 @@
-// check-pass
-
-struct CustomEq;
-
-impl Eq for CustomEq {}
-impl PartialEq for CustomEq {
-    fn eq(&self, _: &Self) -> bool {
-        false
-    }
-}
-
-#[derive(PartialEq, Eq)]
-enum Foo {
-    Bar,
-    Baz,
-    Qux(CustomEq),
-}
-
-// We know that `BAR_BAZ` will always be `Foo::Bar` and thus eligible for structural matching, but
-// dataflow will be more conservative.
-const BAR_BAZ: Foo = if 42 == 42 {
-    Foo::Bar
-} else {
-    Foo::Qux(CustomEq)
-};
-
-fn main() {
-    match Foo::Qux(CustomEq) {
-        BAR_BAZ => panic!(),
-        //~^ WARN must be annotated with `#[derive(PartialEq)]`
-        //~| NOTE the traits must be derived
-        //~| NOTE StructuralPartialEq.html for details
-        //~| WARN this was previously accepted
-        //~| NOTE see issue #73448
-        //~| NOTE `#[warn(nontrivial_structural_match)]` on by default
-        _ => {}
-    }
-}
diff --git a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr b/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr
deleted file mode 100644
index c473c00f8dbbd..0000000000000
--- a/tests/ui/consts/const_in_pattern/custom-eq-branch-warn.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-warning: to use a constant of type `CustomEq` in a pattern, the constant's initializer must be trivial or `CustomEq` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/custom-eq-branch-warn.rs:29:9
-   |
-LL |         BAR_BAZ => panic!(),
-   |         ^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-   = note: `#[warn(nontrivial_structural_match)]` on by default
-
-warning: 1 warning emitted
-
diff --git a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr
index 1546f23908c6f..bc1015c173426 100644
--- a/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr
+++ b/tests/ui/consts/const_in_pattern/issue-34784-match-on-non-int-raw-ptr.stderr
@@ -5,7 +5,7 @@ LL |         C => {}
    |         ^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 note: the lint level is defined here
   --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
    |
@@ -19,7 +19,7 @@ LL |         C_INNER => {}
    |         ^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9
@@ -28,7 +28,7 @@ LL |         D => {}
    |         ^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9
@@ -37,7 +37,67 @@ LL |         STR => {}
    |         ^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 error: aborting due to 4 previous errors
 
+Future incompatibility report: Future breakage diagnostic:
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:10:9
+   |
+LL |         C => {}
+   |         ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+note: the lint level is defined here
+  --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
+   |
+LL | #![deny(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:18:9
+   |
+LL |         C_INNER => {}
+   |         ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+note: the lint level is defined here
+  --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
+   |
+LL | #![deny(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:30:9
+   |
+LL |         D => {}
+   |         ^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+note: the lint level is defined here
+  --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
+   |
+LL | #![deny(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+error: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:36:9
+   |
+LL |         STR => {}
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+note: the lint level is defined here
+  --> $DIR/issue-34784-match-on-non-int-raw-ptr.rs:1:9
+   |
+LL | #![deny(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/consts/const_in_pattern/issue-44333.stderr b/tests/ui/consts/const_in_pattern/issue-44333.stderr
index 441aeecbc6d95..f5931f0cad08b 100644
--- a/tests/ui/consts/const_in_pattern/issue-44333.stderr
+++ b/tests/ui/consts/const_in_pattern/issue-44333.stderr
@@ -5,7 +5,7 @@ LL |         FOO => println!("foo"),
    |         ^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 note: the lint level is defined here
   --> $DIR/issue-44333.rs:3:9
    |
@@ -19,7 +19,37 @@ LL |         BAR => println!("bar"),
    |         ^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: 2 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-44333.rs:19:9
+   |
+LL |         FOO => println!("foo"),
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+note: the lint level is defined here
+  --> $DIR/issue-44333.rs:3:9
+   |
+LL | #![warn(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-44333.rs:21:9
+   |
+LL |         BAR => println!("bar"),
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+note: the lint level is defined here
+  --> $DIR/issue-44333.rs:3:9
+   |
+LL | #![warn(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/consts/const_in_pattern/issue-73431.stderr b/tests/ui/consts/const_in_pattern/issue-73431.stderr
deleted file mode 100644
index c82dea4aa50df..0000000000000
--- a/tests/ui/consts/const_in_pattern/issue-73431.stderr
+++ /dev/null
@@ -1 +0,0 @@
-WARN rustc_mir_build::thir::pattern::const_to_pat MIR const-checker found novel structural match violation. See #73448.
diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.rs b/tests/ui/consts/const_in_pattern/reject_non_structural.rs
index 196930baed5de..71d4138104db1 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_structural.rs
+++ b/tests/ui/consts/const_in_pattern/reject_non_structural.rs
@@ -100,5 +100,5 @@ fn main() {
     //~| NOTE the traits must be derived
     //~| NOTE StructuralPartialEq.html for details
     //~| WARN previously accepted by the compiler but is being phased out
-    //~| NOTE for more information, see issue #62411
+    //~| NOTE for more information, see
 }
diff --git a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr
index da32b6d698bb5..2c7aaf89aa787 100644
--- a/tests/ui/consts/const_in_pattern/reject_non_structural.stderr
+++ b/tests/ui/consts/const_in_pattern/reject_non_structural.stderr
@@ -86,7 +86,7 @@ LL |     match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops")
    |                             ^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 note: the lint level is defined here
@@ -97,3 +97,20 @@ LL | #![warn(indirect_structural_match)]
 
 error: aborting due to 9 previous errors; 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/reject_non_structural.rs:98:29
+   |
+LL |     match &Some(NoDerive) { ADDR_OF => dbg!(ADDR_OF), _ => panic!("whoops"), };
+   |                             ^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/reject_non_structural.rs:14:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs b/tests/ui/consts/const_in_pattern/warn_corner_cases.rs
deleted file mode 100644
index 75f1965921c91..0000000000000
--- a/tests/ui/consts/const_in_pattern/warn_corner_cases.rs
+++ /dev/null
@@ -1,41 +0,0 @@
-// run-pass
-
-// This test is checking our logic for structural match checking by enumerating
-// the different kinds of const expressions. This test is collecting cases where
-// we have accepted the const expression as a pattern in the past but we want
-// to begin warning the user that a future version of Rust may start rejecting
-// such const expressions.
-
-// The specific corner cases we are exploring here are instances where the
-// const-evaluator computes a value that *does* meet the conditions for
-// structural-match, but the const expression itself has abstractions (like
-// calls to const functions) that may fit better with a type-based analysis
-// rather than a commitment to a specific value.
-
-#![warn(indirect_structural_match)]
-
-#[derive(Copy, Clone, Debug)]
-struct NoDerive(#[allow(dead_code)] u32);
-
-// This impl makes `NoDerive` irreflexive.
-impl PartialEq for NoDerive { fn eq(&self, _: &Self) -> bool { false } }
-impl Eq for NoDerive { }
-
-fn main() {
-    const INDEX: Option<NoDerive> = [None, Some(NoDerive(10))][0];
-    match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
-    //~^ WARN must be annotated with `#[derive(PartialEq)]`
-    //~| WARN this was previously accepted
-
-    const fn build() -> Option<NoDerive> { None }
-    const CALL: Option<NoDerive> = build();
-    match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
-    //~^ WARN must be annotated with `#[derive(PartialEq)]`
-    //~| WARN this was previously accepted
-
-    impl NoDerive { const fn none() -> Option<NoDerive> { None } }
-    const METHOD_CALL: Option<NoDerive> = NoDerive::none();
-    match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
-    //~^ WARN must be annotated with `#[derive(PartialEq)]`
-    //~| WARN this was previously accepted
-}
diff --git a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr b/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr
deleted file mode 100644
index 8ffd035ebec61..0000000000000
--- a/tests/ui/consts/const_in_pattern/warn_corner_cases.stderr
+++ /dev/null
@@ -1,36 +0,0 @@
-warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/warn_corner_cases.rs:26:47
-   |
-LL |     match None { Some(_) => panic!("whoops"), INDEX => dbg!(INDEX), };
-   |                                               ^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-   = note: `#[warn(nontrivial_structural_match)]` on by default
-
-warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/warn_corner_cases.rs:32:47
-   |
-LL |     match None { Some(_) => panic!("whoops"), CALL => dbg!(CALL), };
-   |                                               ^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-warning: to use a constant of type `NoDerive` in a pattern, the constant's initializer must be trivial or `NoDerive` must be annotated with `#[derive(PartialEq)]`
-  --> $DIR/warn_corner_cases.rs:38:47
-   |
-LL |     match None { Some(_) => panic!("whoops"), METHOD_CALL => dbg!(METHOD_CALL), };
-   |                                               ^^^^^^^^^^^
-   |
-   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #73448 <https://github.com/rust-lang/rust/issues/73448>
-   = note: the traits must be derived, manual `impl`s are not sufficient
-   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
-
-warning: 3 warnings emitted
-
diff --git a/tests/ui/consts/issue-89088.stderr b/tests/ui/consts/issue-89088.stderr
new file mode 100644
index 0000000000000..d5c5f76b90a01
--- /dev/null
+++ b/tests/ui/consts/issue-89088.stderr
@@ -0,0 +1,17 @@
+Future incompatibility report: Future breakage diagnostic:
+warning: to use a constant of type `Cow<'_, str>` in a pattern, `Cow<'_, str>` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/issue-89088.rs:19:9
+   |
+LL |         FOO => todo!(),
+   |         ^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/issue-89088.rs:5:10
+   |
+LL | #![allow(indirect_structural_match)]
+   |          ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/derives/derive-assoc-type-not-impl.stderr b/tests/ui/derives/derive-assoc-type-not-impl.stderr
index 61268ffc7f852..13ba80243a5eb 100644
--- a/tests/ui/derives/derive-assoc-type-not-impl.stderr
+++ b/tests/ui/derives/derive-assoc-type-not-impl.stderr
@@ -15,9 +15,6 @@ note: trait bound `NotClone: Clone` was not satisfied
    |
 LL | #[derive(Clone)]
    |          ^^^^^ unsatisfied trait bound introduced in this `derive` macro
-   = help: items from traits can only be used if the trait is implemented and in scope
-   = note: the following trait defines an item `clone`, perhaps you need to implement it:
-           candidate #1: `Clone`
 help: consider annotating `NotClone` with `#[derive(Clone)]`
    |
 LL + #[derive(Clone)]
diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
index add4d58f86a0d..92ce4a0970f36 100644
--- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
+++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.rs
@@ -5,7 +5,7 @@ trait X {
     type Y<T>;
 }
 
-trait M {
+trait M { //~ NOTE
     fn f(&self) {}
 }
 
diff --git a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
index 1dd463f996ce6..61512dd46582d 100644
--- a/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
+++ b/tests/ui/generic-associated-types/method-unsatisfied-assoc-type-predicate.stderr
@@ -14,6 +14,12 @@ LL | impl<T: X<Y<i32> = i32>> M for T {}
    |           ^^^^^^^^^^^^   -     -
    |           |
    |           unsatisfied trait bound introduced here
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `M` defines an item `f`, perhaps you need to implement it
+  --> $DIR/method-unsatisfied-assoc-type-predicate.rs:8:1
+   |
+LL | trait M {
+   | ^^^^^^^
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
index 73870703cfbac..699a4ecc42bb9 100644
--- a/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
+++ b/tests/ui/higher-ranked/trait-bounds/issue-30786.stderr
@@ -15,6 +15,12 @@ note: the following trait bounds were not satisfied:
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `StreamExt` defines an item `filterx`, perhaps you need to implement it
+  --> $DIR/issue-30786.rs:66:1
+   |
+LL | pub trait StreamExt
+   | ^^^^^^^^^^^^^^^^^^^
 
 error[E0599]: the method `countx` exists for struct `Filter<Map<Repeat, fn(&u64) -> &u64 {identity::<u64>}>, {closure@issue-30786.rs:131:30}>`, but its trait bounds were not satisfied
   --> $DIR/issue-30786.rs:132:24
@@ -33,6 +39,12 @@ note: the following trait bounds were not satisfied:
    |
 LL | impl<T> StreamExt for T where for<'a> &'a mut T: Stream {}
    |         ---------     -                          ^^^^^^ unsatisfied trait bound introduced here
+   = help: items from traits can only be used if the trait is implemented and in scope
+note: `StreamExt` defines an item `countx`, perhaps you need to implement it
+  --> $DIR/issue-30786.rs:66:1
+   |
+LL | pub trait StreamExt
+   | ^^^^^^^^^^^^^^^^^^^
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/methods/method-call-err-msg.stderr b/tests/ui/methods/method-call-err-msg.stderr
index f431085745405..6df49e432a13a 100644
--- a/tests/ui/methods/method-call-err-msg.stderr
+++ b/tests/ui/methods/method-call-err-msg.stderr
@@ -63,8 +63,9 @@ LL | |      .take()
 note: the trait `Iterator` must be implemented
   --> $SRC_DIR/core/src/iter/traits/iterator.rs:LL:COL
    = help: items from traits can only be used if the trait is implemented and in scope
-   = note: the following trait defines an item `take`, perhaps you need to implement it:
-           candidate #1: `Iterator`
+   = note: the following traits define an item `take`, perhaps you need to implement one of them:
+           candidate #1: `std::io::Read`
+           candidate #2: `Iterator`
 
 error[E0061]: this method takes 3 arguments but 0 arguments were supplied
   --> $DIR/method-call-err-msg.rs:21:7
diff --git a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs
index 2b349f0ed5f99..253b2d8890100 100644
--- a/tests/ui/pattern/bindings-after-at/bind-by-copy.rs
+++ b/tests/ui/pattern/bindings-after-at/bind-by-copy.rs
@@ -1,13 +1,30 @@
 // run-pass
+#![allow(unused)]
 
 // Test copy
 
-struct A { a: i32, b: i32 }
-struct B { a: i32, b: C }
-struct D { a: i32, d: C }
-#[derive(Copy,Clone)]
-struct C { c: i32 }
+struct A {
+    a: i32,
+    b: i32,
+}
+struct B {
+    a: i32,
+    b: C,
+}
+struct D {
+    a: i32,
+    d: C,
+}
+#[derive(Copy, Clone)]
+struct C {
+    c: i32,
+}
+enum E {
+    E { a: i32, e: C },
+    NotE,
+}
 
+#[rustfmt::skip]
 pub fn main() {
     match (A {a: 10, b: 20}) {
         x@A {a, b: 20} => { assert!(x.a == 10); assert!(a == 10); }
@@ -23,6 +40,23 @@ pub fn main() {
     y.d.c = 30;
     assert_eq!(d.c, 20);
 
+    match (E::E { a: 10, e: C { c: 20 } }) {
+        x @ E::E{ a, e: C { c } } => {
+            assert!(matches!(x, E::E { a: 10, e: C { c: 20 } }));
+            assert!(a == 10);
+            assert!(c == 20);
+        }
+        _ => panic!(),
+    }
+    match (E::E { a: 10, e: C { c: 20 } }) {
+        mut x @ E::E{ a, e: C { mut c } } => {
+            x = E::NotE;
+            c += 30;
+            assert_eq!(c, 50);
+        }
+        _ => panic!(),
+    }
+
     let some_b = Some(B { a: 10, b: C { c: 20 } });
 
     // in irrefutable pattern
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
index a61d682152407..bfb3c3b20d63c 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.rs
@@ -15,8 +15,8 @@ fn main() {
     let a @ (b, c) = (u(), u()); //~ ERROR use of partially moved value
 
     match Ok(U) {
-        a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of moved value
-                                     //~^ ERROR use of moved value
+        a @ Ok(b) | a @ Err(b) => {} //~ ERROR use of partially moved value
+                                     //~^ ERROR use of partially moved value
     }
 
     fn fun(a @ b: U) {} //~ ERROR use of moved value
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
index 324897151124c..ba0622090bb7d 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
+++ b/tests/ui/pattern/bindings-after-at/borrowck-move-and-move.stderr
@@ -40,35 +40,33 @@ help: borrow this binding in the pattern to avoid moving the value
 LL |     let ref a @ (b, ref c) = (u(), u());
    |         +++         +++
 
-error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:18:16
+error[E0382]: use of partially moved value
+  --> $DIR/borrowck-move-and-move.rs:18:9
    |
-LL |     match Ok(U) {
-   |           ----- move occurs because value has type `Result<U, U>`, which does not implement the `Copy` trait
 LL |         a @ Ok(b) | a @ Err(b) => {}
-   |         -      ^ value used here after move
+   |         ^      - value partially moved here
    |         |
-   |         value moved here
+   |         value used here after partial move
    |
+   = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 help: borrow this binding in the pattern to avoid moving the value
    |
-LL |         ref a @ Ok(b) | a @ Err(b) => {}
-   |         +++
+LL |         ref a @ Ok(ref b) | a @ Err(b) => {}
+   |         +++        +++
 
-error[E0382]: use of moved value
-  --> $DIR/borrowck-move-and-move.rs:18:29
+error[E0382]: use of partially moved value
+  --> $DIR/borrowck-move-and-move.rs:18:21
    |
-LL |     match Ok(U) {
-   |           ----- move occurs because value has type `Result<U, U>`, which does not implement the `Copy` trait
 LL |         a @ Ok(b) | a @ Err(b) => {}
-   |                     -       ^ value used here after move
+   |                     ^       - value partially moved here
    |                     |
-   |                     value moved here
+   |                     value used here after partial move
    |
+   = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 help: borrow this binding in the pattern to avoid moving the value
    |
-LL |         a @ Ok(b) | ref a @ Err(b) => {}
-   |                     +++
+LL |         a @ Ok(b) | ref a @ Err(ref b) => {}
+   |                     +++         +++
 
 error[E0382]: use of partially moved value
   --> $DIR/borrowck-move-and-move.rs:25:9
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs
index 06dc6e1c4da1f..ac57838f0298f 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref-inverse.rs
@@ -48,19 +48,17 @@ fn main() {
         //~^ ERROR borrow of moved value
         //~| ERROR borrow of moved value
         //~| ERROR borrow of moved value
-        //~| ERROR use of moved value
+        //~| ERROR use of partially moved value
         None => {}
     }
     match Some([U, U]) {
         mut a @ Some([ref b, ref mut c]) => {}
         //~^ ERROR borrow of moved value
-        //~| ERROR borrow of moved value
         None => {}
     }
     match Some(u()) {
         a @ Some(ref b) => {}
         //~^ ERROR borrow of moved value
-        //~| ERROR borrow of moved value
         None => {}
     }
     match Some((u(), u())) {
@@ -68,13 +66,12 @@ fn main() {
         //~^ ERROR borrow of moved value
         //~| ERROR borrow of moved value
         //~| ERROR borrow of moved value
-        //~| ERROR use of moved value
+        //~| ERROR use of partially moved value
         None => {}
     }
     match Some([u(), u()]) {
         mut a @ Some([ref b, ref mut c]) => {}
         //~^ ERROR borrow of moved value
-        //~| ERROR borrow of moved value
         None => {}
     }
 }
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 1ed019f0a6927..fd7a51388bc10 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
@@ -215,7 +215,7 @@ LL |         ref mut a @ Some([ref b, ref mut c]) => {}
    |         +++
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:60:9
    |
 LL |         a @ Some(ref b) => {}
    |         ^        ----- value borrowed here after move
@@ -229,7 +229,7 @@ LL |         ref a @ Some(ref b) => {}
    |         +++
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:9
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         ^                 ---------      ----- value borrowed here after move
@@ -244,7 +244,7 @@ LL |         ref a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |         +++
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:19
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:19
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                   ^^^^^   --------- value borrowed here after move
@@ -258,7 +258,7 @@ LL |         a @ Some((ref mut b @ ref mut c, d @ ref e)) => {}
    |                   +++
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:38
    |
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
    |                                      ^   ----- value borrowed here after move
@@ -272,7 +272,7 @@ LL |         a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
    |                                      +++
 
 error: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:9
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:73:9
    |
 LL |         mut a @ Some([ref b, ref mut c]) => {}
    |         ^^^^^         -----  --------- value borrowed here after move
@@ -314,66 +314,33 @@ help: borrow this binding in the pattern to avoid moving the value
 LL |     let ref a @ (mut b @ ref mut c, ref d @ ref e) = (u(), u());
    |         +++                         +++
 
-error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:38
+error[E0382]: use of partially moved value
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:47:9
    |
-LL |     match Some((U, U)) {
-   |           ------------ move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |         - value moved here           ^ value used here after move
-   |
-help: borrow this binding in the pattern to avoid moving the value
-   |
-LL |         ref a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |         +++
-
-error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:55:30
-   |
-LL |     match Some([U, U]) {
-   |           ------------ move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
-LL |         mut a @ Some([ref b, ref mut c]) => {}
-   |         -----                ^^^^^^^^^ value borrowed here after move
-   |         |
-   |         value moved here
-
-error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:61:18
-   |
-LL |     match Some(u()) {
-   |           --------- move occurs because value has type `Option<U>`, which does not implement the `Copy` trait
-LL |         a @ Some(ref b) => {}
-   |         -        ^^^^^ value borrowed here after move
+   |         ^                            - value partially moved here
    |         |
-   |         value moved here
+   |         value used here after partial move
    |
+   = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 help: borrow this binding in the pattern to avoid moving the value
    |
-LL |         ref a @ Some(ref b) => {}
-   |         +++
+LL |         ref a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
+   |         +++                              +++
 
-error[E0382]: use of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:67:38
+error[E0382]: use of partially moved value
+  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:65:9
    |
-LL |     match Some((u(), u())) {
-   |           ---------------- move occurs because value has type `Option<(U, U)>`, which does not implement the `Copy` trait
 LL |         a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |         - value moved here           ^ value used here after move
+   |         ^                            - value partially moved here
+   |         |
+   |         value used here after partial move
    |
+   = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 help: borrow this binding in the pattern to avoid moving the value
    |
-LL |         ref a @ Some((mut b @ ref mut c, d @ ref e)) => {}
-   |         +++
-
-error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:75:30
-   |
-LL |     match Some([u(), u()]) {
-   |           ---------------- move occurs because value has type `Option<[U; 2]>`, which does not implement the `Copy` trait
-LL |         mut a @ Some([ref b, ref mut c]) => {}
-   |         -----                ^^^^^^^^^ value borrowed here after move
-   |         |
-   |         value moved here
+LL |         ref a @ Some((mut b @ ref mut c, ref d @ ref e)) => {}
+   |         +++                              +++
 
 error: borrow of moved value
   --> $DIR/borrowck-pat-by-move-and-ref-inverse.rs:11:11
@@ -457,6 +424,6 @@ help: borrow this binding in the pattern to avoid moving the value
 LL |     fn f3(ref a @ [ref mut b, ref c]: [U; 2]) {}
    |           +++
 
-error: aborting due to 33 previous errors
+error: aborting due to 30 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs
index 0b0a7801049fe..095c871e8d205 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-by-move-and-ref.rs
@@ -58,11 +58,13 @@ fn main() {
     match Some([U, U]) {
         ref mut a @ Some([b, mut c]) => {}
         //~^ ERROR cannot move out of value because it is borrowed
+        //~| ERROR borrow of partially moved value
         None => {}
     }
     match Some(u()) {
         ref a @ Some(b) => {}
         //~^ ERROR cannot move out of value because it is borrowed
+        //~| ERROR borrow of partially moved value
         None => {}
     }
     match Some((u(), u())) {
@@ -77,6 +79,7 @@ fn main() {
     match Some([u(), u()]) {
         ref mut a @ Some([b, mut c]) => {}
         //~^ ERROR cannot move out of value because it is borrowed
+        //~| ERROR borrow of partially moved value
         None => {}
     }
 }
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 c8c4d9b8fdb13..45ada8fd51606 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
@@ -125,7 +125,7 @@ LL |         ref mut a @ Some([b, mut c]) => {}
    |         value is mutably borrowed by `a` here
 
 error: cannot move out of value because it is borrowed
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:64:9
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:65:9
    |
 LL |         ref a @ Some(b) => {}
    |         ^^^^^        - value is moved into `b` here
@@ -133,7 +133,7 @@ LL |         ref a @ Some(b) => {}
    |         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
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:9
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         ^^^^^                 -----          - value is moved into `e` here
@@ -142,7 +142,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |         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:23
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       ^^^^^   ----- value is moved into `c` here
@@ -150,7 +150,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       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
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      ^^^^^   - value is moved into `e` here
@@ -158,7 +158,7 @@ LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      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
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9
    |
 LL |         ref mut a @ Some([b, mut c]) => {}
    |         ^^^^^^^^^         -  ----- value is moved into `c` here
@@ -236,8 +236,36 @@ help: borrow this binding in the pattern to avoid moving the value
 LL |     let ref mut a @ [b, ref mut c] = [u(), u()];
    |                         +++
 
+error[E0382]: borrow of partially moved value
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:59:9
+   |
+LL |         ref mut a @ Some([b, mut c]) => {}
+   |         ^^^^^^^^^            ----- value partially moved here
+   |         |
+   |         value borrowed here after partial move
+   |
+   = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref mut a @ Some([b, ref mut c]) => {}
+   |                              +++
+
+error[E0382]: borrow of partially moved value
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:65:9
+   |
+LL |         ref a @ Some(b) => {}
+   |         ^^^^^        - value partially moved here
+   |         |
+   |         value borrowed here after partial move
+   |
+   = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref a @ Some(ref b) => {}
+   |                      +++
+
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:69:23
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:23
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                       ^^^^^   ----- value moved here
@@ -251,7 +279,7 @@ LL |         ref a @ Some((ref b @ ref mut c, ref d @ e)) => {}
    |                               +++
 
 error[E0382]: borrow of moved value
-  --> $DIR/borrowck-pat-by-move-and-ref.rs:69:38
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:71:38
    |
 LL |         ref a @ Some((ref b @ mut c, ref d @ e)) => {}
    |                                      ^^^^^   - value moved here
@@ -264,6 +292,20 @@ help: borrow this binding in the pattern to avoid moving the value
 LL |         ref a @ Some((ref b @ mut c, ref d @ ref e)) => {}
    |                                              +++
 
+error[E0382]: borrow of partially moved value
+  --> $DIR/borrowck-pat-by-move-and-ref.rs:80:9
+   |
+LL |         ref mut a @ Some([b, mut c]) => {}
+   |         ^^^^^^^^^            ----- value partially moved here
+   |         |
+   |         value borrowed here after partial move
+   |
+   = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
+help: borrow this binding in the pattern to avoid moving the value
+   |
+LL |         ref mut a @ Some([b, ref mut c]) => {}
+   |                              +++
+
 error: cannot move out of value because it is borrowed
   --> $DIR/borrowck-pat-by-move-and-ref.rs:11:11
    |
@@ -345,6 +387,6 @@ LL |     fn f3(ref mut a @ [b, mut c]: [U; 2]) {}
    |
    = note: partial move occurs because value has type `U`, which does not implement the `Copy` trait
 
-error: aborting due to 36 previous errors
+error: aborting due to 39 previous errors
 
 For more information about this error, try `rustc --explain E0382`.
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
index 6bc0d346c111a..98f316dd74bdd 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-and-ref.rs
@@ -7,7 +7,7 @@ fn main() {
     match &mut Some(1) {
         ref mut z @ &mut Some(ref a) => {
         //~^ ERROR cannot borrow value as immutable because it is also borrowed as mutable
-        //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
+        //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
             **z = None;
             println!("{}", *a);
         }
@@ -76,8 +76,8 @@ fn main() {
         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
             //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
             //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
-            //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
-            //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
+            //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
+            //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
             *b = U;
             drop(a);
         }
@@ -87,6 +87,8 @@ fn main() {
         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false } => {}
         //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
         //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
+        //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
+        //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
         //~| ERROR cannot assign to `*b`, as it is immutable for the pattern guard
         _ => {}
     }
@@ -101,6 +103,8 @@ fn main() {
         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
         //~^ ERROR cannot borrow value as mutable because it is also borrowed as immutable
         //~| ERROR cannot borrow value as mutable because it is also borrowed as immutable
+        //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
+        //~| ERROR cannot borrow value as immutable because it is also borrowed as mutable
         //~| ERROR cannot move out of `b` in pattern guard
         //~| ERROR cannot move out of `b` in pattern guard
         _ => {}
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 0b432487615b2..9359244c6ebc1 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
@@ -138,7 +138,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    |                                 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
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96: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
@@ -146,7 +146,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |         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
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96: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
@@ -154,7 +154,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); fa
    |                                 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
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103: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
@@ -162,7 +162,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |         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
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103: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
@@ -170,7 +170,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    |                                 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
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:9
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |         ^^^^^^^^^      ----- value is borrowed by `b` here
@@ -178,7 +178,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |         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
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:33
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                 ^^^^^^^^^       ----- value is borrowed by `b` here
@@ -186,7 +186,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    |                                 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
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^    ---------  --------- value is mutably borrowed by `c` here
@@ -195,7 +195,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         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:123:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^    ---------  --------- value is mutably borrowed by `c` here
@@ -204,7 +204,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         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:129:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^    ---------  --------- value is mutably borrowed by `c` here
@@ -213,7 +213,7 @@ LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         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:134:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:138:9
    |
 LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         ^^^^^^^^^    -----  ----- value is borrowed by `c` here
@@ -221,16 +221,16 @@ LL |     let ref mut a @ (ref b, ref c) = (U, U);
    |         |            value is borrowed by `b` here
    |         value is mutably borrowed by `a` here
 
-error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:31
+error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:8:9
    |
 LL |         ref mut z @ &mut Some(ref a) => {
-   |         ---------             ^^^^^ immutable borrow occurs here
+   |         ^^^^^^^^^             ----- immutable borrow occurs here
    |         |
    |         mutable borrow occurs here
 ...
-LL |             **z = None;
-   |             ---------- mutable borrow later used here
+LL |             println!("{}", *a);
+   |                            -- immutable borrow later used here
 
 error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:46:9
@@ -254,27 +254,44 @@ LL |     let ref a @ ref mut b = u();
 LL |     *b = u();
    |     -------- mutable borrow later used here
 
-error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:20
+error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:9
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
-   |         -----      ^^^^^^^^^ mutable borrow occurs here
+   |         ^^^^^      --------- mutable borrow occurs here
    |         |
    |         immutable borrow occurs here
 ...
-LL |             drop(a);
-   |                  - immutable borrow later used here
+LL |             *b = U;
+   |             ------ mutable borrow later used here
 
-error[E0502]: cannot borrow value as mutable because it is also borrowed as immutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:45
+error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:76:33
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) => {
-   |                                 -----       ^^^^^^^^^ mutable borrow occurs here
+   |                                 ^^^^^       --------- mutable borrow occurs here
    |                                 |
    |                                 immutable borrow occurs here
 ...
-LL |             drop(a);
-   |                  - immutable borrow later used here
+LL |             *b = U;
+   |             ------ mutable borrow later used here
+
+error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
+  --> $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 } => {}
+   |         ^^^^^      --------- mutable borrow occurs here     ------ mutable borrow later used here
+   |         |
+   |         immutable borrow occurs here
+
+error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
+  --> $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 } => {}
+   |                                 ^^^^^       ---------       ------ mutable borrow later used here
+   |                                 |           |
+   |                                 |           mutable borrow occurs here
+   |                                 immutable borrow occurs here
 
 error[E0594]: cannot assign to `*b`, as it is immutable for the pattern guard
   --> $DIR/borrowck-pat-ref-mut-and-ref.rs:87:61
@@ -285,15 +302,32 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { *b = U; false }
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
 error[E0594]: cannot assign to `*a`, as it is immutable for the pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:94:61
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:96:61
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { *a = Err(U); false } => {}
    |                                                             ^^^^^^^^^^^ cannot assign
    |
    = note: variables bound in patterns are immutable until the end of the pattern guard
 
+error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:9
+   |
+LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
+   |         ^^^^^      --------- mutable borrow occurs here          - mutable borrow later used here
+   |         |
+   |         immutable borrow occurs here
+
+error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:33
+   |
+LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
+   |                                 ^^^^^       ---------            - mutable borrow later used here
+   |                                 |           |
+   |                                 |           mutable borrow occurs here
+   |                                 immutable borrow occurs here
+
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
@@ -301,7 +335,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `b` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:101:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:103:66
    |
 LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false } => {}
    |                                                                  ^ move occurs because `b` has type `&mut U`, which does not implement the `Copy` trait
@@ -310,7 +344,7 @@ LL |         ref a @ Ok(ref mut b) | ref a @ Err(ref mut b) if { drop(b); false
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait
@@ -318,7 +352,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: variables bound in patterns cannot be moved from until after the end of the pattern guard
 
 error[E0507]: cannot move out of `a` in pattern guard
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:109:66
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:113:66
    |
 LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false } => {}
    |                                                                  ^ move occurs because `a` has type `&mut Result<U, U>`, which does not implement the `Copy` trait
@@ -327,7 +361,7 @@ LL |         ref mut a @ Ok(ref b) | ref mut a @ Err(ref b) if { drop(a); false
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:117:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:121:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^    --------- mutable borrow occurs here
@@ -338,7 +372,7 @@ LL |     *b = U;
    |     ------ mutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:123:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:127:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^    --------- mutable borrow occurs here
@@ -349,7 +383,7 @@ LL |     *b = U;
    |     ------ mutable borrow later used here
 
 error[E0502]: cannot borrow value as immutable because it is also borrowed as mutable
-  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:129:9
+  --> $DIR/borrowck-pat-ref-mut-and-ref.rs:133:9
    |
 LL |     let ref a @ (ref mut b, ref mut c) = (U, U);
    |         ^^^^^    --------- mutable borrow occurs here
@@ -409,7 +443,7 @@ LL |     fn f4_also_moved(ref a @ ref mut b @ c: U) {}
    |                      |       value borrowed here after move
    |                      move occurs because value has type `U`, which does not implement the `Copy` trait
 
-error: aborting due to 47 previous errors
+error: aborting due to 51 previous errors
 
 Some errors have detailed explanations: E0382, E0502, E0507, E0594.
 For more information about an error, try `rustc --explain E0382`.
diff --git a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
index 99739c7bce041..5f86a6a0ca919 100644
--- a/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
+++ b/tests/ui/pattern/bindings-after-at/borrowck-pat-ref-mut-twice.rs
@@ -82,6 +82,8 @@ fn main() {
         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
             //~^ ERROR cannot borrow value as mutable more than once at a time
             //~| ERROR cannot borrow value as mutable more than once at a time
+            //~| ERROR cannot borrow value as mutable more than once at a time
+            //~| ERROR cannot borrow value as mutable more than once at a time
             *b = U;
         }
     }
@@ -89,8 +91,6 @@ fn main() {
         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
             //~^ ERROR cannot borrow value as mutable more than once at a time
             //~| ERROR cannot borrow value as mutable more than once at a time
-            //~| ERROR cannot borrow value as mutable more than once at a time
-            //~| ERROR cannot borrow value as mutable more than once at a time
             *a = Err(U);
 
             // FIXME: The binding name value used above makes for problematic diagnostics.
@@ -101,8 +101,6 @@ fn main() {
         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
             //~^ ERROR cannot borrow value as mutable more than once at a time
             //~| ERROR cannot borrow value as mutable more than once at a time
-            //~| ERROR cannot borrow value as mutable more than once at a time
-            //~| ERROR cannot borrow value as mutable more than once at a time
             drop(a);
         }
     }
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 c634ea470c5d5..3446148d2b15b 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
@@ -163,7 +163,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     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
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         ^^^^^^^^^      --------- value is mutably borrowed by `b` here
@@ -171,7 +171,7 @@ LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |         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
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:91:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
    |                                     ^^^^^^^^^       --------- value is mutably borrowed by `b` here
@@ -217,48 +217,26 @@ LL |     *b = U;
    |     ------ first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:89:24
-   |
-LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |         ---------      ^^^^^^^^^ second mutable borrow occurs here
-   |         |
-   |         first mutable borrow occurs here
-...
-LL |             *a = Err(U);
-   |             ----------- first borrow later used here
-
-error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:89:53
-   |
-LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |                                     ---------       ^^^^^^^^^ second mutable borrow occurs here
-   |                                     |
-   |                                     first mutable borrow occurs here
-...
-LL |             *a = Err(U);
-   |             ----------- first borrow later used here
-
-error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:101:24
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:82:9
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |         ---------      ^^^^^^^^^ second mutable borrow occurs here
+   |         ^^^^^^^^^      --------- first mutable borrow occurs here
    |         |
-   |         first mutable borrow occurs here
+   |         second mutable borrow occurs here
 ...
-LL |             drop(a);
-   |                  - first borrow later used here
+LL |             *b = U;
+   |             ------ first borrow later used here
 
 error[E0499]: cannot borrow value as mutable more than once at a time
-  --> $DIR/borrowck-pat-ref-mut-twice.rs:101:53
+  --> $DIR/borrowck-pat-ref-mut-twice.rs:82:37
    |
 LL |         ref mut a @ Ok(ref mut b) | ref mut a @ Err(ref mut b) => {
-   |                                     ---------       ^^^^^^^^^ second mutable borrow occurs here
+   |                                     ^^^^^^^^^       --------- first mutable borrow occurs here
    |                                     |
-   |                                     first mutable borrow occurs here
+   |                                     second mutable borrow occurs here
 ...
-LL |             drop(a);
-   |                  - first borrow later used here
+LL |             *b = U;
+   |             ------ first borrow later used here
 
 error: cannot borrow value as mutable more than once at a time
   --> $DIR/borrowck-pat-ref-mut-twice.rs:8:11
@@ -313,7 +291,7 @@ LL |     fn f4_also_moved(ref mut a @ ref mut b @ c: U) {}
    |                      |           value borrowed here after move
    |                      move occurs because value has type `U`, which does not implement the `Copy` trait
 
-error: aborting due to 31 previous errors
+error: aborting due to 29 previous errors
 
 Some errors have detailed explanations: E0382, E0499.
 For more information about an error, try `rustc --explain E0382`.
diff --git a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr
index 0b4d99727581b..59b454d398195 100644
--- a/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr
+++ b/tests/ui/pattern/usefulness/const-partial_eq-fallback-ice.stderr
@@ -9,3 +9,21 @@ LL |     if let CONSTANT = &&MyType {
 
 error: aborting due to 1 previous error
 
+Future incompatibility report: Future breakage diagnostic:
+warning: to use a constant of type `MyType` in a pattern, `MyType` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/const-partial_eq-fallback-ice.rs:14:12
+   |
+LL |     if let CONSTANT = &&MyType {
+   |            ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/const-partial_eq-fallback-ice.rs:1:10
+   |
+LL | #![allow(warnings)]
+   |          ^^^^^^^^
+   = note: `#[allow(indirect_structural_match)]` implied by `#[allow(warnings)]`
+
diff --git a/tests/ui/pattern/usefulness/consts-opaque.stderr b/tests/ui/pattern/usefulness/consts-opaque.stderr
index 0b1a2e2736e1d..6a5bd185e39b3 100644
--- a/tests/ui/pattern/usefulness/consts-opaque.stderr
+++ b/tests/ui/pattern/usefulness/consts-opaque.stderr
@@ -5,7 +5,7 @@ LL |         QUUX => {}
    |         ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: `#[warn(pointer_structural_match)]` on by default
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
@@ -15,7 +15,7 @@ LL |         QUUX => {}
    |         ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/consts-opaque.rs:108:9
@@ -24,7 +24,7 @@ LL |         WRAPQUUX => {}
    |         ^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/consts-opaque.rs:110:9
@@ -33,7 +33,7 @@ LL |         WRAPQUUX => {}
    |         ^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/consts-opaque.rs:117:9
@@ -42,7 +42,7 @@ LL |         WRAPQUUX => {}
    |         ^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/consts-opaque.rs:127:9
@@ -51,7 +51,7 @@ LL |         WRAPQUUX => {}
    |         ^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/consts-opaque.rs:139:9
@@ -60,7 +60,7 @@ LL |         WHOKNOWSQUUX => {}
    |         ^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/consts-opaque.rs:142:9
@@ -69,7 +69,7 @@ LL |         WHOKNOWSQUUX => {}
    |         ^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 error: unreachable pattern
   --> $DIR/consts-opaque.rs:48:9
@@ -166,3 +166,91 @@ LL |         WRAPQUUX => {}, Wrap(_) => todo!()
 error: aborting due to 10 previous errors; 8 warnings emitted
 
 For more information about this error, try `rustc --explain E0004`.
+Future incompatibility report: Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/consts-opaque.rs:96:9
+   |
+LL |         QUUX => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/consts-opaque.rs:98:9
+   |
+LL |         QUUX => {}
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/consts-opaque.rs:108:9
+   |
+LL |         WRAPQUUX => {}
+   |         ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/consts-opaque.rs:110:9
+   |
+LL |         WRAPQUUX => {}
+   |         ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/consts-opaque.rs:117:9
+   |
+LL |         WRAPQUUX => {}
+   |         ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/consts-opaque.rs:127:9
+   |
+LL |         WRAPQUUX => {}
+   |         ^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/consts-opaque.rs:139:9
+   |
+LL |         WHOKNOWSQUUX => {}
+   |         ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/consts-opaque.rs:142:9
+   |
+LL |         WHOKNOWSQUUX => {}
+   |         ^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
index 910d491baaf43..9945041113d79 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-embedded.stderr
@@ -5,7 +5,7 @@ LL |         WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLIN
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 note: the lint level is defined here
@@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)]
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:24:9
+   |
+LL |         WRAP_DOUBLY_INDIRECT_INLINE => { panic!("WRAP_DOUBLY_INDIRECT_INLINE matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/cant-hide-behind-doubly-indirect-embedded.rs:7:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
index cadd9be023c50..6ac261ae81437 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-doubly-indirect-param.stderr
@@ -5,7 +5,7 @@ LL |         WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 note: the lint level is defined here
@@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)]
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/cant-hide-behind-doubly-indirect-param.rs:24:9
+   |
+LL |         WRAP_DOUBLY_INDIRECT_PARAM => { panic!("WRAP_DOUBLY_INDIRECT_PARAM matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/cant-hide-behind-doubly-indirect-param.rs:7:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
index e4321cc6a4c71..41616fb90fe96 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-embedded.stderr
@@ -5,7 +5,7 @@ LL |         WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itse
    |         ^^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 note: the lint level is defined here
@@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)]
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:24:9
+   |
+LL |         WRAP_INDIRECT_INLINE => { panic!("WRAP_INDIRECT_INLINE matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/cant-hide-behind-indirect-struct-embedded.rs:7:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
index decc29ad67cd2..99dea5171d1bc 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/cant-hide-behind-indirect-struct-param.stderr
@@ -5,7 +5,7 @@ LL |         WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself
    |         ^^^^^^^^^^^^^^^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 note: the lint level is defined here
@@ -16,3 +16,20 @@ LL | #![warn(indirect_structural_match)]
 
 warning: 1 warning emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: to use a constant of type `NoDerive` in a pattern, `NoDerive` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/cant-hide-behind-indirect-struct-param.rs:24:9
+   |
+LL |         WRAP_INDIRECT_PARAM => { panic!("WRAP_INDIRECT_PARAM matched itself"); }
+   |         ^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/cant-hide-behind-indirect-struct-param.rs:7:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr
index 080bf5885ba75..11163ba70ec65 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/fn-ptr-is-structurally-matchable.stderr
@@ -5,7 +5,7 @@ LL |         Wrap(CFN1) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: `#[warn(pointer_structural_match)]` on by default
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
@@ -15,7 +15,7 @@ LL |         Wrap(CFN2) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14
@@ -24,7 +24,7 @@ LL |         Wrap(CFN3) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14
@@ -33,7 +33,7 @@ LL |         Wrap(CFN4) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14
@@ -42,7 +42,7 @@ LL |         Wrap(CFN5) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14
@@ -51,7 +51,7 @@ LL |         Wrap(CFN6) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14
@@ -60,7 +60,7 @@ LL |         Wrap(CFN7) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14
@@ -69,7 +69,7 @@ LL |         Wrap(CFN8) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14
@@ -78,7 +78,7 @@ LL |         Wrap(CFN9) => count += 1,
    |              ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
   --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9
@@ -87,7 +87,117 @@ LL |         CFOO => count += 1,
    |         ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: 10 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:43:14
+   |
+LL |         Wrap(CFN1) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:52:14
+   |
+LL |         Wrap(CFN2) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:61:14
+   |
+LL |         Wrap(CFN3) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:70:14
+   |
+LL |         Wrap(CFN4) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:79:14
+   |
+LL |         Wrap(CFN5) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:88:14
+   |
+LL |         Wrap(CFN6) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:97:14
+   |
+LL |         Wrap(CFN7) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:106:14
+   |
+LL |         Wrap(CFN8) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:115:14
+   |
+LL |         Wrap(CFN9) => count += 1,
+   |              ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/fn-ptr-is-structurally-matchable.rs:138:9
+   |
+LL |         CFOO => count += 1,
+   |         ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: `#[warn(pointer_structural_match)]` on by default
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
index fdb67bcf2d8e4..374e5d5acd080 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.rs
@@ -10,7 +10,7 @@
 
 // Issue 62307 pointed out a case where the structural-match checking
 // was too shallow.
-#![warn(indirect_structural_match, nontrivial_structural_match)]
+#![warn(indirect_structural_match)]
 // run-pass
 
 #[derive(Debug)]
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
index d0f2b820afa90..d4ab1ce3ba2ad 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-62307-match-ref-ref-forbidden-without-eq.stderr
@@ -5,13 +5,13 @@ LL |         RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0);
    |         ^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 note: the lint level is defined here
   --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
    |
-LL | #![warn(indirect_structural_match, nontrivial_structural_match)]
+LL | #![warn(indirect_structural_match)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
@@ -21,9 +21,43 @@ LL |         RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1);
    |         ^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/62411>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
    = note: the traits must be derived, manual `impl`s are not sufficient
    = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
 
 warning: 2 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:31:9
+   |
+LL |         RR_B1 => { println!("CLAIM RR0: {:?} matches {:?}", RR_B1, RR_B0); }
+   |         ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: to use a constant of type `B` in a pattern, `B` must be annotated with `#[derive(PartialEq)]`
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:38:9
+   |
+LL |         RR_B1 => { println!("CLAIM RR1: {:?} matches {:?}", RR_B1, RR_B1); }
+   |         ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+   = note: the traits must be derived, manual `impl`s are not sufficient
+   = note: see https://doc.rust-lang.org/stable/std/marker/trait.StructuralPartialEq.html for details
+note: the lint level is defined here
+  --> $DIR/issue-62307-match-ref-ref-forbidden-without-eq.rs:13:9
+   |
+LL | #![warn(indirect_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
index 4fdfce60bb861..0edcf44c4d795 100644
--- a/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
+++ b/tests/ui/rfcs/rfc-1445-restrict-constants-in-patterns/issue-63479-match-fnptr.stderr
@@ -5,7 +5,7 @@ LL |     B(TEST) => println!("matched"),
    |       ^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 note: the lint level is defined here
   --> $DIR/issue-63479-match-fnptr.rs:8:9
    |
@@ -19,7 +19,37 @@ LL |     TEST2 => println!("matched"),
    |     ^^^^^
    |
    = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
-   = note: for more information, see issue #62411 <https://github.com/rust-lang/rust/issues/70861>
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
 
 warning: 2 warnings emitted
 
+Future incompatibility report: Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-63479-match-fnptr.rs:36:7
+   |
+LL |     B(TEST) => println!("matched"),
+   |       ^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+note: the lint level is defined here
+  --> $DIR/issue-63479-match-fnptr.rs:8:9
+   |
+LL | #![warn(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
+Future breakage diagnostic:
+warning: function pointers and raw pointers not derived from integers in patterns behave unpredictably and should not be relied upon. See https://github.com/rust-lang/rust/issues/70861 for details.
+  --> $DIR/issue-63479-match-fnptr.rs:42:5
+   |
+LL |     TEST2 => println!("matched"),
+   |     ^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in a future release!
+   = note: for more information, see issue #120362 <https://github.com/rust-lang/rust/issues/120362>
+note: the lint level is defined here
+  --> $DIR/issue-63479-match-fnptr.rs:8:9
+   |
+LL | #![warn(pointer_structural_match)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^
+
diff --git a/tests/ui/traits/method-on-unbounded-type-param.rs b/tests/ui/traits/method-on-unbounded-type-param.rs
new file mode 100644
index 0000000000000..8505eb41e98bb
--- /dev/null
+++ b/tests/ui/traits/method-on-unbounded-type-param.rs
@@ -0,0 +1,15 @@
+fn f<T>(a: T, b: T) -> std::cmp::Ordering {
+    a.cmp(&b) //~ ERROR E0599
+}
+fn g<T>(a: T, b: T) -> std::cmp::Ordering {
+    (&a).cmp(&b) //~ ERROR E0599
+}
+fn h<T>(a: &T, b: T) -> std::cmp::Ordering {
+    a.cmp(&b) //~ ERROR E0599
+}
+trait T {}
+impl<X: std::cmp::Ord> T for X {}
+fn main() {
+    let x: Box<dyn T> = Box::new(0);
+    x.cmp(&x); //~ ERROR E0599
+}
diff --git a/tests/ui/traits/method-on-unbounded-type-param.stderr b/tests/ui/traits/method-on-unbounded-type-param.stderr
new file mode 100644
index 0000000000000..0d8bd8ee964e7
--- /dev/null
+++ b/tests/ui/traits/method-on-unbounded-type-param.stderr
@@ -0,0 +1,84 @@
+error[E0599]: no method named `cmp` found for type parameter `T` in the current scope
+  --> $DIR/method-on-unbounded-type-param.rs:2:7
+   |
+LL | fn f<T>(a: T, b: T) -> std::cmp::Ordering {
+   |      - method `cmp` not found for this type parameter
+LL |     a.cmp(&b)
+   |       ^^^ method cannot be called on `T` due to unsatisfied trait bounds
+   |
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them:
+   |
+LL | fn f<T: Ord>(a: T, b: T) -> std::cmp::Ordering {
+   |       +++++
+LL | fn f<T: Iterator>(a: T, b: T) -> std::cmp::Ordering {
+   |       ++++++++++
+
+error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied
+  --> $DIR/method-on-unbounded-type-param.rs:5:10
+   |
+LL |     (&a).cmp(&b)
+   |          ^^^ method cannot be called on `&T` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `T: Ord`
+           which is required by `&T: Ord`
+           `&T: Iterator`
+           which is required by `&mut &T: Iterator`
+           `T: Iterator`
+           which is required by `&mut T: Iterator`
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them:
+   |
+LL | fn g<T: Ord>(a: T, b: T) -> std::cmp::Ordering {
+   |       +++++
+LL | fn g<T: Iterator>(a: T, b: T) -> std::cmp::Ordering {
+   |       ++++++++++
+
+error[E0599]: the method `cmp` exists for reference `&T`, but its trait bounds were not satisfied
+  --> $DIR/method-on-unbounded-type-param.rs:8:7
+   |
+LL |     a.cmp(&b)
+   |       ^^^ method cannot be called on `&T` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `T: Ord`
+           which is required by `&T: Ord`
+           `&T: Iterator`
+           which is required by `&mut &T: Iterator`
+           `T: Iterator`
+           which is required by `&mut T: Iterator`
+   = help: items from traits can only be used if the type parameter is bounded by the trait
+help: the following traits define an item `cmp`, perhaps you need to restrict type parameter `T` with one of them:
+   |
+LL | fn h<T: Ord>(a: &T, b: T) -> std::cmp::Ordering {
+   |       +++++
+LL | fn h<T: Iterator>(a: &T, b: T) -> std::cmp::Ordering {
+   |       ++++++++++
+
+error[E0599]: the method `cmp` exists for struct `Box<dyn T>`, but its trait bounds were not satisfied
+  --> $DIR/method-on-unbounded-type-param.rs:14:7
+   |
+LL | trait T {}
+   | ------- doesn't satisfy `dyn T: Iterator` or `dyn T: Ord`
+...
+LL |     x.cmp(&x);
+   |       ^^^ method cannot be called on `Box<dyn T>` due to unsatisfied trait bounds
+   |
+   = note: the following trait bounds were not satisfied:
+           `dyn T: Iterator`
+           which is required by `Box<dyn T>: Iterator`
+           `dyn T: Ord`
+           which is required by `Box<dyn T>: Ord`
+           `Box<dyn T>: Iterator`
+           which is required by `&mut Box<dyn T>: Iterator`
+           `dyn T: Iterator`
+           which is required by `&mut dyn T: Iterator`
+   = help: items from traits can only be used if the trait is implemented and in scope
+   = note: the following traits define an item `cmp`, perhaps you need to implement one of them:
+           candidate #1: `Ord`
+           candidate #2: `Iterator`
+
+error: aborting due to 4 previous errors
+
+For more information about this error, try `rustc --explain E0599`.