diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 0934e42b277e4..c6f3fcada08e6 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -173,6 +173,11 @@ jobs:
       - name: ensure the stable version number is correct
         run: src/ci/scripts/verify-stable-version-number.sh
 
+      # Show the environment just before we run the build
+      # This makes it easier to diagnose problems with the above install scripts.
+      - name: show the current environment
+        run: src/ci/scripts/dump-environment.sh
+
       - name: run the build
         # Redirect stderr to stdout to avoid reordering the two streams in the GHA logs.
         run: src/ci/scripts/run-build-from-ci.sh 2>&1
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index ae00bb4e218ab..73a1432b06ce6 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -230,10 +230,19 @@ enum InheritedRefMatchRule {
     /// underlying type is not a reference type, the inherited reference will be consumed.
     EatInner,
     /// When the underlying type is a reference type, reference patterns consume both layers of
-    /// reference, i.e. they both reset the binding mode and consume the reference type. Reference
-    /// patterns are not permitted when there is no underlying reference type, i.e. they can't eat
-    /// only an inherited reference. This is the current stable Rust behavior.
-    EatBoth,
+    /// reference, i.e. they both reset the binding mode and consume the reference type.
+    EatBoth {
+        /// If `true`, an inherited reference will be considered when determining whether a reference
+        /// pattern matches a given type:
+        /// - If the underlying type is not a reference, a reference pattern may eat the inherited reference;
+        /// - If the underlying type is a reference, a reference pattern matches if it can eat either one
+        ///    of the underlying and inherited references. E.g. a `&mut` pattern is allowed if either the
+        ///    underlying type is `&mut` or the inherited reference is `&mut`.
+        /// If `false`, a reference pattern is only matched against the underlying type.
+        /// This is `false` for stable Rust and `true` for both the `ref_pat_eat_one_layer_2024` and
+        /// `ref_pat_eat_one_layer_2024_structural` feature gates.
+        consider_inherited_ref: bool,
+    },
 }
 
 impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
@@ -259,10 +268,13 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             } else {
                 // Currently, matching against an inherited ref on edition 2024 is an error.
                 // Use `EatBoth` as a fallback to be similar to stable Rust.
-                InheritedRefMatchRule::EatBoth
+                InheritedRefMatchRule::EatBoth { consider_inherited_ref: false }
             }
         } else {
-            InheritedRefMatchRule::EatBoth
+            InheritedRefMatchRule::EatBoth {
+                consider_inherited_ref: self.tcx.features().ref_pat_eat_one_layer_2024()
+                    || self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
+            }
         }
     }
 
@@ -2371,6 +2383,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             // NB: This assumes that `&` patterns can match against mutable
                             // references (RFC 3627, Rule 5). If we implement a pattern typing
                             // ruleset with Rule 4 but not Rule 5, we'll need to check that here.
+                            // FIXME(ref_pat_eat_one_layer_2024_structural): If we already tried
+                            // matching the real reference, the error message should explain that
+                            // falling back to the inherited reference didn't work. This should be
+                            // the same error as the old-Edition version below.
                             debug_assert!(ref_pat_matches_mut_ref);
                             self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
                         }
@@ -2381,9 +2397,46 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                         return expected;
                     }
                 }
-                InheritedRefMatchRule::EatBoth => {
+                InheritedRefMatchRule::EatBoth { consider_inherited_ref: true } => {
                     // Reset binding mode on old editions
                     pat_info.binding_mode = ByRef::No;
+
+                    if let ty::Ref(_, inner_ty, _) = *expected.kind() {
+                        // Consume both the inherited and inner references.
+                        if pat_mutbl.is_mut() && inh_mut.is_mut() {
+                            // As a special case, a `&mut` reference pattern will be able to match
+                            // against a reference type of any mutability if the inherited ref is
+                            // mutable. Since this allows us to match against a shared reference
+                            // type, we refer to this as "falling back" to matching the inherited
+                            // reference, though we consume the real reference as well. We handle
+                            // this here to avoid adding this case to the common logic below.
+                            self.check_pat(inner, inner_ty, pat_info);
+                            return expected;
+                        } else {
+                            // Otherwise, use the common logic below for matching the inner
+                            // reference type.
+                            // FIXME(ref_pat_eat_one_layer_2024_structural): If this results in a
+                            // mutability mismatch, the error message should explain that falling
+                            // back to the inherited reference didn't work. This should be the same
+                            // error as the Edition 2024 version above.
+                        }
+                    } else {
+                        // The expected type isn't a reference type, so only match against the
+                        // inherited reference.
+                        if pat_mutbl > inh_mut {
+                            // We can't match a lone inherited shared reference with `&mut`.
+                            self.error_inherited_ref_mutability_mismatch(pat, pat_prefix_span);
+                        }
+
+                        self.typeck_results.borrow_mut().skipped_ref_pats_mut().insert(pat.hir_id);
+                        self.check_pat(inner, expected, pat_info);
+                        return expected;
+                    }
+                }
+                InheritedRefMatchRule::EatBoth { consider_inherited_ref: false } => {
+                    // Reset binding mode on stable Rust. This will be a type error below if
+                    // `expected` is not a reference type.
+                    pat_info.binding_mode = ByRef::No;
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
                         pat,
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 5111a025f94ee..74c48a45f185a 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -1431,37 +1431,48 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
 
     /// Warns against some misuses of `#[must_use]`
     fn check_must_use(&self, hir_id: HirId, attr: &Attribute, target: Target) {
-        if !matches!(
+        if matches!(
             target,
             Target::Fn
                 | Target::Enum
                 | Target::Struct
                 | Target::Union
-                | Target::Method(_)
+                | Target::Method(MethodKind::Trait { body: false } | MethodKind::Inherent)
                 | Target::ForeignFn
                 // `impl Trait` in return position can trip
                 // `unused_must_use` if `Trait` is marked as
                 // `#[must_use]`
                 | Target::Trait
         ) {
-            let article = match target {
-                Target::ExternCrate
-                | Target::Enum
-                | Target::Impl
-                | Target::Expression
-                | Target::Arm
-                | Target::AssocConst
-                | Target::AssocTy => "an",
-                _ => "a",
-            };
+            return;
+        }
 
-            self.tcx.emit_node_span_lint(
-                UNUSED_ATTRIBUTES,
-                hir_id,
-                attr.span,
-                errors::MustUseNoEffect { article, target },
-            );
+        // `#[must_use]` can be applied to a trait method definition with a default body
+        if let Target::Method(MethodKind::Trait { body: true }) = target
+            && let parent_def_id = self.tcx.hir().get_parent_item(hir_id).def_id
+            && let containing_item = self.tcx.hir().expect_item(parent_def_id)
+            && let hir::ItemKind::Trait(..) = containing_item.kind
+        {
+            return;
         }
+
+        let article = match target {
+            Target::ExternCrate
+            | Target::Enum
+            | Target::Impl
+            | Target::Expression
+            | Target::Arm
+            | Target::AssocConst
+            | Target::AssocTy => "an",
+            _ => "a",
+        };
+
+        self.tcx.emit_node_span_lint(
+            UNUSED_ATTRIBUTES,
+            hir_id,
+            attr.span,
+            errors::MustUseNoEffect { article, target },
+        );
     }
 
     /// Checks if `#[must_not_suspend]` is applied to a struct, enum, union, or trait.
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 0962865e7f190..b37c684a0556a 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -8,7 +8,7 @@ use rustc_ast::ptr::P;
 use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty};
 use rustc_ast::{
     self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind,
-    Item, ItemKind, MethodCall, NodeId, Path, Ty, TyKind,
+    Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind,
 };
 use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
@@ -1529,7 +1529,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     Applicability::MaybeIncorrect,
                 );
                 true
-            } else if kind == DefKind::Struct
+            } else if matches!(kind, DefKind::Struct | DefKind::TyAlias)
                 && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
                 && let Ok(snippet) = this.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
             {
@@ -1566,7 +1566,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             }
         };
 
-        let mut bad_struct_syntax_suggestion = |this: &mut Self, def_id: DefId| {
+        let bad_struct_syntax_suggestion = |this: &mut Self, err: &mut Diag<'_>, def_id: DefId| {
             let (followed_by_brace, closing_brace) = this.followed_by_brace(span);
 
             match source {
@@ -1740,12 +1740,10 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 }
             }
             (
-                Res::Def(kind @ (DefKind::Mod | DefKind::Trait), _),
+                Res::Def(kind @ (DefKind::Mod | DefKind::Trait | DefKind::TyAlias), _),
                 PathSource::Expr(Some(parent)),
-            ) => {
-                if !path_sep(self, err, parent, kind) {
-                    return false;
-                }
+            ) if path_sep(self, err, parent, kind) => {
+                return true;
             }
             (
                 Res::Def(DefKind::Enum, def_id),
@@ -1777,13 +1775,13 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor {
                     if let PathSource::Expr(Some(parent)) = source {
                         if let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind {
-                            bad_struct_syntax_suggestion(self, def_id);
+                            bad_struct_syntax_suggestion(self, err, def_id);
                             return true;
                         }
                     }
                     struct_ctor
                 } else {
-                    bad_struct_syntax_suggestion(self, def_id);
+                    bad_struct_syntax_suggestion(self, err, def_id);
                     return true;
                 };
 
@@ -1861,7 +1859,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 err.span_label(span, "constructor is not visible here due to private fields");
             }
             (Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => {
-                bad_struct_syntax_suggestion(self, def_id);
+                bad_struct_syntax_suggestion(self, err, def_id);
             }
             (Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
                 match source {
@@ -2471,31 +2469,73 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         def_id: DefId,
         span: Span,
     ) {
-        let Some(variants) = self.collect_enum_ctors(def_id) else {
+        let Some(variant_ctors) = self.collect_enum_ctors(def_id) else {
             err.note("you might have meant to use one of the enum's variants");
             return;
         };
 
-        let suggest_only_tuple_variants =
-            matches!(source, PathSource::TupleStruct(..)) || source.is_call();
-        if suggest_only_tuple_variants {
+        // If the expression is a field-access or method-call, try to find a variant with the field/method name
+        // that could have been intended, and suggest replacing the `.` with `::`.
+        // Otherwise, suggest adding `::VariantName` after the enum;
+        // and if the expression is call-like, only suggest tuple variants.
+        let (suggest_path_sep_dot_span, suggest_only_tuple_variants) = match source {
+            // `Type(a, b)` in a pattern, only suggest adding a tuple variant after `Type`.
+            PathSource::TupleStruct(..) => (None, true),
+            PathSource::Expr(Some(expr)) => match &expr.kind {
+                // `Type(a, b)`, only suggest adding a tuple variant after `Type`.
+                ExprKind::Call(..) => (None, true),
+                // `Type.Foo(a, b)`, suggest replacing `.` -> `::` if variant `Foo` exists and is a tuple variant,
+                // otherwise suggest adding a variant after `Type`.
+                ExprKind::MethodCall(box MethodCall {
+                    receiver,
+                    span,
+                    seg: PathSegment { ident, .. },
+                    ..
+                }) => {
+                    let dot_span = receiver.span.between(*span);
+                    let found_tuple_variant = variant_ctors.iter().any(|(path, _, ctor_kind)| {
+                        *ctor_kind == CtorKind::Fn
+                            && path.segments.last().is_some_and(|seg| seg.ident == *ident)
+                    });
+                    (found_tuple_variant.then_some(dot_span), false)
+                }
+                // `Type.Foo`, suggest replacing `.` -> `::` if variant `Foo` exists and is a unit or tuple variant,
+                // otherwise suggest adding a variant after `Type`.
+                ExprKind::Field(base, ident) => {
+                    let dot_span = base.span.between(ident.span);
+                    let found_tuple_or_unit_variant = variant_ctors.iter().any(|(path, ..)| {
+                        path.segments.last().is_some_and(|seg| seg.ident == *ident)
+                    });
+                    (found_tuple_or_unit_variant.then_some(dot_span), false)
+                }
+                _ => (None, false),
+            },
+            _ => (None, false),
+        };
+
+        if let Some(dot_span) = suggest_path_sep_dot_span {
+            err.span_suggestion_verbose(
+                dot_span,
+                "use the path separator to refer to a variant",
+                "::",
+                Applicability::MaybeIncorrect,
+            );
+        } else if suggest_only_tuple_variants {
             // Suggest only tuple variants regardless of whether they have fields and do not
             // suggest path with added parentheses.
-            let mut suggestable_variants = variants
+            let mut suggestable_variants = variant_ctors
                 .iter()
                 .filter(|(.., kind)| *kind == CtorKind::Fn)
                 .map(|(variant, ..)| path_names_to_string(variant))
                 .collect::<Vec<_>>();
             suggestable_variants.sort();
 
-            let non_suggestable_variant_count = variants.len() - suggestable_variants.len();
+            let non_suggestable_variant_count = variant_ctors.len() - suggestable_variants.len();
 
-            let source_msg = if source.is_call() {
-                "to construct"
-            } else if matches!(source, PathSource::TupleStruct(..)) {
+            let source_msg = if matches!(source, PathSource::TupleStruct(..)) {
                 "to match against"
             } else {
-                unreachable!()
+                "to construct"
             };
 
             if !suggestable_variants.is_empty() {
@@ -2514,7 +2554,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
             }
 
             // If the enum has no tuple variants..
-            if non_suggestable_variant_count == variants.len() {
+            if non_suggestable_variant_count == variant_ctors.len() {
                 err.help(format!("the enum has no tuple variants {source_msg}"));
             }
 
@@ -2537,7 +2577,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 }
             };
 
-            let mut suggestable_variants = variants
+            let mut suggestable_variants = variant_ctors
                 .iter()
                 .filter(|(_, def_id, kind)| !needs_placeholder(*def_id, *kind))
                 .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
@@ -2564,7 +2604,7 @@ impl<'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 );
             }
 
-            let mut suggestable_variants_with_placeholders = variants
+            let mut suggestable_variants_with_placeholders = variant_ctors
                 .iter()
                 .filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
                 .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
diff --git a/library/alloc/src/lib.rs b/library/alloc/src/lib.rs
index 1bb0f76106472..b16d40e988e15 100644
--- a/library/alloc/src/lib.rs
+++ b/library/alloc/src/lib.rs
@@ -105,6 +105,7 @@
 #![feature(box_uninit_write)]
 #![feature(bstr)]
 #![feature(bstr_internals)]
+#![feature(char_max_len)]
 #![feature(clone_to_uninit)]
 #![feature(coerce_unsized)]
 #![feature(const_eval_select)]
diff --git a/library/alloc/src/string.rs b/library/alloc/src/string.rs
index 154da69107884..9446afd4b24b0 100644
--- a/library/alloc/src/string.rs
+++ b/library/alloc/src/string.rs
@@ -1419,7 +1419,9 @@ impl String {
     pub fn push(&mut self, ch: char) {
         match ch.len_utf8() {
             1 => self.vec.push(ch as u8),
-            _ => self.vec.extend_from_slice(ch.encode_utf8(&mut [0; 4]).as_bytes()),
+            _ => {
+                self.vec.extend_from_slice(ch.encode_utf8(&mut [0; char::MAX_LEN_UTF8]).as_bytes())
+            }
         }
     }
 
@@ -1716,7 +1718,7 @@ impl String {
     #[rustc_confusables("set")]
     pub fn insert(&mut self, idx: usize, ch: char) {
         assert!(self.is_char_boundary(idx));
-        let mut bits = [0; 4];
+        let mut bits = [0; char::MAX_LEN_UTF8];
         let bits = ch.encode_utf8(&mut bits).as_bytes();
 
         unsafe {
@@ -2797,7 +2799,7 @@ impl SpecToString for core::ascii::Char {
 impl SpecToString for char {
     #[inline]
     fn spec_to_string(&self) -> String {
-        String::from(self.encode_utf8(&mut [0; 4]))
+        String::from(self.encode_utf8(&mut [0; char::MAX_LEN_UTF8]))
     }
 }
 
@@ -3155,6 +3157,24 @@ impl From<String> for Vec<u8> {
     }
 }
 
+#[stable(feature = "try_from_vec_u8_for_string", since = "CURRENT_RUSTC_VERSION")]
+impl TryFrom<Vec<u8>> for String {
+    type Error = FromUtf8Error;
+    /// Converts the given [`Vec<u8>`] into a  [`String`] if it contains valid UTF-8 data.
+    ///
+    /// # Examples
+    ///
+    /// ```
+    /// let s1 = b"hello world".to_vec();
+    /// let v1 = String::try_from(s1).unwrap();
+    /// assert_eq!(v1, "hello world");
+    ///
+    /// ```
+    fn try_from(bytes: Vec<u8>) -> Result<Self, Self::Error> {
+        Self::from_utf8(bytes)
+    }
+}
+
 #[cfg(not(no_global_oom_handling))]
 #[stable(feature = "rust1", since = "1.0.0")]
 impl fmt::Write for String {
diff --git a/library/alloc/tests/lib.rs b/library/alloc/tests/lib.rs
index 1bcec4037cdd6..f95be6a6df0b3 100644
--- a/library/alloc/tests/lib.rs
+++ b/library/alloc/tests/lib.rs
@@ -3,6 +3,7 @@
 #![feature(iter_array_chunks)]
 #![feature(assert_matches)]
 #![feature(btree_extract_if)]
+#![feature(char_max_len)]
 #![feature(cow_is_borrowed)]
 #![feature(core_intrinsics)]
 #![feature(downcast_unchecked)]
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index 23a0e5e525643..906fa2d425e77 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -2,6 +2,7 @@
 
 use std::assert_matches::assert_matches;
 use std::borrow::Cow;
+use std::char::MAX_LEN_UTF8;
 use std::cmp::Ordering::{Equal, Greater, Less};
 use std::str::{from_utf8, from_utf8_unchecked};
 
@@ -1231,7 +1232,7 @@ fn test_to_uppercase_rev_iterator() {
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_chars_decoding() {
-    let mut bytes = [0; 4];
+    let mut bytes = [0; MAX_LEN_UTF8];
     for c in (0..0x110000).filter_map(std::char::from_u32) {
         let s = c.encode_utf8(&mut bytes);
         if Some(c) != s.chars().next() {
@@ -1243,7 +1244,7 @@ fn test_chars_decoding() {
 #[test]
 #[cfg_attr(miri, ignore)] // Miri is too slow
 fn test_chars_rev_decoding() {
-    let mut bytes = [0; 4];
+    let mut bytes = [0; MAX_LEN_UTF8];
     for c in (0..0x110000).filter_map(std::char::from_u32) {
         let s = c.encode_utf8(&mut bytes);
         if Some(c) != s.chars().rev().next() {
diff --git a/library/core/src/char/methods.rs b/library/core/src/char/methods.rs
index 34f5c3e94bcd5..85cc315626d4b 100644
--- a/library/core/src/char/methods.rs
+++ b/library/core/src/char/methods.rs
@@ -71,6 +71,16 @@ impl char {
     #[stable(feature = "assoc_char_consts", since = "1.52.0")]
     pub const MAX: char = '\u{10FFFF}';
 
+    /// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
+    /// UTF-8 encoding.
+    #[unstable(feature = "char_max_len", issue = "121714")]
+    pub const MAX_LEN_UTF8: usize = 4;
+
+    /// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
+    /// to UTF-16 encoding.
+    #[unstable(feature = "char_max_len", issue = "121714")]
+    pub const MAX_LEN_UTF16: usize = 2;
+
     /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
     /// decoding error.
     ///
diff --git a/library/core/src/char/mod.rs b/library/core/src/char/mod.rs
index 59fd7250e8f8e..088c709f1a2af 100644
--- a/library/core/src/char/mod.rs
+++ b/library/core/src/char/mod.rs
@@ -95,6 +95,16 @@ const MAX_THREE_B: u32 = 0x10000;
 #[stable(feature = "rust1", since = "1.0.0")]
 pub const MAX: char = char::MAX;
 
+/// The maximum number of bytes required to [encode](char::encode_utf8) a `char` to
+/// UTF-8 encoding.
+#[unstable(feature = "char_max_len", issue = "121714")]
+pub const MAX_LEN_UTF8: usize = char::MAX_LEN_UTF8;
+
+/// The maximum number of two-byte units required to [encode](char::encode_utf16) a `char`
+/// to UTF-16 encoding.
+#[unstable(feature = "char_max_len", issue = "121714")]
+pub const MAX_LEN_UTF16: usize = char::MAX_LEN_UTF16;
+
 /// `U+FFFD REPLACEMENT CHARACTER` (�) is used in Unicode to represent a
 /// decoding error. Use [`char::REPLACEMENT_CHARACTER`] instead.
 #[stable(feature = "decode_utf16", since = "1.9.0")]
diff --git a/library/core/src/fmt/mod.rs b/library/core/src/fmt/mod.rs
index a1bf3a4d7a706..764e7fff33ec7 100644
--- a/library/core/src/fmt/mod.rs
+++ b/library/core/src/fmt/mod.rs
@@ -3,7 +3,7 @@
 #![stable(feature = "rust1", since = "1.0.0")]
 
 use crate::cell::{Cell, Ref, RefCell, RefMut, SyncUnsafeCell, UnsafeCell};
-use crate::char::EscapeDebugExtArgs;
+use crate::char::{EscapeDebugExtArgs, MAX_LEN_UTF8};
 use crate::marker::PhantomData;
 use crate::num::fmt as numfmt;
 use crate::ops::Deref;
@@ -187,7 +187,7 @@ pub trait Write {
     /// ```
     #[stable(feature = "fmt_write_char", since = "1.1.0")]
     fn write_char(&mut self, c: char) -> Result {
-        self.write_str(c.encode_utf8(&mut [0; 4]))
+        self.write_str(c.encode_utf8(&mut [0; MAX_LEN_UTF8]))
     }
 
     /// Glue for usage of the [`write!`] macro with implementors of this trait.
@@ -2768,7 +2768,7 @@ impl Display for char {
         if f.options.width.is_none() && f.options.precision.is_none() {
             f.write_char(*self)
         } else {
-            f.pad(self.encode_utf8(&mut [0; 4]))
+            f.pad(self.encode_utf8(&mut [0; MAX_LEN_UTF8]))
         }
     }
 }
diff --git a/library/core/src/slice/sort/shared/smallsort.rs b/library/core/src/slice/sort/shared/smallsort.rs
index 09f898309bd65..f6dcf42ba6037 100644
--- a/library/core/src/slice/sort/shared/smallsort.rs
+++ b/library/core/src/slice/sort/shared/smallsort.rs
@@ -387,7 +387,7 @@ unsafe fn swap_if_less<T, F>(v_base: *mut T, a_pos: usize, b_pos: usize, is_less
 where
     F: FnMut(&T, &T) -> bool,
 {
-    // SAFETY: the caller must guarantee that `a` and `b` each added to `v_base` yield valid
+    // SAFETY: the caller must guarantee that `a_pos` and `b_pos` each added to `v_base` yield valid
     // pointers into `v_base`, and are properly aligned, and part of the same allocation.
     unsafe {
         let v_a = v_base.add(a_pos);
@@ -404,16 +404,16 @@ where
         // The equivalent code with a branch would be:
         //
         // if should_swap {
-        //     ptr::swap(left, right, 1);
+        //     ptr::swap(v_a, v_b, 1);
         // }
 
         // The goal is to generate cmov instructions here.
-        let left_swap = if should_swap { v_b } else { v_a };
-        let right_swap = if should_swap { v_a } else { v_b };
+        let v_a_swap = should_swap.select_unpredictable(v_b, v_a);
+        let v_b_swap = should_swap.select_unpredictable(v_a, v_b);
 
-        let right_swap_tmp = ManuallyDrop::new(ptr::read(right_swap));
-        ptr::copy(left_swap, v_a, 1);
-        ptr::copy_nonoverlapping(&*right_swap_tmp, v_b, 1);
+        let v_b_swap_tmp = ManuallyDrop::new(ptr::read(v_b_swap));
+        ptr::copy(v_a_swap, v_a, 1);
+        ptr::copy_nonoverlapping(&*v_b_swap_tmp, v_b, 1);
     }
 }
 
@@ -640,26 +640,21 @@ pub unsafe fn sort4_stable<T, F: FnMut(&T, &T) -> bool>(
         //  1,  1 |  c   b    a         d
         let c3 = is_less(&*c, &*a);
         let c4 = is_less(&*d, &*b);
-        let min = select(c3, c, a);
-        let max = select(c4, b, d);
-        let unknown_left = select(c3, a, select(c4, c, b));
-        let unknown_right = select(c4, d, select(c3, b, c));
+        let min = c3.select_unpredictable(c, a);
+        let max = c4.select_unpredictable(b, d);
+        let unknown_left = c3.select_unpredictable(a, c4.select_unpredictable(c, b));
+        let unknown_right = c4.select_unpredictable(d, c3.select_unpredictable(b, c));
 
         // Sort the last two unknown elements.
         let c5 = is_less(&*unknown_right, &*unknown_left);
-        let lo = select(c5, unknown_right, unknown_left);
-        let hi = select(c5, unknown_left, unknown_right);
+        let lo = c5.select_unpredictable(unknown_right, unknown_left);
+        let hi = c5.select_unpredictable(unknown_left, unknown_right);
 
         ptr::copy_nonoverlapping(min, dst, 1);
         ptr::copy_nonoverlapping(lo, dst.add(1), 1);
         ptr::copy_nonoverlapping(hi, dst.add(2), 1);
         ptr::copy_nonoverlapping(max, dst.add(3), 1);
     }
-
-    #[inline(always)]
-    fn select<T>(cond: bool, if_true: *const T, if_false: *const T) -> *const T {
-        if cond { if_true } else { if_false }
-    }
 }
 
 /// SAFETY: The caller MUST guarantee that `v_base` is valid for 8 reads and
diff --git a/library/core/src/str/pattern.rs b/library/core/src/str/pattern.rs
index 52e2364893eb1..2d941adfd859c 100644
--- a/library/core/src/str/pattern.rs
+++ b/library/core/src/str/pattern.rs
@@ -38,6 +38,7 @@
     issue = "27721"
 )]
 
+use crate::char::MAX_LEN_UTF8;
 use crate::cmp::Ordering;
 use crate::convert::TryInto as _;
 use crate::slice::memchr;
@@ -561,8 +562,8 @@ impl Pattern for char {
     type Searcher<'a> = CharSearcher<'a>;
 
     #[inline]
-    fn into_searcher(self, haystack: &str) -> Self::Searcher<'_> {
-        let mut utf8_encoded = [0; 4];
+    fn into_searcher<'a>(self, haystack: &'a str) -> Self::Searcher<'a> {
+        let mut utf8_encoded = [0; MAX_LEN_UTF8];
         let utf8_size = self
             .encode_utf8(&mut utf8_encoded)
             .len()
diff --git a/library/coretests/tests/char.rs b/library/coretests/tests/char.rs
index 6422387e9560b..153fb36925e66 100644
--- a/library/coretests/tests/char.rs
+++ b/library/coretests/tests/char.rs
@@ -1,3 +1,4 @@
+use std::char::MAX_LEN_UTF8;
 use std::str::FromStr;
 use std::{char, str};
 
@@ -259,7 +260,7 @@ fn test_escape_unicode() {
 #[test]
 fn test_encode_utf8() {
     fn check(input: char, expect: &[u8]) {
-        let mut buf = [0; 4];
+        let mut buf = [0; MAX_LEN_UTF8];
         let ptr = buf.as_ptr();
         let s = input.encode_utf8(&mut buf);
         assert_eq!(s.as_ptr() as usize, ptr as usize);
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 1e1ff29e16151..25c7d10e0bd8f 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -13,6 +13,7 @@
 #![feature(bigint_helper_methods)]
 #![feature(bstr)]
 #![feature(cell_update)]
+#![feature(char_max_len)]
 #![feature(clone_to_uninit)]
 #![feature(const_eval_select)]
 #![feature(const_swap_nonoverlapping)]
diff --git a/library/portable-simd/crates/core_simd/src/masks.rs b/library/portable-simd/crates/core_simd/src/masks.rs
index b763a7c75a5a6..19d45f4d3b31a 100644
--- a/library/portable-simd/crates/core_simd/src/masks.rs
+++ b/library/portable-simd/crates/core_simd/src/masks.rs
@@ -401,7 +401,6 @@ where
     LaneCount<N>: SupportedLaneCount,
 {
     #[inline]
-    #[must_use = "method returns a defaulted mask with all elements set to false (0)"]
     fn default() -> Self {
         Self::splat(false)
     }
@@ -413,7 +412,6 @@ where
     LaneCount<N>: SupportedLaneCount,
 {
     #[inline]
-    #[must_use = "method returns a new bool and does not mutate the original value"]
     fn eq(&self, other: &Self) -> bool {
         self.0 == other.0
     }
@@ -425,7 +423,6 @@ where
     LaneCount<N>: SupportedLaneCount,
 {
     #[inline]
-    #[must_use = "method returns a new Ordering and does not mutate the original value"]
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         self.0.partial_cmp(&other.0)
     }
@@ -451,7 +448,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitand(self, rhs: Self) -> Self {
         Self(self.0 & rhs.0)
     }
@@ -464,7 +460,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitand(self, rhs: bool) -> Self {
         self & Self::splat(rhs)
     }
@@ -477,7 +472,6 @@ where
 {
     type Output = Mask<T, N>;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitand(self, rhs: Mask<T, N>) -> Mask<T, N> {
         Mask::splat(self) & rhs
     }
@@ -490,7 +484,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitor(self, rhs: Self) -> Self {
         Self(self.0 | rhs.0)
     }
@@ -503,7 +496,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitor(self, rhs: bool) -> Self {
         self | Self::splat(rhs)
     }
@@ -516,7 +508,6 @@ where
 {
     type Output = Mask<T, N>;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitor(self, rhs: Mask<T, N>) -> Mask<T, N> {
         Mask::splat(self) | rhs
     }
@@ -529,7 +520,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitxor(self, rhs: Self) -> Self::Output {
         Self(self.0 ^ rhs.0)
     }
@@ -542,7 +532,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitxor(self, rhs: bool) -> Self::Output {
         self ^ Self::splat(rhs)
     }
@@ -555,7 +544,6 @@ where
 {
     type Output = Mask<T, N>;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitxor(self, rhs: Mask<T, N>) -> Self::Output {
         Mask::splat(self) ^ rhs
     }
@@ -568,7 +556,6 @@ where
 {
     type Output = Mask<T, N>;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn not(self) -> Self::Output {
         Self(!self.0)
     }
diff --git a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs
index 2d01946b5747c..387b508c4b4ef 100644
--- a/library/portable-simd/crates/core_simd/src/masks/full_masks.rs
+++ b/library/portable-simd/crates/core_simd/src/masks/full_masks.rs
@@ -21,7 +21,6 @@ where
     LaneCount<N>: SupportedLaneCount,
 {
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn clone(&self) -> Self {
         *self
     }
@@ -252,7 +251,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitand(self, rhs: Self) -> Self {
         // Safety: `self` is an integer vector
         unsafe { Self(core::intrinsics::simd::simd_and(self.0, rhs.0)) }
@@ -266,7 +264,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitor(self, rhs: Self) -> Self {
         // Safety: `self` is an integer vector
         unsafe { Self(core::intrinsics::simd::simd_or(self.0, rhs.0)) }
@@ -280,7 +277,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn bitxor(self, rhs: Self) -> Self {
         // Safety: `self` is an integer vector
         unsafe { Self(core::intrinsics::simd::simd_xor(self.0, rhs.0)) }
@@ -294,7 +290,6 @@ where
 {
     type Output = Self;
     #[inline]
-    #[must_use = "method returns a new mask and does not mutate the original value"]
     fn not(self) -> Self::Output {
         Self::splat(true) ^ self
     }
diff --git a/library/portable-simd/crates/core_simd/src/ops.rs b/library/portable-simd/crates/core_simd/src/ops.rs
index d3bd14a340278..4ac64a253a3bd 100644
--- a/library/portable-simd/crates/core_simd/src/ops.rs
+++ b/library/portable-simd/crates/core_simd/src/ops.rs
@@ -135,7 +135,6 @@ macro_rules! for_base_types {
                     type Output = $out;
 
                     #[inline]
-                    #[must_use = "operator returns a new vector without mutating the inputs"]
                     // TODO: only useful for int Div::div, but we hope that this
                     // will essentially always get inlined anyway.
                     #[track_caller]
diff --git a/library/portable-simd/crates/core_simd/src/ops/deref.rs b/library/portable-simd/crates/core_simd/src/ops/deref.rs
index 0ff76cfba39bb..913cbbe977c46 100644
--- a/library/portable-simd/crates/core_simd/src/ops/deref.rs
+++ b/library/portable-simd/crates/core_simd/src/ops/deref.rs
@@ -18,7 +18,6 @@ macro_rules! deref_lhs {
             type Output = Simd<T, N>;
 
             #[inline]
-            #[must_use = "operator returns a new vector without mutating the inputs"]
             fn $call(self, rhs: $simd) -> Self::Output {
                 (*self).$call(rhs)
             }
@@ -39,7 +38,6 @@ macro_rules! deref_rhs {
             type Output = Simd<T, N>;
 
             #[inline]
-            #[must_use = "operator returns a new vector without mutating the inputs"]
             fn $call(self, rhs: &$simd) -> Self::Output {
                 self.$call(*rhs)
             }
@@ -71,7 +69,6 @@ macro_rules! deref_ops {
                 type Output = $simd;
 
                 #[inline]
-                #[must_use = "operator returns a new vector without mutating the inputs"]
                 fn $call(self, rhs: &'rhs $simd) -> Self::Output {
                     (*self).$call(*rhs)
                 }
diff --git a/library/portable-simd/crates/core_simd/src/ops/unary.rs b/library/portable-simd/crates/core_simd/src/ops/unary.rs
index bdae96332a3ae..412a5b801171b 100644
--- a/library/portable-simd/crates/core_simd/src/ops/unary.rs
+++ b/library/portable-simd/crates/core_simd/src/ops/unary.rs
@@ -11,7 +11,6 @@ macro_rules! neg {
             type Output = Self;
 
             #[inline]
-            #[must_use = "operator returns a new vector without mutating the input"]
             fn neg(self) -> Self::Output {
                 // Safety: `self` is a signed vector
                 unsafe { core::intrinsics::simd::simd_neg(self) }
@@ -46,7 +45,6 @@ macro_rules! not {
             type Output = Self;
 
             #[inline]
-            #[must_use = "operator returns a new vector without mutating the input"]
             fn not(self) -> Self::Output {
                 self ^ (Simd::splat(!(0 as $scalar)))
             }
diff --git a/library/portable-simd/crates/core_simd/src/simd/num/float.rs b/library/portable-simd/crates/core_simd/src/simd/num/float.rs
index 79954b937b397..db705dfe20221 100644
--- a/library/portable-simd/crates/core_simd/src/simd/num/float.rs
+++ b/library/portable-simd/crates/core_simd/src/simd/num/float.rs
@@ -371,7 +371,6 @@ macro_rules! impl_trait {
             }
 
             #[inline]
-            #[must_use = "method returns a new mask and does not mutate the original value"]
             fn is_normal(self) -> Self::Mask {
                 !(self.abs().simd_eq(Self::splat(0.0)) | self.is_nan() | self.is_subnormal() | self.is_infinite())
             }
diff --git a/library/std/src/fs/tests.rs b/library/std/src/fs/tests.rs
index 8e307f57cf9d2..1a266f71965d9 100644
--- a/library/std/src/fs/tests.rs
+++ b/library/std/src/fs/tests.rs
@@ -1,5 +1,6 @@
 use rand::RngCore;
 
+use crate::char::MAX_LEN_UTF8;
 use crate::fs::{self, File, FileTimes, OpenOptions};
 use crate::io::prelude::*;
 use crate::io::{BorrowedBuf, ErrorKind, SeekFrom};
@@ -155,7 +156,7 @@ fn file_test_io_non_positional_read() {
 #[test]
 fn file_test_io_seek_and_tell_smoke_test() {
     let message = "ten-four";
-    let mut read_mem = [0; 4];
+    let mut read_mem = [0; MAX_LEN_UTF8];
     let set_cursor = 4 as u64;
     let tell_pos_pre_read;
     let tell_pos_post_read;
@@ -356,7 +357,7 @@ fn file_test_io_seek_shakedown() {
     let chunk_one: &str = "qwer";
     let chunk_two: &str = "asdf";
     let chunk_three: &str = "zxcv";
-    let mut read_mem = [0; 4];
+    let mut read_mem = [0; MAX_LEN_UTF8];
     let tmpdir = tmpdir();
     let filename = &tmpdir.join("file_rt_io_file_test_seek_shakedown.txt");
     {
@@ -621,7 +622,7 @@ fn file_test_directoryinfo_readdir() {
         check!(w.write(msg));
     }
     let files = check!(fs::read_dir(dir));
-    let mut mem = [0; 4];
+    let mut mem = [0; MAX_LEN_UTF8];
     for f in files {
         let f = f.unwrap().path();
         {
diff --git a/library/std/src/lib.rs b/library/std/src/lib.rs
index 750116c6269dd..0661b3d770e48 100644
--- a/library/std/src/lib.rs
+++ b/library/std/src/lib.rs
@@ -284,6 +284,7 @@
 #![feature(cfg_sanitizer_cfi)]
 #![feature(cfg_target_thread_local)]
 #![feature(cfi_encoding)]
+#![feature(char_max_len)]
 #![feature(concat_idents)]
 #![feature(decl_macro)]
 #![feature(deprecated_suggestion)]
diff --git a/library/std/src/sys/os_str/bytes.rs b/library/std/src/sys/os_str/bytes.rs
index 5b65d862be102..1d337694944bc 100644
--- a/library/std/src/sys/os_str/bytes.rs
+++ b/library/std/src/sys/os_str/bytes.rs
@@ -8,7 +8,7 @@ use crate::collections::TryReserveError;
 use crate::fmt::Write;
 use crate::rc::Rc;
 use crate::sync::Arc;
-use crate::sys_common::{AsInner, IntoInner};
+use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::{fmt, mem, str};
 
 #[cfg(test)]
@@ -25,6 +25,37 @@ pub struct Slice {
     pub inner: [u8],
 }
 
+impl IntoInner<Vec<u8>> for Buf {
+    fn into_inner(self) -> Vec<u8> {
+        self.inner
+    }
+}
+
+impl FromInner<Vec<u8>> for Buf {
+    fn from_inner(inner: Vec<u8>) -> Self {
+        Buf { inner }
+    }
+}
+
+impl AsInner<[u8]> for Buf {
+    #[inline]
+    fn as_inner(&self) -> &[u8] {
+        &self.inner
+    }
+}
+
+impl fmt::Debug for Buf {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(self.as_slice(), f)
+    }
+}
+
+impl fmt::Display for Buf {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), f)
+    }
+}
+
 impl fmt::Debug for Slice {
     fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
         fmt::Debug::fmt(&self.inner.utf8_chunks().debug(), f)
@@ -55,18 +86,6 @@ impl fmt::Display for Slice {
     }
 }
 
-impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(self.as_slice(), formatter)
-    }
-}
-
-impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self.as_slice(), formatter)
-    }
-}
-
 impl Clone for Buf {
     #[inline]
     fn clone(&self) -> Self {
@@ -79,19 +98,6 @@ impl Clone for Buf {
     }
 }
 
-impl IntoInner<Vec<u8>> for Buf {
-    fn into_inner(self) -> Vec<u8> {
-        self.inner
-    }
-}
-
-impl AsInner<[u8]> for Buf {
-    #[inline]
-    fn as_inner(&self) -> &[u8] {
-        &self.inner
-    }
-}
-
 impl Buf {
     #[inline]
     pub fn into_encoded_bytes(self) -> Vec<u8> {
@@ -103,6 +109,12 @@ impl Buf {
         Self { inner: s }
     }
 
+    #[inline]
+    pub fn into_string(self) -> Result<String, Buf> {
+        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() })
+    }
+
+    #[inline]
     pub fn from_string(s: String) -> Buf {
         Buf { inner: s.into_bytes() }
     }
@@ -122,6 +134,11 @@ impl Buf {
         self.inner.capacity()
     }
 
+    #[inline]
+    pub fn push_slice(&mut self, s: &Slice) {
+        self.inner.extend_from_slice(&s.inner)
+    }
+
     #[inline]
     pub fn reserve(&mut self, additional: usize) {
         self.inner.reserve(additional)
@@ -157,7 +174,7 @@ impl Buf {
         // SAFETY: Slice just wraps [u8],
         // and &*self.inner is &[u8], therefore
         // transmuting &[u8] to &Slice is safe.
-        unsafe { mem::transmute(&*self.inner) }
+        unsafe { mem::transmute(self.inner.as_slice()) }
     }
 
     #[inline]
@@ -165,15 +182,7 @@ impl Buf {
         // SAFETY: Slice just wraps [u8],
         // and &mut *self.inner is &mut [u8], therefore
         // transmuting &mut [u8] to &mut Slice is safe.
-        unsafe { mem::transmute(&mut *self.inner) }
-    }
-
-    pub fn into_string(self) -> Result<String, Buf> {
-        String::from_utf8(self.inner).map_err(|p| Buf { inner: p.into_bytes() })
-    }
-
-    pub fn push_slice(&mut self, s: &Slice) {
-        self.inner.extend_from_slice(&s.inner)
+        unsafe { mem::transmute(self.inner.as_mut_slice()) }
     }
 
     #[inline]
@@ -278,18 +287,22 @@ impl Slice {
         unsafe { Slice::from_encoded_bytes_unchecked(s.as_bytes()) }
     }
 
+    #[inline]
     pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
         str::from_utf8(&self.inner)
     }
 
+    #[inline]
     pub fn to_string_lossy(&self) -> Cow<'_, str> {
         String::from_utf8_lossy(&self.inner)
     }
 
+    #[inline]
     pub fn to_owned(&self) -> Buf {
         Buf { inner: self.inner.to_vec() }
     }
 
+    #[inline]
     pub fn clone_into(&self, buf: &mut Buf) {
         self.inner.clone_into(&mut buf.inner)
     }
@@ -300,6 +313,7 @@ impl Slice {
         unsafe { mem::transmute(boxed) }
     }
 
+    #[inline]
     pub fn empty_box() -> Box<Slice> {
         let boxed: Box<[u8]> = Default::default();
         unsafe { mem::transmute(boxed) }
diff --git a/library/std/src/sys/os_str/wtf8.rs b/library/std/src/sys/os_str/wtf8.rs
index a4ad5966afe57..19728d33990ac 100644
--- a/library/std/src/sys/os_str/wtf8.rs
+++ b/library/std/src/sys/os_str/wtf8.rs
@@ -10,11 +10,16 @@ use crate::sys_common::wtf8::{Wtf8, Wtf8Buf, check_utf8_boundary};
 use crate::sys_common::{AsInner, FromInner, IntoInner};
 use crate::{fmt, mem};
 
-#[derive(Clone, Hash)]
+#[derive(Hash)]
 pub struct Buf {
     pub inner: Wtf8Buf,
 }
 
+#[repr(transparent)]
+pub struct Slice {
+    pub inner: Wtf8,
+}
+
 impl IntoInner<Wtf8Buf> for Buf {
     fn into_inner(self) -> Wtf8Buf {
         self.inner
@@ -35,31 +40,38 @@ impl AsInner<Wtf8> for Buf {
 }
 
 impl fmt::Debug for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(self.as_slice(), formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(self.as_slice(), f)
     }
 }
 
 impl fmt::Display for Buf {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(self.as_slice(), formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(self.as_slice(), f)
     }
 }
 
-#[repr(transparent)]
-pub struct Slice {
-    pub inner: Wtf8,
-}
-
 impl fmt::Debug for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Debug::fmt(&self.inner, formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Debug::fmt(&self.inner, f)
     }
 }
 
 impl fmt::Display for Slice {
-    fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
-        fmt::Display::fmt(&self.inner, formatter)
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        fmt::Display::fmt(&self.inner, f)
+    }
+}
+
+impl Clone for Buf {
+    #[inline]
+    fn clone(&self) -> Self {
+        Buf { inner: self.inner.clone() }
+    }
+
+    #[inline]
+    fn clone_from(&mut self, source: &Self) {
+        self.inner.clone_from(&source.inner)
     }
 }
 
@@ -74,62 +86,57 @@ impl Buf {
         unsafe { Self { inner: Wtf8Buf::from_bytes_unchecked(s) } }
     }
 
-    pub fn with_capacity(capacity: usize) -> Buf {
-        Buf { inner: Wtf8Buf::with_capacity(capacity) }
-    }
-
-    pub fn clear(&mut self) {
-        self.inner.clear()
-    }
-
-    pub fn capacity(&self) -> usize {
-        self.inner.capacity()
+    #[inline]
+    pub fn into_string(self) -> Result<String, Buf> {
+        self.inner.into_string().map_err(|buf| Buf { inner: buf })
     }
 
+    #[inline]
     pub fn from_string(s: String) -> Buf {
         Buf { inner: Wtf8Buf::from_string(s) }
     }
 
-    pub fn as_slice(&self) -> &Slice {
-        // SAFETY: Slice is just a wrapper for Wtf8,
-        // and self.inner.as_slice() returns &Wtf8.
-        // Therefore, transmuting &Wtf8 to &Slice is safe.
-        unsafe { mem::transmute(self.inner.as_slice()) }
+    #[inline]
+    pub fn with_capacity(capacity: usize) -> Buf {
+        Buf { inner: Wtf8Buf::with_capacity(capacity) }
     }
 
-    pub fn as_mut_slice(&mut self) -> &mut Slice {
-        // SAFETY: Slice is just a wrapper for Wtf8,
-        // and self.inner.as_mut_slice() returns &mut Wtf8.
-        // Therefore, transmuting &mut Wtf8 to &mut Slice is safe.
-        // Additionally, care should be taken to ensure the slice
-        // is always valid Wtf8.
-        unsafe { mem::transmute(self.inner.as_mut_slice()) }
+    #[inline]
+    pub fn clear(&mut self) {
+        self.inner.clear()
     }
 
-    pub fn into_string(self) -> Result<String, Buf> {
-        self.inner.into_string().map_err(|buf| Buf { inner: buf })
+    #[inline]
+    pub fn capacity(&self) -> usize {
+        self.inner.capacity()
     }
 
+    #[inline]
     pub fn push_slice(&mut self, s: &Slice) {
         self.inner.push_wtf8(&s.inner)
     }
 
+    #[inline]
     pub fn reserve(&mut self, additional: usize) {
         self.inner.reserve(additional)
     }
 
+    #[inline]
     pub fn try_reserve(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.inner.try_reserve(additional)
     }
 
+    #[inline]
     pub fn reserve_exact(&mut self, additional: usize) {
         self.inner.reserve_exact(additional)
     }
 
+    #[inline]
     pub fn try_reserve_exact(&mut self, additional: usize) -> Result<(), TryReserveError> {
         self.inner.try_reserve_exact(additional)
     }
 
+    #[inline]
     pub fn shrink_to_fit(&mut self) {
         self.inner.shrink_to_fit()
     }
@@ -139,6 +146,24 @@ impl Buf {
         self.inner.shrink_to(min_capacity)
     }
 
+    #[inline]
+    pub fn as_slice(&self) -> &Slice {
+        // SAFETY: Slice is just a wrapper for Wtf8,
+        // and self.inner.as_slice() returns &Wtf8.
+        // Therefore, transmuting &Wtf8 to &Slice is safe.
+        unsafe { mem::transmute(self.inner.as_slice()) }
+    }
+
+    #[inline]
+    pub fn as_mut_slice(&mut self) -> &mut Slice {
+        // SAFETY: Slice is just a wrapper for Wtf8,
+        // and self.inner.as_mut_slice() returns &mut Wtf8.
+        // Therefore, transmuting &mut Wtf8 to &mut Slice is safe.
+        // Additionally, care should be taken to ensure the slice
+        // is always valid Wtf8.
+        unsafe { mem::transmute(self.inner.as_mut_slice()) }
+    }
+
     #[inline]
     pub fn leak<'a>(self) -> &'a mut Slice {
         unsafe { mem::transmute(self.inner.leak()) }
@@ -194,6 +219,7 @@ impl Slice {
     }
 
     #[track_caller]
+    #[inline]
     pub fn check_public_boundary(&self, index: usize) {
         check_utf8_boundary(&self.inner, index);
     }
@@ -203,18 +229,22 @@ impl Slice {
         unsafe { mem::transmute(Wtf8::from_str(s)) }
     }
 
+    #[inline]
     pub fn to_str(&self) -> Result<&str, crate::str::Utf8Error> {
         self.inner.as_str()
     }
 
+    #[inline]
     pub fn to_string_lossy(&self) -> Cow<'_, str> {
         self.inner.to_string_lossy()
     }
 
+    #[inline]
     pub fn to_owned(&self) -> Buf {
         Buf { inner: self.inner.to_owned() }
     }
 
+    #[inline]
     pub fn clone_into(&self, buf: &mut Buf) {
         self.inner.clone_into(&mut buf.inner)
     }
@@ -224,6 +254,7 @@ impl Slice {
         unsafe { mem::transmute(self.inner.into_box()) }
     }
 
+    #[inline]
     pub fn empty_box() -> Box<Slice> {
         unsafe { mem::transmute(Wtf8::empty_box()) }
     }
diff --git a/library/std/src/sys/pal/windows/stdio.rs b/library/std/src/sys/pal/windows/stdio.rs
index fd3f559ba1901..1b245991aa797 100644
--- a/library/std/src/sys/pal/windows/stdio.rs
+++ b/library/std/src/sys/pal/windows/stdio.rs
@@ -1,5 +1,6 @@
 #![unstable(issue = "none", feature = "windows_stdio")]
 
+use core::char::MAX_LEN_UTF8;
 use core::str::utf8_char_width;
 
 use super::api::{self, WinError};
@@ -426,7 +427,7 @@ fn utf16_to_utf8(utf16: &[u16], utf8: &mut [u8]) -> io::Result<usize> {
 
 impl IncompleteUtf8 {
     pub const fn new() -> IncompleteUtf8 {
-        IncompleteUtf8 { bytes: [0; 4], len: 0 }
+        IncompleteUtf8 { bytes: [0; MAX_LEN_UTF8], len: 0 }
     }
 }
 
diff --git a/library/std/src/sys_common/wtf8.rs b/library/std/src/sys_common/wtf8.rs
index 6c60d901ee904..952c39132b056 100644
--- a/library/std/src/sys_common/wtf8.rs
+++ b/library/std/src/sys_common/wtf8.rs
@@ -18,7 +18,7 @@
 #[cfg(test)]
 mod tests;
 
-use core::char::{encode_utf8_raw, encode_utf16_raw};
+use core::char::{MAX_LEN_UTF8, MAX_LEN_UTF16, encode_utf8_raw, encode_utf16_raw};
 use core::clone::CloneToUninit;
 use core::str::next_code_point;
 
@@ -156,9 +156,12 @@ impl ops::DerefMut for Wtf8Buf {
     }
 }
 
-/// Format the string with double quotes,
-/// and surrogates as `\u` followed by four hexadecimal digits.
-/// Example: `"a\u{D800}"` for a string with code points [U+0061, U+D800]
+/// Formats the string in double quotes, with characters escaped according to
+/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
+/// where each `x` is a hexadecimal digit.
+///
+/// For example, the code units [U+0061, U+D800, U+000A] are formatted as
+/// `"a\u{D800}\n"`.
 impl fmt::Debug for Wtf8Buf {
     #[inline]
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
@@ -181,7 +184,7 @@ impl Wtf8Buf {
 
     /// Creates a WTF-8 string from a WTF-8 byte vec.
     ///
-    /// Since the byte vec is not checked for valid WTF-8, this functions is
+    /// Since the byte vec is not checked for valid WTF-8, this function is
     /// marked unsafe.
     #[inline]
     pub unsafe fn from_bytes_unchecked(value: Vec<u8>) -> Wtf8Buf {
@@ -205,7 +208,7 @@ impl Wtf8Buf {
     /// Since WTF-8 is a superset of UTF-8, this always succeeds.
     #[inline]
     pub fn from_str(s: &str) -> Wtf8Buf {
-        Wtf8Buf { bytes: <[_]>::to_vec(s.as_bytes()), is_known_utf8: true }
+        Wtf8Buf { bytes: s.as_bytes().to_vec(), is_known_utf8: true }
     }
 
     pub fn clear(&mut self) {
@@ -237,10 +240,11 @@ impl Wtf8Buf {
         string
     }
 
-    /// Copied from String::push
+    /// Appends the given `char` to the end of this string.
     /// This does **not** include the WTF-8 concatenation check or `is_known_utf8` check.
+    /// Copied from String::push.
     fn push_code_point_unchecked(&mut self, code_point: CodePoint) {
-        let mut bytes = [0; 4];
+        let mut bytes = [0; MAX_LEN_UTF8];
         let bytes = encode_utf8_raw(code_point.value, &mut bytes);
         self.bytes.extend_from_slice(bytes)
     }
@@ -264,16 +268,16 @@ impl Wtf8Buf {
     ///
     /// # Panics
     ///
-    /// Panics if the new capacity overflows `usize`.
+    /// Panics if the new capacity exceeds `isize::MAX` bytes.
     #[inline]
     pub fn reserve(&mut self, additional: usize) {
         self.bytes.reserve(additional)
     }
 
-    /// Tries to reserve capacity for at least `additional` more length units
-    /// in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to avoid
-    /// frequent reallocations. After calling `try_reserve`, capacity will be
-    /// greater than or equal to `self.len() + additional`. Does nothing if
+    /// Tries to reserve capacity for at least `additional` more bytes to be
+    /// inserted in the given `Wtf8Buf`. The `Wtf8Buf` may reserve more space to
+    /// avoid frequent reallocations. After calling `try_reserve`, capacity will
+    /// be greater than or equal to `self.len() + additional`. Does nothing if
     /// capacity is already sufficient. This method preserves the contents even
     /// if an error occurs.
     ///
@@ -291,8 +295,8 @@ impl Wtf8Buf {
         self.bytes.reserve_exact(additional)
     }
 
-    /// Tries to reserve the minimum capacity for exactly `additional`
-    /// length units in the given `Wtf8Buf`. After calling
+    /// Tries to reserve the minimum capacity for exactly `additional` more
+    /// bytes to be inserted in the given `Wtf8Buf`. After calling
     /// `try_reserve_exact`, capacity will be greater than or equal to
     /// `self.len() + additional` if it returns `Ok(())`.
     /// Does nothing if the capacity is already sufficient.
@@ -440,22 +444,17 @@ impl Wtf8Buf {
     ///
     /// Surrogates are replaced with `"\u{FFFD}"` (the replacement character “�”)
     pub fn into_string_lossy(mut self) -> String {
-        // Fast path: If we already have UTF-8, we can return it immediately.
-        if self.is_known_utf8 {
-            return unsafe { String::from_utf8_unchecked(self.bytes) };
-        }
-
-        let mut pos = 0;
-        loop {
-            match self.next_surrogate(pos) {
-                Some((surrogate_pos, _)) => {
-                    pos = surrogate_pos + 3;
-                    self.bytes[surrogate_pos..pos]
-                        .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
-                }
-                None => return unsafe { String::from_utf8_unchecked(self.bytes) },
+        if !self.is_known_utf8 {
+            let mut pos = 0;
+            while let Some((surrogate_pos, _)) = self.next_surrogate(pos) {
+                pos = surrogate_pos + 3;
+                // Surrogates and the replacement character are all 3 bytes, so
+                // they can substituted in-place.
+                self.bytes[surrogate_pos..pos]
+                    .copy_from_slice(UTF8_REPLACEMENT_CHARACTER.as_bytes());
             }
         }
+        unsafe { String::from_utf8_unchecked(self.bytes) }
     }
 
     /// Converts this `Wtf8Buf` into a boxed `Wtf8`.
@@ -535,9 +534,9 @@ impl AsInner<[u8]> for Wtf8 {
     }
 }
 
-/// Format the slice with double quotes,
-/// and surrogates as `\u` followed by four hexadecimal digits.
-/// Example: `"a\u{D800}"` for a slice with code points [U+0061, U+D800]
+/// Formats the string in double quotes, with characters escaped according to
+/// [`char::escape_debug`] and unpaired surrogates represented as `\u{xxxx}`,
+/// where each `x` is a hexadecimal digit.
 impl fmt::Debug for Wtf8 {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         fn write_str_escaped(f: &mut fmt::Formatter<'_>, s: &str) -> fmt::Result {
@@ -562,6 +561,8 @@ impl fmt::Debug for Wtf8 {
     }
 }
 
+/// Formats the string with unpaired surrogates substituted with the replacement
+/// character, U+FFFD.
 impl fmt::Display for Wtf8 {
     fn fmt(&self, formatter: &mut fmt::Formatter<'_>) -> fmt::Result {
         let wtf8_bytes = &self.bytes;
@@ -672,9 +673,8 @@ impl Wtf8 {
     ///
     /// This only copies the data if necessary (if it contains any surrogate).
     pub fn to_string_lossy(&self) -> Cow<'_, str> {
-        let surrogate_pos = match self.next_surrogate(0) {
-            None => return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) }),
-            Some((pos, _)) => pos,
+        let Some((surrogate_pos, _)) = self.next_surrogate(0) else {
+            return Cow::Borrowed(unsafe { str::from_utf8_unchecked(&self.bytes) });
         };
         let wtf8_bytes = &self.bytes;
         let mut utf8_bytes = Vec::with_capacity(self.len());
@@ -964,7 +964,7 @@ pub struct Wtf8CodePoints<'a> {
     bytes: slice::Iter<'a, u8>,
 }
 
-impl<'a> Iterator for Wtf8CodePoints<'a> {
+impl Iterator for Wtf8CodePoints<'_> {
     type Item = CodePoint;
 
     #[inline]
@@ -990,7 +990,7 @@ pub struct EncodeWide<'a> {
 
 // Copied from libunicode/u_str.rs
 #[stable(feature = "rust1", since = "1.0.0")]
-impl<'a> Iterator for EncodeWide<'a> {
+impl Iterator for EncodeWide<'_> {
     type Item = u16;
 
     #[inline]
@@ -1001,7 +1001,7 @@ impl<'a> Iterator for EncodeWide<'a> {
             return Some(tmp);
         }
 
-        let mut buf = [0; 2];
+        let mut buf = [0; MAX_LEN_UTF16];
         self.code_points.next().map(|code_point| {
             let n = encode_utf16_raw(code_point.value, &mut buf).len();
             if n == 2 {
diff --git a/src/ci/scripts/install-mingw.sh b/src/ci/scripts/install-mingw.sh
index 91eab2e7a0816..c8c501e646a9d 100755
--- a/src/ci/scripts/install-mingw.sh
+++ b/src/ci/scripts/install-mingw.sh
@@ -32,6 +32,12 @@ if isWindows && isKnownToBeMingwBuild; then
             ;;
     esac
 
+    # Stop /msys64/bin from being prepended to PATH by adding the bin directory manually.
+    # Note that this intentionally uses a Windows style path instead of the msys2 path to
+    # avoid being auto-translated into `/usr/bin`, which will not have the desired effect.
+    msys2Path="c:/msys64"
+    ciCommandAddPath "${msys2Path}/usr/bin"
+
     mingw_dir="mingw${bits}"
 
     curl -o mingw.7z "${MIRRORS_BASE}/${mingw_archive}"
diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md
index bc58768611175..bfdb579cd3523 100644
--- a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md
+++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024-structural.md
@@ -10,10 +10,11 @@ This feature is incomplete and not yet intended for general use.
 
 This implements experimental, Edition-dependent match ergonomics under consideration for inclusion
 in Rust.
-For more information, see the corresponding typing rules for [Editions 2024 and later].
-On earlier Editions, the current behavior is unspecified.
+For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for
+[Editions 2024 and later].
 
 For alternative experimental match ergonomics, see the feature
 [`ref_pat_eat_one_layer_2024`](./ref-pat-eat-one-layer-2024.md).
 
+[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQEBAAAAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false
 [Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAgEBAQEBAgIAAAAAAAAAAAAAAAA%3D&mode=rules&do_cmp=false
diff --git a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md
index 43de1849a5ebb..0c90cec0dbddb 100644
--- a/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md
+++ b/src/doc/unstable-book/src/language-features/ref-pat-eat-one-layer-2024.md
@@ -10,10 +10,11 @@ This feature is incomplete and not yet intended for general use.
 
 This implements experimental, Edition-dependent match ergonomics under consideration for inclusion
 in Rust.
-For more information, see the corresponding typing rules for [Editions 2024 and later].
-On earlier Editions, the current behavior is unspecified.
+For more information, see the corresponding typing rules for [Editions 2021 and earlier] and for
+[Editions 2024 and later].
 
 For alternative experimental match ergonomics, see the feature
 [`ref_pat_eat_one_layer_2024_structural`](./ref-pat-eat-one-layer-2024-structural.md).
 
+[Editions 2021 and earlier]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAQIBAQABAAAAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false
 [Editions 2024 and later]: https://nadrieril.github.io/typing-rust-patterns/?compare=false&opts1=AQEBAAABAQABAgIAAQEBAAEBAAABAAA%3D&mode=rules&do_cmp=false
diff --git a/src/tools/clippy/clippy_lints/src/infinite_iter.rs b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
index 3cb47d8ef9191..960b9aa032bea 100644
--- a/src/tools/clippy/clippy_lints/src/infinite_iter.rs
+++ b/src/tools/clippy/clippy_lints/src/infinite_iter.rs
@@ -94,7 +94,6 @@ impl Finiteness {
 }
 
 impl From<bool> for Finiteness {
-    #[must_use]
     fn from(b: bool) -> Self {
         if b { Infinite } else { Finite }
     }
diff --git a/src/tools/clippy/clippy_utils/src/consts.rs b/src/tools/clippy/clippy_utils/src/consts.rs
index 4f707e34abf9a..dd149c4a29b9f 100644
--- a/src/tools/clippy/clippy_utils/src/consts.rs
+++ b/src/tools/clippy/clippy_utils/src/consts.rs
@@ -351,21 +351,18 @@ pub enum FullInt {
 }
 
 impl PartialEq for FullInt {
-    #[must_use]
     fn eq(&self, other: &Self) -> bool {
         self.cmp(other) == Ordering::Equal
     }
 }
 
 impl PartialOrd for FullInt {
-    #[must_use]
     fn partial_cmp(&self, other: &Self) -> Option<Ordering> {
         Some(self.cmp(other))
     }
 }
 
 impl Ord for FullInt {
-    #[must_use]
     fn cmp(&self, other: &Self) -> Ordering {
         use FullInt::{S, U};
 
diff --git a/src/tools/tidy/src/issues.txt b/src/tools/tidy/src/issues.txt
index 39c9a148e9e56..1cb47353469fa 100644
--- a/src/tools/tidy/src/issues.txt
+++ b/src/tools/tidy/src/issues.txt
@@ -3619,7 +3619,6 @@ ui/resolve/issue-21221-1.rs
 ui/resolve/issue-21221-2.rs
 ui/resolve/issue-21221-3.rs
 ui/resolve/issue-21221-4.rs
-ui/resolve/issue-22692.rs
 ui/resolve/issue-2330.rs
 ui/resolve/issue-23305.rs
 ui/resolve/issue-2356.rs
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.rs b/tests/ui/lint/unused/unused_attributes-must_use.rs
index 51f868706b69b..860fc5046d103 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.rs
+++ b/tests/ui/lint/unused/unused_attributes-must_use.rs
@@ -79,6 +79,11 @@ trait Use {
 #[must_use] //~ ERROR `#[must_use]` has no effect
 impl Use for () {
     type AssocTy = ();
+
+    #[must_use] //~ ERROR `#[must_use]` has no effect
+    fn get_four(&self) -> usize {
+        4
+    }
 }
 
 #[must_use] //~ ERROR `#[must_use]` has no effect
diff --git a/tests/ui/lint/unused/unused_attributes-must_use.stderr b/tests/ui/lint/unused/unused_attributes-must_use.stderr
index 9633767c44287..28fd8eeb8cbdc 100644
--- a/tests/ui/lint/unused/unused_attributes-must_use.stderr
+++ b/tests/ui/lint/unused/unused_attributes-must_use.stderr
@@ -76,43 +76,43 @@ LL | #[must_use]
    | ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a trait alias
-  --> $DIR/unused_attributes-must_use.rs:84:1
+  --> $DIR/unused_attributes-must_use.rs:89:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a macro def
-  --> $DIR/unused_attributes-must_use.rs:87:1
+  --> $DIR/unused_attributes-must_use.rs:92:1
    |
 LL | #[must_use]
    | ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a statement
-  --> $DIR/unused_attributes-must_use.rs:95:5
+  --> $DIR/unused_attributes-must_use.rs:100:5
    |
 LL |     #[must_use]
    |     ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a closure
-  --> $DIR/unused_attributes-must_use.rs:99:13
+  --> $DIR/unused_attributes-must_use.rs:104:13
    |
 LL |     let x = #[must_use]
    |             ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to an match arm
-  --> $DIR/unused_attributes-must_use.rs:121:9
+  --> $DIR/unused_attributes-must_use.rs:126:9
    |
 LL |         #[must_use]
    |         ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a struct field
-  --> $DIR/unused_attributes-must_use.rs:129:28
+  --> $DIR/unused_attributes-must_use.rs:134:28
    |
 LL |     let s = PatternField { #[must_use]  foo: 123 };
    |                            ^^^^^^^^^^^
 
 error: `#[must_use]` has no effect when applied to a pattern field
-  --> $DIR/unused_attributes-must_use.rs:130:24
+  --> $DIR/unused_attributes-must_use.rs:135:24
    |
 LL |     let PatternField { #[must_use] foo } = s;
    |                        ^^^^^^^^^^^
@@ -129,6 +129,12 @@ error: `#[must_use]` has no effect when applied to an associated type
 LL |     #[must_use]
    |     ^^^^^^^^^^^
 
+error: `#[must_use]` has no effect when applied to a provided trait method
+  --> $DIR/unused_attributes-must_use.rs:83:5
+   |
+LL |     #[must_use]
+   |     ^^^^^^^^^^^
+
 error: `#[must_use]` has no effect when applied to a foreign static item
   --> $DIR/unused_attributes-must_use.rs:50:5
    |
@@ -136,7 +142,7 @@ LL |     #[must_use]
    |     ^^^^^^^^^^^
 
 error: unused `X` that must be used
-  --> $DIR/unused_attributes-must_use.rs:103:5
+  --> $DIR/unused_attributes-must_use.rs:108:5
    |
 LL |     X;
    |     ^
@@ -152,7 +158,7 @@ LL |     let _ = X;
    |     +++++++
 
 error: unused `Y` that must be used
-  --> $DIR/unused_attributes-must_use.rs:104:5
+  --> $DIR/unused_attributes-must_use.rs:109:5
    |
 LL |     Y::Z;
    |     ^^^^
@@ -163,7 +169,7 @@ LL |     let _ = Y::Z;
    |     +++++++
 
 error: unused `U` that must be used
-  --> $DIR/unused_attributes-must_use.rs:105:5
+  --> $DIR/unused_attributes-must_use.rs:110:5
    |
 LL |     U { unit: () };
    |     ^^^^^^^^^^^^^^
@@ -174,7 +180,7 @@ LL |     let _ = U { unit: () };
    |     +++++++
 
 error: unused return value of `U::method` that must be used
-  --> $DIR/unused_attributes-must_use.rs:106:5
+  --> $DIR/unused_attributes-must_use.rs:111:5
    |
 LL |     U::method();
    |     ^^^^^^^^^^^
@@ -185,7 +191,7 @@ LL |     let _ = U::method();
    |     +++++++
 
 error: unused return value of `foo` that must be used
-  --> $DIR/unused_attributes-must_use.rs:107:5
+  --> $DIR/unused_attributes-must_use.rs:112:5
    |
 LL |     foo();
    |     ^^^^^
@@ -196,7 +202,7 @@ LL |     let _ = foo();
    |     +++++++
 
 error: unused return value of `foreign_foo` that must be used
-  --> $DIR/unused_attributes-must_use.rs:110:9
+  --> $DIR/unused_attributes-must_use.rs:115:9
    |
 LL |         foreign_foo();
    |         ^^^^^^^^^^^^^
@@ -207,7 +213,7 @@ LL |         let _ = foreign_foo();
    |         +++++++
 
 error: unused return value of `Use::get_four` that must be used
-  --> $DIR/unused_attributes-must_use.rs:118:5
+  --> $DIR/unused_attributes-must_use.rs:123:5
    |
 LL |     ().get_four();
    |     ^^^^^^^^^^^^^
@@ -217,5 +223,5 @@ help: use `let _ = ...` to ignore the resulting value
 LL |     let _ = ().get_four();
    |     +++++++
 
-error: aborting due to 28 previous errors
+error: aborting due to 29 previous errors
 
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/auxiliary/mixed-editions-macros.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/auxiliary/mixed-editions-macros.rs
new file mode 100644
index 0000000000000..14d26be91a082
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/auxiliary/mixed-editions-macros.rs
@@ -0,0 +1,48 @@
+//@[classic2021] edition: 2024
+//@[structural2021] edition: 2024
+//@[classic2024] edition: 2021
+//@[structural2024] edition: 2021
+//! This contains macros in an edition *different* to the one used in `../mixed-editions.rs`, in
+//! order to test typing mixed-edition patterns.
+
+#[macro_export]
+macro_rules! match_ctor {
+    ($p:pat) => {
+        [$p]
+    };
+}
+
+#[macro_export]
+macro_rules! match_ref {
+    ($p:pat) => {
+        &$p
+    };
+}
+
+#[macro_export]
+macro_rules! bind {
+    ($i:ident) => {
+        $i
+    }
+}
+
+#[macro_export]
+macro_rules! bind_ref {
+    ($i:ident) => {
+        ref $i
+    }
+}
+
+#[macro_export]
+macro_rules! bind_mut {
+    ($i:ident) => {
+        mut $i
+    }
+}
+
+#[macro_export]
+macro_rules! bind_ref_mut {
+    ($i:ident) => {
+        ref mut $i
+    }
+}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr
new file mode 100644
index 0000000000000..355a8af6760f3
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2021.stderr
@@ -0,0 +1,37 @@
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/borrowck-errors.rs:31:29
+   |
+LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+   |                       -     ^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       data moved here
+   |                       move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
+   |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-errors.rs:36:10
+   |
+LL |     let &ref mut x = &0;
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-errors.rs:41:23
+   |
+LL |     if let &Some(Some(x)) = &Some(&mut Some(0)) {
+   |                       ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-errors.rs:46:11
+   |
+LL |     let &[x] = &&mut [0];
+   |           ^ cannot borrow as mutable
+
+error: aborting due to 4 previous errors
+
+Some errors have detailed explanations: E0507, E0596.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
index 1c44617830828..d40bdb9111b30 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.classic2024.stderr
@@ -1,25 +1,25 @@
-error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array
-  --> $DIR/borrowck-errors.rs:13:16
+error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
+  --> $DIR/borrowck-errors.rs:15:16
    |
 LL |     let [&x] = &[&mut 0];
    |           -    ^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
-   |           move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |           move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
    |
 help: consider borrowing the pattern binding
    |
 LL |     let [&ref x] = &[&mut 0];
    |           +++
 
-error[E0508]: cannot move out of type `[&mut u32; 1]`, a non-copy array
-  --> $DIR/borrowck-errors.rs:19:16
+error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
+  --> $DIR/borrowck-errors.rs:22:16
    |
 LL |     let [&x] = &mut [&mut 0];
    |           -    ^^^^^^^^^^^^^ cannot move out of here
    |           |
    |           data moved here
-   |           move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |           move occurs because `x` has type `&mut i32`, which does not implement the `Copy` trait
    |
 help: consider borrowing the pattern binding
    |
@@ -27,7 +27,7 @@ LL |     let [&ref x] = &mut [&mut 0];
    |           +++
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/borrowck-errors.rs:27:29
+  --> $DIR/borrowck-errors.rs:31:29
    |
 LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
    |                       -     ^^^^^^^^^^^^^^^^^^^
@@ -42,25 +42,25 @@ LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
    |
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:32:10
+  --> $DIR/borrowck-errors.rs:36:10
    |
 LL |     let &ref mut x = &0;
    |          ^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:37:23
+  --> $DIR/borrowck-errors.rs:41:23
    |
 LL |     if let &Some(Some(x)) = &Some(&mut Some(0)) {
    |                       ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:42:11
+  --> $DIR/borrowck-errors.rs:46:11
    |
 LL |     let &[x] = &&mut [0];
    |           ^ cannot borrow as mutable
 
 error[E0508]: cannot move out of type `[&mut i32; 1]`, a non-copy array
-  --> $DIR/borrowck-errors.rs:46:20
+  --> $DIR/borrowck-errors.rs:50:20
    |
 LL |     let [&mut x] = &mut [&mut 0];
    |               -    ^^^^^^^^^^^^^ cannot move out of here
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
index 59cafc50d8661..621ca7cc792eb 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.rs
@@ -1,11 +1,13 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //! Tests for pattern errors not handled by the pattern typing rules, but by borrowck.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 /// These patterns additionally use `&` to match a `&mut` reference type, which causes compilation
 /// to fail in HIR typeck on stable. As such, they need to be separate from the other tests.
@@ -14,13 +16,15 @@ fn errors_caught_in_hir_typeck_on_stable() {
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
     //[classic2024]~^^^ ERROR: cannot move out of type
-    let _: &u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: u32 = x;
+    #[cfg(structural2024)] let _: &u32 = x;
 
     let [&x] = &mut [&mut 0];
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
     //[classic2024]~^^^ ERROR: cannot move out of type
-    let _: &u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: u32 = x;
+    #[cfg(structural2024)] let _: &u32 = x;
 }
 
 pub fn main() {
@@ -35,16 +39,16 @@ pub fn main() {
     // For 2021 edition, this is also a regression test for #136223
     // since the maximum mutability is downgraded during the pattern check process.
     if let &Some(Some(x)) = &Some(&mut Some(0)) {
-        //[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
-        let _: &u32 = x;
+        //[stable2021,classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+        #[cfg(any(structural2021, structural2024))] let _: &u32 = x;
     }
 
     let &[x] = &&mut [0];
-    //[stable2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
-    let _: &u32 = x;
+    //[stable2021,classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+    #[cfg(any(structural2021, structural2024))] let _: &u32 = x;
 
     let [&mut x] = &mut [&mut 0];
     //[classic2024]~^ ERROR: cannot move out of type
-    #[cfg(stable2021)] let _: u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
     #[cfg(structural2024)] let _: &mut u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
index deefe21ca7d45..edcf9f3035707 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/borrowck-errors.rs:13:10
+  --> $DIR/borrowck-errors.rs:15:10
    |
 LL |     let [&x] = &[&mut 0];
    |          ^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -15,7 +15,7 @@ LL +     let [x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/borrowck-errors.rs:19:10
+  --> $DIR/borrowck-errors.rs:22:10
    |
 LL |     let [&x] = &mut [&mut 0];
    |          ^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -31,7 +31,7 @@ LL +     let [x] = &mut [&mut 0];
    |
 
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/borrowck-errors.rs:27:29
+  --> $DIR/borrowck-errors.rs:31:29
    |
 LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
    |                       -     ^^^^^^^^^^^^^^^^^^^
@@ -46,19 +46,19 @@ LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
    |
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:32:10
+  --> $DIR/borrowck-errors.rs:36:10
    |
 LL |     let &ref mut x = &0;
    |          ^^^^^^^^^ cannot borrow as mutable
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:37:23
+  --> $DIR/borrowck-errors.rs:41:23
    |
 LL |     if let &Some(Some(x)) = &Some(&mut Some(0)) {
    |                       ^ cannot borrow as mutable
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:42:11
+  --> $DIR/borrowck-errors.rs:46:11
    |
 LL |     let &[x] = &&mut [0];
    |           ^ cannot borrow as mutable
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr
new file mode 100644
index 0000000000000..208f6c8bbed03
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2021.stderr
@@ -0,0 +1,25 @@
+error[E0507]: cannot move out of a shared reference
+  --> $DIR/borrowck-errors.rs:31:29
+   |
+LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+   |                       -     ^^^^^^^^^^^^^^^^^^^
+   |                       |
+   |                       data moved here
+   |                       move occurs because `x` has type `&mut u32`, which does not implement the `Copy` trait
+   |
+help: consider removing the borrow
+   |
+LL -     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
+LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
+   |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/borrowck-errors.rs:36:10
+   |
+LL |     let &ref mut x = &0;
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 2 previous errors
+
+Some errors have detailed explanations: E0507, E0596.
+For more information about an error, try `rustc --explain E0507`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr
index 30d2f9f3d702f..208f6c8bbed03 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/borrowck-errors.structural2024.stderr
@@ -1,5 +1,5 @@
 error[E0507]: cannot move out of a shared reference
-  --> $DIR/borrowck-errors.rs:27:29
+  --> $DIR/borrowck-errors.rs:31:29
    |
 LL |     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
    |                       -     ^^^^^^^^^^^^^^^^^^^
@@ -14,7 +14,7 @@ LL +     if let Some(Some(x)) = Some(&Some(&mut 0)) {
    |
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/borrowck-errors.rs:32:10
+  --> $DIR/borrowck-errors.rs:36:10
    |
 LL |     let &ref mut x = &0;
    |          ^^^^^^^^^ cannot borrow as mutable
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr
new file mode 100644
index 0000000000000..7e3caaf979748
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2021.stderr
@@ -0,0 +1,103 @@
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/mixed-editions.rs:41:10
+   |
+LL |     let [bind_mut!(y)] = &[0];
+   |          ^^^^^^^^^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: this error originates in the macro `bind_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:76:21
+   |
+LL |     let match_ref!([x]) = &mut &mut [0];
+   |                     ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:80:22
+   |
+LL |     let &match_ctor!(y) = &mut &mut [0];
+   |         -            ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:84:17
+   |
+LL |     let &[bind!(z)] = &mut &mut [0];
+   |         -       ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:110:28
+   |
+LL |     let match_ref!(ref mut x) = &mut 0;
+   |                            ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:112:24
+   |
+LL |     let &bind_ref_mut!(x) = &mut 0;
+   |         -              ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:116:29
+   |
+LL |     let [match_ref!(ref mut x)] = &mut [0];
+   |                             ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:118:25
+   |
+LL |     let [&bind_ref_mut!(x)] = &mut [0];
+   |          -              ^
+   |          |
+   |          help: replace this `&` with `&mut`: `&mut`
+
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/mixed-editions.rs:30:10
+   |
+LL |     let [bind_ref!(y)] = &[0];
+   |          ^^^^^^^^^^^^ occurs within macro expansion
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/mixed-editions.rs:30:9
+   |
+LL |     let [bind_ref!(y)] = &[0];
+   |         ^^^^^^^^^^^^^^ this matches on type `&_`
+   = note: this error originates in the macro `bind_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: make the implied reference pattern explicit
+   |
+LL |     let &[bind_ref!(y)] = &[0];
+   |         +
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:61:21
+   |
+LL |     let match_ref!([x]) = &&mut [0];
+   |                     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:65:22
+   |
+LL |     let &match_ctor!(y) = &&mut [0];
+   |                      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:69:11
+   |
+LL |     let &[bind!(z)] = &&mut [0];
+   |           ^^^^^^^^ cannot borrow as mutable
+   |
+   = note: this error originates in the macro `bind` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0596, E0658.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr
new file mode 100644
index 0000000000000..466993a1671f4
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.classic2024.stderr
@@ -0,0 +1,97 @@
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/mixed-editions.rs:37:21
+   |
+LL |     let match_ctor!(mut x) = &[0];
+   |                     ^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:76:21
+   |
+LL |     let match_ref!([x]) = &mut &mut [0];
+   |                     ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:80:22
+   |
+LL |     let &match_ctor!(y) = &mut &mut [0];
+   |         -            ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:84:17
+   |
+LL |     let &[bind!(z)] = &mut &mut [0];
+   |         -       ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:110:28
+   |
+LL |     let match_ref!(ref mut x) = &mut 0;
+   |                            ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:112:24
+   |
+LL |     let &bind_ref_mut!(x) = &mut 0;
+   |         -              ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:116:29
+   |
+LL |     let [match_ref!(ref mut x)] = &mut [0];
+   |                             ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:118:25
+   |
+LL |     let [&bind_ref_mut!(x)] = &mut [0];
+   |          -              ^
+   |          |
+   |          help: replace this `&` with `&mut`: `&mut`
+
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/mixed-editions.rs:26:21
+   |
+LL |     let match_ctor!(ref x) = &[0];
+   |                     ^^^ binding modifier not allowed under `ref` default binding mode
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+help: make the implied reference pattern explicit
+  --> $DIR/auxiliary/mixed-editions-macros.rs:11:9
+   |
+LL |         &[$p]
+   |         +
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:61:21
+   |
+LL |     let match_ref!([x]) = &&mut [0];
+   |                     ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:65:22
+   |
+LL |     let &match_ctor!(y) = &&mut [0];
+   |                      ^ cannot borrow as mutable
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/mixed-editions.rs:69:11
+   |
+LL |     let &[bind!(z)] = &&mut [0];
+   |           ^^^^^^^^ cannot borrow as mutable
+   |
+   = note: this error originates in the macro `bind` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error: aborting due to 12 previous errors
+
+Some errors have detailed explanations: E0596, E0658.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.rs
new file mode 100644
index 0000000000000..0a22b55ab6374
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.rs
@@ -0,0 +1,122 @@
+//@ revisions: classic2021 structural2021 classic2024 structural2024
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
+//@[classic2024] edition: 2024
+//@[structural2024] edition: 2024
+//@ aux-build:mixed-editions-macros.rs
+//! Tests for typing mixed-edition patterns under the `ref_pat_eat_one_layer_2024` and
+//! `ref_pat_eat_one_layer_2024_structural` feature gates.
+//! This is meant both to check that patterns are typed with edition-appropriate typing rules and
+//! that we keep our internal state consistent when mixing editions.
+#![allow(incomplete_features, unused)]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
+
+extern crate mixed_editions_macros;
+use mixed_editions_macros::*;
+
+// Tests type equality in a way that avoids coercing `&&T` to `&T`.
+trait Eq<T> {}
+impl<T> Eq<T> for T {}
+fn assert_type_eq<T, U: Eq<T>>(_: T, _: U) {}
+
+/// Make sure binding with `ref` in the presence of an inherited reference is forbidden when and
+/// only when the binding is from edition 2024.
+fn ref_binding_tests() {
+    let match_ctor!(ref x) = &[0];
+    //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    #[cfg(any(classic2021, structural2021))] assert_type_eq(x, &0u32);
+
+    let [bind_ref!(y)] = &[0];
+    //[classic2021,structural2021]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    #[cfg(any(classic2024, structural2024))] assert_type_eq(y, &0u32);
+}
+
+/// Likewise, when binding with `mut`.
+fn mut_binding_tests() {
+    let match_ctor!(mut x) = &[0];
+    //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference
+    #[cfg(any(classic2021, structural2021))] assert_type_eq(x, 0u32);
+
+    let [bind_mut!(y)] = &[0];
+    //[classic2021,structural2021]~^ ERROR: binding cannot be both mutable and by-reference
+    #[cfg(any(classic2024, structural2024))] assert_type_eq(y, 0u32);
+}
+
+/// Make sure reference patterns correspond to one deref on edition 2024 and two on edition 2021.
+fn layers_eaten_tests() {
+    let match_ctor!(&x) = &[&0];
+    #[cfg(any(classic2021, structural2021))] assert_type_eq(x, 0u32);
+    #[cfg(any(classic2024, structural2024))] assert_type_eq(x, &0u32);
+
+    let [match_ref!(y)] = &[&0];
+    #[cfg(any(classic2021, structural2021))] assert_type_eq(y, &0u32);
+    #[cfg(any(classic2024, structural2024))] assert_type_eq(y, 0u32);
+}
+
+/// Make sure downgrading mutable binding modes inside shared refs ("Rule 3") doesn't break.
+/// This only applies to `ref_pat_eat_one_layer_2024_structural`, which has Rule 3 in all editions;
+/// under `ref_pat_eat_one_layer_2024`, these should be errors.
+fn rule_3_tests() {
+    let match_ref!([x]) = &&mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(x, &0u32);
+
+    let &match_ctor!(y) = &&mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(y, &0u32);
+
+    let &[bind!(z)] = &&mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow data in a `&` reference as mutable
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(z, &0u32);
+}
+
+/// Test that the interaction between Rules 3 and 5 doesn't break.
+fn rules_3_and_5_tests() {
+    let match_ref!([x]) = &mut &mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(x, &0u32);
+
+    let &match_ctor!(y) = &mut &mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(y, &0u32);
+
+    let &[bind!(z)] = &mut &mut [0];
+    //[classic2021,classic2024]~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    #[cfg(any(structural2021, structural2024))] assert_type_eq(z, &0u32);
+}
+
+/// Make sure matching a lone shared reference with a `&` ("Rule 4") doesn't break.
+fn rule_4_tests() {
+    let match_ref!([x]) = &[0];
+    assert_type_eq(x, 0u32);
+
+    let &match_ctor!(y) = &[0];
+    assert_type_eq(y, 0u32);
+}
+
+/// Make sure matching a `&mut` reference with a `&` pattern ("Rule 5") doesn't break.
+fn rule_5_tests() {
+    let match_ref!(x) = &mut 0;
+    assert_type_eq(x, 0u32);
+
+    // also test inherited references (assumes rule 4)
+    let [match_ref!(y)] = &mut [0];
+    assert_type_eq(y, 0u32);
+}
+
+/// Make sure binding with `ref mut` is an error within a `&` pattern matching a `&mut` reference.
+fn rule_5_mutability_error_tests() {
+    let match_ref!(ref mut x) = &mut 0;
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    let &bind_ref_mut!(x) = &mut 0;
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+
+    // also test inherited references (assumes rule 4)
+    let [match_ref!(ref mut x)] = &mut [0];
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+    let [&bind_ref_mut!(x)] = &mut [0];
+    //~^ ERROR: cannot borrow as mutable inside an `&` pattern
+}
+
+fn main() {}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr
new file mode 100644
index 0000000000000..4075dc9529da1
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2021.stderr
@@ -0,0 +1,61 @@
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/mixed-editions.rs:41:10
+   |
+LL |     let [bind_mut!(y)] = &[0];
+   |          ^^^^^^^^^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+   = note: this error originates in the macro `bind_mut` (in Nightly builds, run with -Z macro-backtrace for more info)
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:110:28
+   |
+LL |     let match_ref!(ref mut x) = &mut 0;
+   |                            ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:112:24
+   |
+LL |     let &bind_ref_mut!(x) = &mut 0;
+   |         -              ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:116:29
+   |
+LL |     let [match_ref!(ref mut x)] = &mut [0];
+   |                             ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:118:25
+   |
+LL |     let [&bind_ref_mut!(x)] = &mut [0];
+   |          -              ^
+   |          |
+   |          help: replace this `&` with `&mut`: `&mut`
+
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/mixed-editions.rs:30:10
+   |
+LL |     let [bind_ref!(y)] = &[0];
+   |          ^^^^^^^^^^^^ occurs within macro expansion
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/mixed-editions.rs:30:9
+   |
+LL |     let [bind_ref!(y)] = &[0];
+   |         ^^^^^^^^^^^^^^ this matches on type `&_`
+   = note: this error originates in the macro `bind_ref` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: make the implied reference pattern explicit
+   |
+LL |     let &[bind_ref!(y)] = &[0];
+   |         +
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0596, E0658.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr
new file mode 100644
index 0000000000000..819a54299ea1c
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mixed-editions.structural2024.stderr
@@ -0,0 +1,55 @@
+error[E0658]: binding cannot be both mutable and by-reference
+  --> $DIR/mixed-editions.rs:37:21
+   |
+LL |     let match_ctor!(mut x) = &[0];
+   |                     ^^^^
+   |
+   = note: see issue #123076 <https://github.com/rust-lang/rust/issues/123076> for more information
+   = help: add `#![feature(mut_ref)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:110:28
+   |
+LL |     let match_ref!(ref mut x) = &mut 0;
+   |                            ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:112:24
+   |
+LL |     let &bind_ref_mut!(x) = &mut 0;
+   |         -              ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:116:29
+   |
+LL |     let [match_ref!(ref mut x)] = &mut [0];
+   |                             ^
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/mixed-editions.rs:118:25
+   |
+LL |     let [&bind_ref_mut!(x)] = &mut [0];
+   |          -              ^
+   |          |
+   |          help: replace this `&` with `&mut`: `&mut`
+
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/mixed-editions.rs:26:21
+   |
+LL |     let match_ctor!(ref x) = &[0];
+   |                     ^^^ binding modifier not allowed under `ref` default binding mode
+   |
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
+help: make the implied reference pattern explicit
+  --> $DIR/auxiliary/mixed-editions-macros.rs:11:9
+   |
+LL |         &[$p]
+   |         +
+
+error: aborting due to 6 previous errors
+
+Some errors have detailed explanations: E0596, E0658.
+For more information about an error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr
index fa95b2b5a575d..6ddced3d16812 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.classic2024.stderr
@@ -1,5 +1,5 @@
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:14:13
+  --> $DIR/mut-ref-mut.rs:18:13
    |
 LL |     let Foo(mut a) = &Foo(0);
    |             ^^^^
@@ -9,7 +9,7 @@ LL |     let Foo(mut a) = &Foo(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:19:13
+  --> $DIR/mut-ref-mut.rs:23:13
    |
 LL |     let Foo(mut a) = &mut Foo(0);
    |             ^^^^
@@ -19,7 +19,7 @@ LL |     let Foo(mut a) = &mut Foo(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0308]: mismatched types
-  --> $DIR/mut-ref-mut.rs:24:10
+  --> $DIR/mut-ref-mut.rs:28:10
    |
 LL |     let [&mut mut x] = &[&mut 0];
    |          ^^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs
index fbd6514df73d6..c8e988ad76d97 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.rs
@@ -1,29 +1,33 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[stable2021] run-pass
+//@[classic2021] run-pass
+//@[structural2021] run-pass
 //! Test diagnostics for binding with `mut` when the default binding mode is by-ref.
 #![allow(incomplete_features, unused_assignments, unused_variables)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     struct Foo(u8);
 
     let Foo(mut a) = &Foo(0);
     //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] { a = 42 }
+    #[cfg(any(stable2021, classic2021, structural2021))] { a = 42 }
     #[cfg(any(classic2024, structural2024))] { a = &42 }
 
     let Foo(mut a) = &mut Foo(0);
     //[classic2024,structural2024]~^ ERROR: binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] { a = 42 }
+    #[cfg(any(stable2021, classic2021, structural2021))] { a = 42 }
     #[cfg(any(classic2024, structural2024))] { a = &mut 42 }
 
     let [&mut mut x] = &[&mut 0];
     //[classic2024]~^ ERROR: mismatched types
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
     //[structural2024]~^^^ binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] { x = 0 }
+    #[cfg(any(stable2021, classic2021, structural2021))] { x = 0 }
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr
index fd82da70a18de..c0c0f966b6804 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/mut-ref-mut.structural2024.stderr
@@ -1,5 +1,5 @@
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:14:13
+  --> $DIR/mut-ref-mut.rs:18:13
    |
 LL |     let Foo(mut a) = &Foo(0);
    |             ^^^^
@@ -9,7 +9,7 @@ LL |     let Foo(mut a) = &Foo(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:19:13
+  --> $DIR/mut-ref-mut.rs:23:13
    |
 LL |     let Foo(mut a) = &mut Foo(0);
    |             ^^^^
@@ -19,7 +19,7 @@ LL |     let Foo(mut a) = &mut Foo(0);
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/mut-ref-mut.rs:24:15
+  --> $DIR/mut-ref-mut.rs:28:15
    |
 LL |     let [&mut mut x] = &[&mut 0];
    |               ^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2021.stderr
new file mode 100644
index 0000000000000..a856a0eaf2a7c
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2021.stderr
@@ -0,0 +1,219 @@
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:20:27
+   |
+LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+   |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                           |
+   |                           expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:33:17
+   |
+LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
+   |                 ^^^^^^^^^^^^^    --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                 |
+   |                 types differ in mutability
+   |
+   = note:      expected reference `&Option<{integer}>`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:38:23
+   |
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/pattern-errors.rs:38:23
+   |
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL -     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:45:23
+   |
+LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:56:17
+   |
+LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     if let Some(&mut Some(x)) = &Some(Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:114:11
+   |
+LL |     let [&&mut x] = &[&mut 0];
+   |           ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &[&mut 0];
+LL +     let [&x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:121:11
+   |
+LL |     let [&&mut x] = &mut [&mut 0];
+   |           ^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &mut [&mut 0];
+LL +     let [&x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:128:11
+   |
+LL |     let [&&mut ref x] = &[&mut 0];
+   |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &[&mut 0];
+LL +     let [&ref x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:135:11
+   |
+LL |     let [&&mut ref x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &mut [&mut 0];
+LL +     let [&ref x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:142:11
+   |
+LL |     let [&&mut mut x] = &[&mut 0];
+   |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &[&mut 0];
+LL +     let [&mut x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:149:11
+   |
+LL |     let [&&mut mut x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &mut [&mut 0];
+LL +     let [&mut x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:164:15
+   |
+LL |     let [&mut &x] = &[&mut 0];
+   |               ^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &x] = &[&mut 0];
+LL +     let [&mut x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:170:15
+   |
+LL |     let [&mut &ref x] = &[&mut 0];
+   |               ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &ref x] = &[&mut 0];
+LL +     let [&mut ref x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:176:15
+   |
+LL |     let [&mut &(mut x)] = &[&mut 0];
+   |               ^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &(mut x)] = &[&mut 0];
+LL +     let [&mut mut x)] = &[&mut 0];
+   |
+
+error: aborting due to 14 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr
index 6726a72631533..90510d23e6614 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.classic2024.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:12:17
+  --> $DIR/pattern-errors.rs:14:17
    |
 LL |     if let Some(&mut x) = &Some(&mut 0) {
    |                 ^^^^^
@@ -12,7 +12,7 @@ LL +     if let Some(&x) = &Some(&mut 0) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:18:17
+  --> $DIR/pattern-errors.rs:20:17
    |
 LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
    |                 ^^^^^
@@ -25,7 +25,7 @@ LL +     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:24:22
+  --> $DIR/pattern-errors.rs:26:22
    |
 LL |     if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
    |                      ^^^^^
@@ -38,7 +38,7 @@ LL +     if let Some(Some(&x)) = &Some(Some(&mut 0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:31:17
+  --> $DIR/pattern-errors.rs:33:17
    |
 LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
    |                 ^^^^^
@@ -51,7 +51,7 @@ LL +     if let Some(&Some(&_)) = &Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:41:23
+  --> $DIR/pattern-errors.rs:45:23
    |
 LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
    |                       ^^^^^
@@ -64,7 +64,7 @@ LL +     if let Some(&Some(&_)) = &mut Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:51:17
+  --> $DIR/pattern-errors.rs:56:17
    |
 LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
    |                 ^^^^^
@@ -77,7 +77,7 @@ LL +     if let Some(&Some(x)) = &Some(Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:147:10
+  --> $DIR/pattern-errors.rs:158:10
    |
 LL |     let [&mut x] = &[&mut 0];
    |          ^^^^^
@@ -90,7 +90,7 @@ LL +     let [&x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:153:10
+  --> $DIR/pattern-errors.rs:164:10
    |
 LL |     let [&mut &x] = &[&mut 0];
    |          ^^^^^
@@ -103,7 +103,7 @@ LL +     let [&&x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:159:10
+  --> $DIR/pattern-errors.rs:170:10
    |
 LL |     let [&mut &ref x] = &[&mut 0];
    |          ^^^^^
@@ -116,7 +116,7 @@ LL +     let [&&ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:165:10
+  --> $DIR/pattern-errors.rs:176:10
    |
 LL |     let [&mut &(mut x)] = &[&mut 0];
    |          ^^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
index c07c2972cd055..5e677445644a6 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.rs
@@ -1,170 +1,181 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //! Test cases for poorly-typed patterns in edition 2024 which are caught by HIR typeck. These must
 //! be separate from cases caught by MIR borrowck or the latter errors may not be emitted.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     if let Some(&mut x) = &Some(&mut 0) {
         //[classic2024]~^ ERROR: mismatched types
         //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-        #[cfg(stable2021)] let _: u32 = x;
+        #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
         #[cfg(structural2024)] let _: &u32 = x;
     }
     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-        //[stable2021,classic2024]~^ ERROR: mismatched types
-        //[stable2021]~| expected integer, found `&_`
+        //[stable2021,classic2021,structural2021,classic2024]~^ ERROR: mismatched types
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&_`
         //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-        let _: u32 = x;
+        #[cfg(structural2024)] let _: u32 = x;
     }
     if let Some(Some(&mut x)) = &Some(Some(&mut 0)) {
         //[classic2024]~^ ERROR: mismatched types
         //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-        #[cfg(stable2021)] let _: u32 = x;
+        #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
         #[cfg(structural2024)] let _: &u32 = x;
     }
 
     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
         //~^ ERROR: mismatched types
-        //[stable2021]~| types differ in mutability
+        //[stable2021,classic2021,structural2021]~| types differ in mutability
         //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern
     }
-    if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
-        //[stable2021,structural2024]~^ ERROR: mismatched types
+    if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+        //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
         //[stable2021]~| types differ in mutability
+        //[classic2021,structural2021]~| expected integer, found `&mut _`
         //[structural2024]~| cannot match inherited `&` with `&mut` pattern
+        #[cfg(classic2024)] let _: u32 = x;
     }
     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
         //~^ ERROR: mismatched types
-        //[stable2021]~| expected integer, found `&mut _`
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&mut _`
         //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern
     }
-    if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
-        //[stable2021,structural2024]~^ ERROR: mismatched types
+    if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
+        //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
         //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_`
-        //[structural2024]~| cannot match inherited `&` with `&mut` pattern
+        //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+        #[cfg(any(classic2021, classic2024))] let _: u32 = x;
     }
     if let Some(&mut Some(x)) = &Some(Some(0)) {
         //~^ ERROR: mismatched types
         //[stable2021]~| expected `Option<{integer}>`, found `&mut _`
-        //[classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~| cannot match inherited `&` with `&mut` pattern
     }
 }
 
 fn structural_errors_0() {
     let &[&mut x] = &&mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&mut _`
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: u32 = x;
 
     let &[&mut x] = &mut &mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: u32 = x;
 
     let &[&mut ref x] = &&mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&mut _`
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: &u32 = x;
 
     let &[&mut ref x] = &mut &mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: &u32 = x;
 
     let &[&mut mut x] = &&mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&mut _`
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: u32 = x;
 
     let &[&mut mut x] = &mut &mut [0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
-    //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    //[structural2021,structural2024]~| cannot match inherited `&` with `&mut` pattern
+    #[cfg(any(classic2021, classic2024))] let _: u32 = x;
 }
 
 fn structural_errors_1() {
     let [&(mut x)] = &[&0];
     //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] let _: u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
     #[cfg(classic2024)] let _: &u32 = x;
 
     let [&(mut x)] = &mut [&0];
     //[structural2024]~^ ERROR: binding cannot be both mutable and by-reference
-    #[cfg(stable2021)] let _: u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
     #[cfg(classic2024)] let _: &u32 = x;
 }
 
 fn structural_errors_2() {
     let [&&mut x] = &[&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(classic2024)] let _: u32 = x;
 
     let [&&mut x] = &mut [&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(classic2024)] let _: u32 = x;
 
     let [&&mut ref x] = &[&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    #[cfg(classic2024)] let _: &u32 = x;
 
     let [&&mut ref x] = &mut [&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    #[cfg(classic2024)] let _: &u32 = x;
 
     let [&&mut mut x] = &[&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(classic2024)] let _: u32 = x;
 
     let [&&mut mut x] = &mut [&mut 0];
-    //[stable2021,structural2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,structural2024]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
+    //[classic2021,structural2021] expected integer, found `&mut _`
     //[structural2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(classic2024)] let _: u32 = x;
 }
 
 fn classic_errors_0() {
     let [&mut x] = &[&mut 0];
     //[classic2024]~^ ERROR: mismatched types
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    #[cfg(stable2021)] let _: u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
     #[cfg(structural2024)] let _: &u32 = x;
 
     let [&mut &x] = &[&mut 0];
-    //[stable2021,classic2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,classic2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&_`
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(structural2024)] let _: u32 = x;
 
     let [&mut &ref x] = &[&mut 0];
-    //[stable2021,classic2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,classic2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&_`
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: &u32 = x;
+    #[cfg(structural2024)] let _: &u32 = x;
 
     let [&mut &(mut x)] = &[&mut 0];
-    //[stable2021,classic2024]~^ ERROR: mismatched types
+    //[stable2021,classic2021,structural2021,classic2024]~^ ERROR: mismatched types
     //[stable2021]~| expected integer, found `&_`
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    let _: u32 = x;
+    #[cfg(structural2024)] let _: u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr
index ad19b122c20d7..76e6d2f562a27 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:18:27
+  --> $DIR/pattern-errors.rs:20:27
    |
 LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
    |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
@@ -15,7 +15,7 @@ LL +     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:31:17
+  --> $DIR/pattern-errors.rs:33:17
    |
 LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
    |                 ^^^^^^^^^^^^^    --------------- this expression has type `&Option<&Option<{integer}>>`
@@ -26,9 +26,9 @@ LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:36:17
+  --> $DIR/pattern-errors.rs:38:17
    |
-LL |     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
    |                 ^^^^^^^^^^^^^    ------------------- this expression has type `&Option<&mut Option<{integer}>>`
    |                 |
    |                 types differ in mutability
@@ -37,7 +37,7 @@ LL |     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:41:23
+  --> $DIR/pattern-errors.rs:45:23
    |
 LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
    |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
@@ -48,9 +48,9 @@ LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:46:17
+  --> $DIR/pattern-errors.rs:50:17
    |
-LL |     if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
+LL |     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
    |                 ^^^^^^^^^^^^^^^^^^^    ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
    |                 |
    |                 expected `Option<&mut Option<{integer}>>`, found `&_`
@@ -59,7 +59,7 @@ LL |     if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:51:17
+  --> $DIR/pattern-errors.rs:56:17
    |
 LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
    |                 ^^^^^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
@@ -70,7 +70,7 @@ LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:59:11
+  --> $DIR/pattern-errors.rs:64:11
    |
 LL |     let &[&mut x] = &&mut [0];
    |           ^^^^^^    --------- this expression has type `&&mut [{integer}; 1]`
@@ -80,7 +80,7 @@ LL |     let &[&mut x] = &&mut [0];
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/pattern-errors.rs:59:11
+  --> $DIR/pattern-errors.rs:64:11
    |
 LL |     let &[&mut x] = &&mut [0];
    |           ^^^^^^
@@ -91,7 +91,7 @@ LL +     let &[x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:65:9
+  --> $DIR/pattern-errors.rs:70:9
    |
 LL |     let &[&mut x] = &mut &mut [0];
    |         ^^^^^^^^^   ------------- this expression has type `&mut &mut [{integer}; 1]`
@@ -102,7 +102,7 @@ LL |     let &[&mut x] = &mut &mut [0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:71:11
+  --> $DIR/pattern-errors.rs:76:11
    |
 LL |     let &[&mut ref x] = &&mut [0];
    |           ^^^^^^^^^^    --------- this expression has type `&&mut [{integer}; 1]`
@@ -112,7 +112,7 @@ LL |     let &[&mut ref x] = &&mut [0];
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/pattern-errors.rs:71:11
+  --> $DIR/pattern-errors.rs:76:11
    |
 LL |     let &[&mut ref x] = &&mut [0];
    |           ^^^^^^^^^^
@@ -123,7 +123,7 @@ LL +     let &[ref x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:77:9
+  --> $DIR/pattern-errors.rs:82:9
    |
 LL |     let &[&mut ref x] = &mut &mut [0];
    |         ^^^^^^^^^^^^^   ------------- this expression has type `&mut &mut [{integer}; 1]`
@@ -134,7 +134,7 @@ LL |     let &[&mut ref x] = &mut &mut [0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:83:11
+  --> $DIR/pattern-errors.rs:88:11
    |
 LL |     let &[&mut mut x] = &&mut [0];
    |           ^^^^^^^^^^    --------- this expression has type `&&mut [{integer}; 1]`
@@ -144,7 +144,7 @@ LL |     let &[&mut mut x] = &&mut [0];
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/pattern-errors.rs:83:11
+  --> $DIR/pattern-errors.rs:88:11
    |
 LL |     let &[&mut mut x] = &&mut [0];
    |           ^^^^^^^^^^
@@ -155,7 +155,7 @@ LL +     let &[mut x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:89:9
+  --> $DIR/pattern-errors.rs:94:9
    |
 LL |     let &[&mut mut x] = &mut &mut [0];
    |         ^^^^^^^^^^^^^   ------------- this expression has type `&mut &mut [{integer}; 1]`
@@ -166,7 +166,7 @@ LL |     let &[&mut mut x] = &mut &mut [0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:109:10
+  --> $DIR/pattern-errors.rs:114:10
    |
 LL |     let [&&mut x] = &[&mut 0];
    |          ^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -177,7 +177,7 @@ LL |     let [&&mut x] = &[&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:115:10
+  --> $DIR/pattern-errors.rs:121:10
    |
 LL |     let [&&mut x] = &mut [&mut 0];
    |          ^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -188,7 +188,7 @@ LL |     let [&&mut x] = &mut [&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:121:10
+  --> $DIR/pattern-errors.rs:128:10
    |
 LL |     let [&&mut ref x] = &[&mut 0];
    |          ^^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -199,7 +199,7 @@ LL |     let [&&mut ref x] = &[&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:127:10
+  --> $DIR/pattern-errors.rs:135:10
    |
 LL |     let [&&mut ref x] = &mut [&mut 0];
    |          ^^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -210,7 +210,7 @@ LL |     let [&&mut ref x] = &mut [&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:133:10
+  --> $DIR/pattern-errors.rs:142:10
    |
 LL |     let [&&mut mut x] = &[&mut 0];
    |          ^^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -221,7 +221,7 @@ LL |     let [&&mut mut x] = &[&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:139:10
+  --> $DIR/pattern-errors.rs:149:10
    |
 LL |     let [&&mut mut x] = &mut [&mut 0];
    |          ^^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -232,7 +232,7 @@ LL |     let [&&mut mut x] = &mut [&mut 0];
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:153:15
+  --> $DIR/pattern-errors.rs:164:15
    |
 LL |     let [&mut &x] = &[&mut 0];
    |               ^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -248,7 +248,7 @@ LL +     let [&mut x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:159:15
+  --> $DIR/pattern-errors.rs:170:15
    |
 LL |     let [&mut &ref x] = &[&mut 0];
    |               ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -264,7 +264,7 @@ LL +     let [&mut ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:165:15
+  --> $DIR/pattern-errors.rs:176:15
    |
 LL |     let [&mut &(mut x)] = &[&mut 0];
    |               ^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2021.stderr
new file mode 100644
index 0000000000000..1ca6bff3f38c3
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2021.stderr
@@ -0,0 +1,310 @@
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:20:27
+   |
+LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+   |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                           |
+   |                           expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:33:17
+   |
+LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
+   |                 ^^^^^^^^^^^^^    --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                 |
+   |                 types differ in mutability
+   |
+   = note:      expected reference `&Option<{integer}>`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:38:23
+   |
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/pattern-errors.rs:38:23
+   |
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+   |                       ^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL -     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:45:23
+   |
+LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
+   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:50:28
+   |
+LL |     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
+   |                            ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
+LL +     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:56:17
+   |
+LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
+   |                 ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     if let Some(&mut Some(x)) = &Some(Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:64:11
+   |
+LL |     let &[&mut x] = &&mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut x] = &&mut [0];
+LL +     let &[&x] = &&mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:70:11
+   |
+LL |     let &[&mut x] = &mut &mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut x] = &mut &mut [0];
+LL +     let &[&x] = &mut &mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:76:11
+   |
+LL |     let &[&mut ref x] = &&mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut ref x] = &&mut [0];
+LL +     let &[&ref x] = &&mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:82:11
+   |
+LL |     let &[&mut ref x] = &mut &mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut ref x] = &mut &mut [0];
+LL +     let &[&ref x] = &mut &mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:88:11
+   |
+LL |     let &[&mut mut x] = &&mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut mut x] = &&mut [0];
+LL +     let &[&mut x] = &&mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:94:11
+   |
+LL |     let &[&mut mut x] = &mut &mut [0];
+   |           ^^^^^
+   |
+   = note: cannot match inherited `&` with `&mut` pattern
+help: replace this `&mut` pattern with `&`
+   |
+LL -     let &[&mut mut x] = &mut &mut [0];
+LL +     let &[&mut x] = &mut &mut [0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:114:11
+   |
+LL |     let [&&mut x] = &[&mut 0];
+   |           ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &[&mut 0];
+LL +     let [&x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:121:11
+   |
+LL |     let [&&mut x] = &mut [&mut 0];
+   |           ^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut x] = &mut [&mut 0];
+LL +     let [&x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:128:11
+   |
+LL |     let [&&mut ref x] = &[&mut 0];
+   |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &[&mut 0];
+LL +     let [&ref x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:135:11
+   |
+LL |     let [&&mut ref x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut ref x] = &mut [&mut 0];
+LL +     let [&ref x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:142:11
+   |
+LL |     let [&&mut mut x] = &[&mut 0];
+   |           ^^^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &[&mut 0];
+LL +     let [&mut x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:149:11
+   |
+LL |     let [&&mut mut x] = &mut [&mut 0];
+   |           ^^^^^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
+   |           |
+   |           expected integer, found `&mut _`
+   |
+   = note:           expected type `{integer}`
+           found mutable reference `&mut _`
+help: consider removing `&mut` from the pattern
+   |
+LL -     let [&&mut mut x] = &mut [&mut 0];
+LL +     let [&mut x] = &mut [&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:164:15
+   |
+LL |     let [&mut &x] = &[&mut 0];
+   |               ^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &x] = &[&mut 0];
+LL +     let [&mut x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:170:15
+   |
+LL |     let [&mut &ref x] = &[&mut 0];
+   |               ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &ref x] = &[&mut 0];
+LL +     let [&mut ref x] = &[&mut 0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/pattern-errors.rs:176:15
+   |
+LL |     let [&mut &(mut x)] = &[&mut 0];
+   |               ^^^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &(mut x)] = &[&mut 0];
+LL +     let [&mut mut x)] = &[&mut 0];
+   |
+
+error: aborting due to 21 previous errors
+
+For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr
index fdf48a5a71b5f..3658893df9cc1 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/pattern-errors.structural2024.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:31:17
+  --> $DIR/pattern-errors.rs:33:17
    |
 LL |     if let Some(&mut Some(&_)) = &Some(&Some(0)) {
    |                 ^^^^^
@@ -12,20 +12,20 @@ LL +     if let Some(&Some(&_)) = &Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:36:23
+  --> $DIR/pattern-errors.rs:38:23
    |
-LL |     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
+LL |     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
    |                       ^^^^^
    |
    = note: cannot match inherited `&` with `&mut` pattern
 help: replace this `&mut` pattern with `&`
    |
-LL -     if let Some(&Some(&mut _)) = &Some(&mut Some(0)) {
-LL +     if let Some(&Some(&_)) = &Some(&mut Some(0)) {
+LL -     if let Some(&Some(&mut x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:41:23
+  --> $DIR/pattern-errors.rs:45:23
    |
 LL |     if let Some(&Some(&mut _)) = &mut Some(&Some(0)) {
    |                       ^^^^^
@@ -38,20 +38,20 @@ LL +     if let Some(&Some(&_)) = &mut Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:46:28
+  --> $DIR/pattern-errors.rs:50:28
    |
-LL |     if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
+LL |     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
    |                            ^^^^^
    |
    = note: cannot match inherited `&` with `&mut` pattern
 help: replace this `&mut` pattern with `&`
    |
-LL -     if let Some(&Some(Some(&mut _))) = &Some(Some(&mut Some(0))) {
-LL +     if let Some(&Some(Some(&_))) = &Some(Some(&mut Some(0))) {
+LL -     if let Some(&Some(Some(&mut x))) = &Some(Some(&mut Some(0))) {
+LL +     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:51:17
+  --> $DIR/pattern-errors.rs:56:17
    |
 LL |     if let Some(&mut Some(x)) = &Some(Some(0)) {
    |                 ^^^^^
@@ -64,7 +64,7 @@ LL +     if let Some(&Some(x)) = &Some(Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:59:11
+  --> $DIR/pattern-errors.rs:64:11
    |
 LL |     let &[&mut x] = &&mut [0];
    |           ^^^^^
@@ -77,7 +77,7 @@ LL +     let &[&x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:65:11
+  --> $DIR/pattern-errors.rs:70:11
    |
 LL |     let &[&mut x] = &mut &mut [0];
    |           ^^^^^
@@ -90,7 +90,7 @@ LL +     let &[&x] = &mut &mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:71:11
+  --> $DIR/pattern-errors.rs:76:11
    |
 LL |     let &[&mut ref x] = &&mut [0];
    |           ^^^^^
@@ -103,7 +103,7 @@ LL +     let &[&ref x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:77:11
+  --> $DIR/pattern-errors.rs:82:11
    |
 LL |     let &[&mut ref x] = &mut &mut [0];
    |           ^^^^^
@@ -116,7 +116,7 @@ LL +     let &[&ref x] = &mut &mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:83:11
+  --> $DIR/pattern-errors.rs:88:11
    |
 LL |     let &[&mut mut x] = &&mut [0];
    |           ^^^^^
@@ -129,7 +129,7 @@ LL +     let &[&mut x] = &&mut [0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:89:11
+  --> $DIR/pattern-errors.rs:94:11
    |
 LL |     let &[&mut mut x] = &mut &mut [0];
    |           ^^^^^
@@ -142,7 +142,7 @@ LL +     let &[&mut x] = &mut &mut [0];
    |
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/pattern-errors.rs:97:12
+  --> $DIR/pattern-errors.rs:102:12
    |
 LL |     let [&(mut x)] = &[&0];
    |            ^^^^
@@ -152,7 +152,7 @@ LL |     let [&(mut x)] = &[&0];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0658]: binding cannot be both mutable and by-reference
-  --> $DIR/pattern-errors.rs:102:12
+  --> $DIR/pattern-errors.rs:107:12
    |
 LL |     let [&(mut x)] = &mut [&0];
    |            ^^^^
@@ -162,7 +162,7 @@ LL |     let [&(mut x)] = &mut [&0];
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:109:11
+  --> $DIR/pattern-errors.rs:114:11
    |
 LL |     let [&&mut x] = &[&mut 0];
    |           ^^^^^
@@ -175,7 +175,7 @@ LL +     let [&&x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:115:11
+  --> $DIR/pattern-errors.rs:121:11
    |
 LL |     let [&&mut x] = &mut [&mut 0];
    |           ^^^^^
@@ -188,7 +188,7 @@ LL +     let [&&x] = &mut [&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:121:11
+  --> $DIR/pattern-errors.rs:128:11
    |
 LL |     let [&&mut ref x] = &[&mut 0];
    |           ^^^^^
@@ -201,7 +201,7 @@ LL +     let [&&ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:127:11
+  --> $DIR/pattern-errors.rs:135:11
    |
 LL |     let [&&mut ref x] = &mut [&mut 0];
    |           ^^^^^
@@ -214,7 +214,7 @@ LL +     let [&&ref x] = &mut [&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:133:11
+  --> $DIR/pattern-errors.rs:142:11
    |
 LL |     let [&&mut mut x] = &[&mut 0];
    |           ^^^^^
@@ -227,7 +227,7 @@ LL +     let [&&mut x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/pattern-errors.rs:139:11
+  --> $DIR/pattern-errors.rs:149:11
    |
 LL |     let [&&mut mut x] = &mut [&mut 0];
    |           ^^^^^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2021.stderr
new file mode 100644
index 0000000000000..1dda2dca4a48a
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2021.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
+   |
+LL |     let [ref mut x] = &[0];
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr
index 56125be2d6fc8..44cb005a748da 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:54:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:58:10
    |
 LL |     let [&mut ref x] = &[&mut 0];
    |          ^^^^^
@@ -12,14 +12,14 @@ LL +     let [&ref x] = &[&mut 0];
    |
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:9
    |
 LL |     let [ref mut x] = &[0];
    |         ^^^^^^^^^^^ this matches on type `&_`
@@ -29,20 +29,20 @@ LL |     let &[ref mut x] = &[0];
    |         +
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^^^ cannot borrow as mutable
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
    |
 LL |     let [ref x] = &[0];
    |          ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
    |
 LL |     let [ref x] = &[0];
    |         ^^^^^^^ this matches on type `&_`
@@ -52,14 +52,14 @@ LL |     let &[ref x] = &[0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
    |
 LL |     let [ref x] = &mut [0];
    |          ^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
    |
 LL |     let [ref x] = &mut [0];
    |         ^^^^^^^ this matches on type `&mut _`
@@ -69,14 +69,14 @@ LL |     let &mut [ref x] = &mut [0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:87:10
    |
 LL |     let [ref mut x] = &mut [0];
    |          ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:87:9
    |
 LL |     let [ref mut x] = &mut [0];
    |         ^^^^^^^^^^^ this matches on type `&mut _`
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs
index 4e048570c33c2..ea6f028fe4b8b 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs
@@ -1,35 +1,37 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //! Tests for errors from binding with `ref x` under a by-ref default binding mode in edition 2024.
 //! These can't be in the same body as tests for other errors, since they're emitted during THIR
 //! construction. The errors on stable edition 2021 Rust are unrelated.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 /// These only fail on the eat-inner variant of the new edition 2024 pattern typing rules.
 /// The eat-outer variant eats the inherited reference, so binding with `ref` isn't a problem.
 fn errors_from_eating_the_real_reference() {
     let [&ref x] = &[&0];
     //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&u32 = x;
 
     let [&ref x] = &mut [&0];
     //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&u32 = x;
 
     let [&mut ref x] = &mut [&mut 0];
     //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&mut u32 = x;
 
     let [&mut ref mut x] = &mut [&mut 0];
     //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &mut u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &mut u32 = x;
     #[cfg(classic2024)] let _: &mut &mut u32 = x;
 }
 
@@ -40,12 +42,14 @@ fn errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable() {
     //[stable2021]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
     //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    #[cfg(any(classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&mut u32 = x;
 
     let [&ref x] = &mut [&mut 0];
     //[stable2021]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
     //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
+    #[cfg(any(classic2021, structural2021))] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&mut u32 = x;
 }
 
@@ -55,7 +59,7 @@ fn errors_dependent_on_eating_order_caught_in_hir_typeck_when_eating_outer() {
     //[classic2024]~^ ERROR: mismatched types
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
     //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
 }
 
 /// These should be errors in all editions. In edition 2024, they should be caught by the pattern
@@ -74,13 +78,13 @@ fn borrowck_errors_in_old_editions() {
 pub fn main() {
     let [ref x] = &[0];
     //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
 
     let [ref x] = &mut [0];
     //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &u32 = x;
 
     let [ref mut x] = &mut [0];
     //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
-    #[cfg(stable2021)] let _: &mut u32 = x;
+    #[cfg(any(stable2021, classic2021, structural2021))] let _: &mut u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr
index 26095d8460572..2ec6650dd7d0b 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:39:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:41:10
    |
 LL |     let [&ref x] = &[&mut 0];
    |          ^^^^^^    --------- this expression has type `&[&mut {integer}; 1]`
@@ -15,7 +15,7 @@ LL +     let [ref x] = &[&mut 0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:45:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:48:10
    |
 LL |     let [&ref x] = &mut [&mut 0];
    |          ^^^^^^    ------------- this expression has type `&mut [&mut {integer}; 1]`
@@ -31,7 +31,7 @@ LL +     let [ref x] = &mut [&mut 0];
    |
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^^^ cannot borrow as mutable
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2021.stderr
new file mode 100644
index 0000000000000..1dda2dca4a48a
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2021.stderr
@@ -0,0 +1,9 @@
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
+   |
+LL |     let [ref mut x] = &[0];
+   |          ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr
index 31930e8c03371..6f62ad06cc493 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr
@@ -1,12 +1,12 @@
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:17:11
    |
 LL |     let [&ref x] = &[&0];
    |           ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:15:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:17:9
    |
 LL |     let [&ref x] = &[&0];
    |         ^^^^^^^^ this matches on type `&_`
@@ -16,14 +16,14 @@ LL |     let &[&ref x] = &[&0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:20:11
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:22:11
    |
 LL |     let [&ref x] = &mut [&0];
    |           ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:20:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:22:9
    |
 LL |     let [&ref x] = &mut [&0];
    |         ^^^^^^^^ this matches on type `&mut _`
@@ -33,14 +33,14 @@ LL |     let &mut [&ref x] = &mut [&0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:25:15
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:27:15
    |
 LL |     let [&mut ref x] = &mut [&mut 0];
    |               ^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:25:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:27:9
    |
 LL |     let [&mut ref x] = &mut [&mut 0];
    |         ^^^^^^^^^^^^ this matches on type `&mut _`
@@ -50,14 +50,14 @@ LL |     let &mut [&mut ref x] = &mut [&mut 0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:30:15
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:32:15
    |
 LL |     let [&mut ref mut x] = &mut [&mut 0];
    |               ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:30:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:32:9
    |
 LL |     let [&mut ref mut x] = &mut [&mut 0];
    |         ^^^^^^^^^^^^^^^^ this matches on type `&mut _`
@@ -67,14 +67,14 @@ LL |     let &mut [&mut ref mut x] = &mut [&mut 0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:39:11
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:41:11
    |
 LL |     let [&ref x] = &[&mut 0];
    |           ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:39:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:41:9
    |
 LL |     let [&ref x] = &[&mut 0];
    |         ^^^^^^^^ this matches on type `&_`
@@ -84,14 +84,14 @@ LL |     let &[&ref x] = &[&mut 0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:45:11
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:48:11
    |
 LL |     let [&ref x] = &mut [&mut 0];
    |           ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:45:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:48:9
    |
 LL |     let [&ref x] = &mut [&mut 0];
    |         ^^^^^^^^ this matches on type `&mut _`
@@ -101,14 +101,14 @@ LL |     let &mut [&ref x] = &mut [&mut 0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:54:15
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:58:15
    |
 LL |     let [&mut ref x] = &[&mut 0];
    |               ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:54:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:58:9
    |
 LL |     let [&mut ref x] = &[&mut 0];
    |         ^^^^^^^^^^^^ this matches on type `&_`
@@ -118,14 +118,14 @@ LL |     let &[&mut ref x] = &[&mut 0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:9
    |
 LL |     let [ref mut x] = &[0];
    |         ^^^^^^^^^^^ this matches on type `&_`
@@ -135,20 +135,20 @@ LL |     let &[ref mut x] = &[0];
    |         +
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:71:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^^^ cannot borrow as mutable
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
    |
 LL |     let [ref x] = &[0];
    |          ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
    |
 LL |     let [ref x] = &[0];
    |         ^^^^^^^ this matches on type `&_`
@@ -158,14 +158,14 @@ LL |     let &[ref x] = &[0];
    |         +
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
    |
 LL |     let [ref x] = &mut [0];
    |          ^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
    |
 LL |     let [ref x] = &mut [0];
    |         ^^^^^^^ this matches on type `&mut _`
@@ -175,14 +175,14 @@ LL |     let &mut [ref x] = &mut [0];
    |         ++++
 
 error: binding modifiers may only be written when the default binding mode is `move`
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:87:10
    |
 LL |     let [ref mut x] = &mut [0];
    |          ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/match-ergonomics.html>
 note: matching on a reference type with a non-reference pattern changes the default binding mode
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:9
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:87:9
    |
 LL |     let [ref mut x] = &mut [0];
    |         ^^^^^^^^^^^ this matches on type `&mut _`
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr
new file mode 100644
index 0000000000000..8127ca92e025e
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2021.stderr
@@ -0,0 +1,51 @@
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
+   |
+LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
+   |                 -             ^
+   |                 |
+   |                 help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31
+   |
+LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
+   |            -                  ^
+   |            |
+   |            help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15
+   |
+LL |     let &pat!(x) = &mut 0;
+   |         -     ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -         ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -                    ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:43:11
+   |
+LL |     let &[x] = &mut &mut [0];
+   |         - ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error: aborting due to 6 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed
index c01784d5076b7..57de9cb4c10d0 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.fixed
@@ -1,5 +1,7 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[classic2024] run-rustfix
@@ -7,19 +9,19 @@
 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
 //! to bind by mutable reference.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
     if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
@@ -28,18 +30,18 @@ pub fn main() {
     }
     let &mut pat!(x) = &mut 0;
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut u8 = x;
 
     let &mut (ref mut a, ref mut b) = &mut (true, false);
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
-    //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut bool = a;
     let _: &mut bool = b;
 
     let &mut [x] = &mut &mut [0];
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr
index 5e98b77be40cd..8127ca92e025e 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.classic2024.stderr
@@ -1,5 +1,5 @@
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:31
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
    |
 LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 -             ^
@@ -7,7 +7,7 @@ LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:31
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31
    |
 LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            -                  ^
@@ -15,7 +15,7 @@ LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:15
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15
    |
 LL |     let &pat!(x) = &mut 0;
    |         -     ^
@@ -23,7 +23,7 @@ LL |     let &pat!(x) = &mut 0;
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:19
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         -         ^
@@ -31,7 +31,7 @@ LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:30
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         -                    ^
@@ -39,7 +39,7 @@ LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:41:11
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:43:11
    |
 LL |     let &[x] = &mut &mut [0];
    |         - ^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
index fe40dabb55394..277ff90b673ce 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.rs
@@ -1,5 +1,7 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[classic2024] run-rustfix
@@ -7,19 +9,19 @@
 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
 //! to bind by mutable reference.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
@@ -28,18 +30,18 @@ pub fn main() {
     }
     let &pat!(x) = &mut 0;
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut u8 = x;
 
     let &(ref mut a, ref mut b) = &mut (true, false);
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
-    //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut bool = a;
     let _: &mut bool = b;
 
     let &[x] = &mut &mut [0];
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr
index 72c6c05e18443..5fbaacd7281d2 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:17
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:17
    |
 LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 ^^^^^^^^^^^^^^^^    ------------------ this expression has type `&mut Option<Option<{integer}>>`
@@ -10,7 +10,7 @@ LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:12
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:12
    |
 LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            ^^^^^^^^^^^^^^^^^^^^^^   ------------------ this expression has type `&mut Option<Option<{integer}>>`
@@ -21,7 +21,7 @@ LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:9
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:9
    |
 LL |     let &pat!(x) = &mut 0;
    |         ^^^^^^^^   ------ this expression has type `&mut {integer}`
@@ -32,7 +32,7 @@ LL |     let &pat!(x) = &mut 0;
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:9
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:9
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         ^^^^^^^^^^^^^^^^^^^^^^^   ------------------ this expression has type `&mut (bool, bool)`
@@ -43,7 +43,7 @@ LL |     let &(ref mut a, ref mut b) = &mut (true, false);
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:41:9
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:43:9
    |
 LL |     let &[x] = &mut &mut [0];
    |         ^^^^   ------------- this expression has type `&mut &mut [{integer}; 1]`
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr
new file mode 100644
index 0000000000000..e735cfed2492f
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2021.stderr
@@ -0,0 +1,43 @@
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
+   |
+LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
+   |                 -             ^
+   |                 |
+   |                 help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31
+   |
+LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
+   |            -                  ^
+   |            |
+   |            help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15
+   |
+LL |     let &pat!(x) = &mut 0;
+   |         -     ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -         ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error[E0596]: cannot borrow as mutable inside an `&` pattern
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30
+   |
+LL |     let &(ref mut a, ref mut b) = &mut (true, false);
+   |         -                    ^
+   |         |
+   |         help: replace this `&` with `&mut`: `&mut`
+
+error: aborting due to 5 previous errors
+
+For more information about this error, try `rustc --explain E0596`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed
index 4ee849b38c53b..bcde4b90f592c 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.fixed
@@ -1,5 +1,7 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[classic2024] run-rustfix
@@ -7,19 +9,19 @@
 //! Tests for `&` patterns matched against `&mut` reference types where the inner pattern attempts
 //! to bind by mutable reference.
 #![allow(incomplete_features)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     if let Some(&mut Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
     if let &mut Some(Some(ref mut x)) = &mut Some(Some(0)) {
         //[stable2021]~^ ERROR: mismatched types
-        //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+        //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
         let _: &mut u8 = x;
     }
 
@@ -28,18 +30,18 @@ pub fn main() {
     }
     let &mut pat!(x) = &mut 0;
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut u8 = x;
 
     let &mut (ref mut a, ref mut b) = &mut (true, false);
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
-    //[classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,structural2021,classic2024,structural2024]~| ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &mut bool = a;
     let _: &mut bool = b;
 
     let &[x] = &mut &mut [0];
     //[stable2021]~^ ERROR: mismatched types
-    //[classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
+    //[classic2021,classic2024]~^^ ERROR: cannot borrow as mutable inside an `&` pattern
     let _: &u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr
index 69cb6c438b6ed..e735cfed2492f 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-mut-inside-shared-ref-pat.structural2024.stderr
@@ -1,5 +1,5 @@
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:14:31
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:16:31
    |
 LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 -             ^
@@ -7,7 +7,7 @@ LL |     if let Some(&Some(ref mut x)) = &mut Some(Some(0)) {
    |                 help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:20:31
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:22:31
    |
 LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            -                  ^
@@ -15,7 +15,7 @@ LL |     if let &Some(Some(ref mut x)) = &mut Some(Some(0)) {
    |            help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:29:15
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:31:15
    |
 LL |     let &pat!(x) = &mut 0;
    |         -     ^
@@ -23,7 +23,7 @@ LL |     let &pat!(x) = &mut 0;
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:19
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:19
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         -         ^
@@ -31,7 +31,7 @@ LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         help: replace this `&` with `&mut`: `&mut`
 
 error[E0596]: cannot borrow as mutable inside an `&` pattern
-  --> $DIR/ref-mut-inside-shared-ref-pat.rs:34:30
+  --> $DIR/ref-mut-inside-shared-ref-pat.rs:36:30
    |
 LL |     let &(ref mut a, ref mut b) = &mut (true, false);
    |         -                    ^
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs
deleted file mode 100644
index ab3264704acc0..0000000000000
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021.rs
+++ /dev/null
@@ -1,17 +0,0 @@
-//@ run-pass
-//@ edition: 2021
-//@ revisions: classic structural
-#![allow(incomplete_features)]
-#![cfg_attr(classic, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural, feature(ref_pat_eat_one_layer_2024_structural))]
-
-pub fn main() {
-    #[cfg(structural)]
-    if let &Some(Some(x)) = &Some(&mut Some(0)) {
-        let _: &u32 = x;
-    }
-
-    if let Some(&x) = Some(&mut 0) {
-        let _: u32 = x;
-    }
-}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs
deleted file mode 100644
index d28567f2859a3..0000000000000
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.rs
+++ /dev/null
@@ -1,37 +0,0 @@
-//@ edition: 2021
-#![allow(incomplete_features)]
-#![feature(ref_pat_eat_one_layer_2024)]
-pub fn main() {
-    if let Some(Some(&x)) = &Some(&Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(Some(&x)) = &Some(Some(&0)) {
-        let _: &u32 = x;
-        //~^ ERROR: mismatched types
-    }
-    if let Some(Some(&&x)) = &Some(Some(&0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(&Some(x)) = &Some(Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(Some(&x)) = &Some(&Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-    if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
-        //~^ ERROR: mismatched types
-        let _: u32 = x;
-    }
-}
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr
deleted file mode 100644
index 0158ed0f42357..0000000000000
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref_pat_eat_one_layer_2021_fail.stderr
+++ /dev/null
@@ -1,133 +0,0 @@
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:5:22
-   |
-LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
-   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
-   |                      |
-   |                      expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL -     if let Some(Some(&x)) = &Some(&Some(0)) {
-LL +     if let Some(Some(x)) = &Some(&Some(0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:10:23
-   |
-LL |         let _: &u32 = x;
-   |                ----   ^ expected `&u32`, found integer
-   |                |
-   |                expected due to this
-   |
-help: consider borrowing here
-   |
-LL |         let _: &u32 = &x;
-   |                       +
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:13:23
-   |
-LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
-   |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
-   |                       |
-   |                       expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL -     if let Some(Some(&&x)) = &Some(Some(&0)) {
-LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:17:17
-   |
-LL |     if let Some(&Some(x)) = &Some(Some(0)) {
-   |                 ^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
-   |                 |
-   |                 expected `Option<{integer}>`, found `&_`
-   |
-   = note:   expected enum `Option<{integer}>`
-           found reference `&_`
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:21:22
-   |
-LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-   |                      ^^^^^^     ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
-   |                      |
-   |                      expected integer, found `&mut _`
-   |
-   = note:           expected type `{integer}`
-           found mutable reference `&mut _`
-note: to declare a mutable binding use: `mut x`
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:21:22
-   |
-LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-   |                      ^^^^^^
-help: consider removing `&mut` from the pattern
-   |
-LL -     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
-LL +     if let Some(Some(x)) = &mut Some(&mut Some(0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:25:22
-   |
-LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
-   |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
-   |                      |
-   |                      expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL -     if let Some(Some(&x)) = &Some(&Some(0)) {
-LL +     if let Some(Some(x)) = &Some(&Some(0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:29:27
-   |
-LL |     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-   |                           ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
-   |                           |
-   |                           expected integer, found `&_`
-   |
-   = note:   expected type `{integer}`
-           found reference `&_`
-help: consider removing `&` from the pattern
-   |
-LL -     if let Some(&mut Some(&x)) = &Some(&mut Some(0)) {
-LL +     if let Some(&mut Some(x)) = &Some(&mut Some(0)) {
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:33:23
-   |
-LL |     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
-   |                       ^^^^^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
-   |                       |
-   |                       expected integer, found `&mut _`
-   |
-   = note:           expected type `{integer}`
-           found mutable reference `&mut _`
-note: to declare a mutable binding use: `mut x`
-  --> $DIR/ref_pat_eat_one_layer_2021_fail.rs:33:23
-   |
-LL |     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
-   |                       ^^^^^^
-help: consider removing `&mut` from the pattern
-   |
-LL -     if let Some(&Some(&mut x)) = &mut Some(&Some(0)) {
-LL +     if let Some(&Some(x)) = &mut Some(&Some(0)) {
-   |
-
-error: aborting due to 8 previous errors
-
-For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr
new file mode 100644
index 0000000000000..f8c2bd9a92128
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.classic2021.stderr
@@ -0,0 +1,122 @@
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:32:23
+   |
+LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
+   |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(Some(&&x)) = &Some(Some(&0)) {
+LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:63:23
+   |
+LL |     if let Some(&Some(&x)) = &Some(&Some(0)) {
+   |                       ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &Some(&Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:82:23
+   |
+LL |     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+   |                       ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:88:23
+   |
+LL |     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+   |                       ^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+LL +     if let Some(&Some(x)) = &mut Some(&Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:123:15
+   |
+LL |     let [&mut &x] = &mut [&0];
+   |               ^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &x] = &mut [&0];
+LL +     let [&mut x] = &mut [&0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:129:15
+   |
+LL |     let [&mut &ref x] = &mut [&0];
+   |               ^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &ref x] = &mut [&0];
+LL +     let [&mut ref x] = &mut [&0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:135:15
+   |
+LL |     let [&mut &(mut x)] = &mut [&0];
+   |               ^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &(mut x)] = &mut [&0];
+LL +     let [&mut mut x)] = &mut [&0];
+   |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/well-typed-edition-2024.rs:109:19
+   |
+LL |         let [&mut ref mut x] = &mut [&0];
+   |                   ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0596.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
index 3114b9d3bf8cb..62c1c28022b7d 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.rs
@@ -1,5 +1,7 @@
-//@ revisions: stable2021 classic2024 structural2024
+//@ revisions: stable2021 classic2021 structural2021 classic2024 structural2024
 //@[stable2021] edition: 2021
+//@[classic2021] edition: 2021
+//@[structural2021] edition: 2021
 //@[classic2024] edition: 2024
 //@[structural2024] edition: 2024
 //@[classic2024] run-pass
@@ -7,8 +9,8 @@
 //! Test cases for well-typed patterns in edition 2024. These are in their own file to ensure we
 //! pass both HIR typeck and MIR borrowck, as we may skip the latter if grouped with failing tests.
 #![allow(incomplete_features, unused_mut)]
-#![cfg_attr(classic2024, feature(ref_pat_eat_one_layer_2024))]
-#![cfg_attr(structural2024, feature(ref_pat_eat_one_layer_2024_structural))]
+#![cfg_attr(any(classic2021, classic2024), feature(ref_pat_eat_one_layer_2024))]
+#![cfg_attr(any(structural2021, structural2024), feature(ref_pat_eat_one_layer_2024_structural))]
 
 pub fn main() {
     // Tests not using match ergonomics. These should always succeed with the same bindings.
@@ -18,110 +20,121 @@ pub fn main() {
 
     // Tests for differences in how many layers of reference are eaten by reference patterns
     if let Some(Some(&x)) = &Some(Some(&0)) {
-        #[cfg(stable2021)] let _: u32 = x;
+        #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
         #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
     }
     if let Some(&Some(x)) = &mut Some(&Some(0)) {
         // This additionally tests that `&` patterns can eat inherited `&mut` refs.
         // This is possible on stable when the real reference being eaten is of a `&` type.
-        #[cfg(stable2021)] let _: u32 = x;
+        #[cfg(any(stable2021, classic2021, structural2021))] let _: u32 = x;
         #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
     }
     if let Some(Some(&&x)) = &Some(Some(&0)) {
-        //[stable2021]~^ mismatched types
-        //[stable2021]~| expected integer, found `&_`
-        let _: u32 = x;
+        //[stable2021,classic2021,structural2021]~^ mismatched types
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&_`
+        #[cfg(any(classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests for eating a lone inherited reference
     if let Some(Some(&x)) = &Some(&Some(0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected integer, found `&_`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
     if let Some(&Some(x)) = &Some(Some(0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected `Option<{integer}>`, found `&_`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected integer, found `&mut _`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests for `&` patterns matching real `&mut` reference types
     if let Some(&Some(&x)) = Some(&Some(&mut 0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| types differ in mutability
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests for eating only one layer and also eating a lone inherited reference
     if let Some(&Some(&x)) = &Some(&Some(0)) {
-        //[stable2021]~^ mismatched types
-        //[stable2021]~| expected integer, found `&_`
-        let _: u32 = x;
+        //[stable2021,classic2021,structural2021]~^ mismatched types
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&_`
+        #[cfg(any(classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests for `&` matching a lone inherited possibly-`&mut` reference
     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected `Option<&mut Option<{integer}>>`, found `&_`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
     if let Some(&Some(x)) = &mut Some(Some(0)) {
         //[stable2021]~^ mismatched types
         //[stable2021]~| expected `Option<{integer}>`, found `&_`
-        let _: u32 = x;
+        #[cfg(any(classic2021, structural2021, classic2024, structural2024))] let _: u32 = x;
     }
 
     // Tests eating one layer, eating a lone inherited ref, and `&` eating `&mut` (realness varies)
     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
-        //[stable2021]~^ mismatched types
+        //[stable2021,classic2021,structural2021]~^ mismatched types
         //[stable2021]~| types differ in mutability
-        let _: u32 = x;
+        //[classic2021,structural2021]~| expected integer, found `&_`
+        #[cfg(any(classic2024, structural2024))] let _: u32 = x;
     }
     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
-        //[stable2021]~^ mismatched types
-        //[stable2021]~| expected integer, found `&_`
-        let _: u32 = x;
+        //[stable2021,classic2021,structural2021]~^ mismatched types
+        //[stable2021,classic2021,structural2021]~| expected integer, found `&_`
+        #[cfg(any(classic2024, structural2024))] let _: u32 = x;
     }
 
-    // Tests for eat-inner rulesets matching on the outer reference if matching on the inner
-    // reference causes a mutability mismatch, i.e. `Deref(EatInner, FallbackToOuter)`:
+    // Tests for eat-inner and eat-both rulesets matching on the outer reference if matching on the
+    // inner reference causes a mutability mismatch. i.e. tests for "fallback-to-outer" deref rules.
     let [&mut x] = &mut [&0];
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: &u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: u32 = x;
+    #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
 
     let [&mut ref x] = &mut [&0];
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: &&u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: &u32 = x;
+    #[cfg(any(classic2024, structural2024))] let _: &&u32 = x;
 
-    let [&mut ref mut x] = &mut [&0];
-    //[stable2021]~^ mismatched types
-    //[stable2021]~| types differ in mutability
-    let _: &mut &u32 = x;
+    fn borrowck_error_on_structural2021() {
+        let [&mut ref mut x] = &mut [&0];
+        //[stable2021]~^ mismatched types
+        //[stable2021]~| types differ in mutability
+        //[classic2021,structural2021]~^^^ cannot borrow data in a `&` reference as mutable
+        #[cfg(any(classic2024, structural2024))] let _: &mut &u32 = x;
+    }
+    borrowck_error_on_structural2021();
 
     let [&mut mut x] = &mut [&0];
     //[stable2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: &u32 = x;
+    #[cfg(any(classic2021, structural2021))] let _: u32 = x;
+    #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
 
     let [&mut &x] = &mut [&0];
-    //[stable2021]~^ mismatched types
+    //[stable2021,classic2021,structural2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: u32 = x;
+    //[classic2021,structural2021]~| expected integer, found `&_`
+    #[cfg(any(classic2024, structural2024))] let _: u32 = x;
 
     let [&mut &ref x] = &mut [&0];
-    //[stable2021]~^ mismatched types
+    //[stable2021,classic2021,structural2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: &u32 = x;
+    //[classic2021,structural2021]~| expected integer, found `&_`
+    #[cfg(any(classic2024, structural2024))] let _: &u32 = x;
 
     let [&mut &(mut x)] = &mut [&0];
-    //[stable2021]~^ mismatched types
+    //[stable2021,classic2021,structural2021]~^ mismatched types
     //[stable2021]~| types differ in mutability
-    let _: u32 = x;
+    //[classic2021,structural2021]~| expected integer, found `&_`
+    #[cfg(any(classic2024, structural2024))] let _: u32 = x;
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr
index b1a8024397bdc..adb47172f34cc 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.stable2021.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:30:23
+  --> $DIR/well-typed-edition-2024.rs:32:23
    |
 LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
    |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
@@ -15,7 +15,7 @@ LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:37:22
+  --> $DIR/well-typed-edition-2024.rs:39:22
    |
 LL |     if let Some(Some(&x)) = &Some(&Some(0)) {
    |                      ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
@@ -31,7 +31,7 @@ LL +     if let Some(Some(x)) = &Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:42:17
+  --> $DIR/well-typed-edition-2024.rs:44:17
    |
 LL |     if let Some(&Some(x)) = &Some(Some(0)) {
    |                 ^^^^^^^^    -------------- this expression has type `&Option<Option<{integer}>>`
@@ -42,7 +42,7 @@ LL |     if let Some(&Some(x)) = &Some(Some(0)) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:47:22
+  --> $DIR/well-typed-edition-2024.rs:49:22
    |
 LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
    |                      ^^^^^^     ----------------------- this expression has type `&mut Option<&mut Option<{integer}>>`
@@ -52,7 +52,7 @@ LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
    = note:           expected type `{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:47:22
+  --> $DIR/well-typed-edition-2024.rs:49:22
    |
 LL |     if let Some(Some(&mut x)) = &mut Some(&mut Some(0)) {
    |                      ^^^^^^
@@ -63,7 +63,7 @@ LL +     if let Some(Some(x)) = &mut Some(&mut Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:54:23
+  --> $DIR/well-typed-edition-2024.rs:56:23
    |
 LL |     if let Some(&Some(&x)) = Some(&Some(&mut 0)) {
    |                       ^^     ------------------- this expression has type `Option<&Option<&mut {integer}>>`
@@ -79,7 +79,7 @@ LL +     if let Some(&Some(x)) = Some(&Some(&mut 0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:61:23
+  --> $DIR/well-typed-edition-2024.rs:63:23
    |
 LL |     if let Some(&Some(&x)) = &Some(&Some(0)) {
    |                       ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
@@ -95,7 +95,7 @@ LL +     if let Some(&Some(x)) = &Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:68:17
+  --> $DIR/well-typed-edition-2024.rs:70:17
    |
 LL |     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
    |                 ^^^^^^^^^^^^^^^    ------------------------- this expression has type `&Option<Option<&mut Option<{integer}>>>`
@@ -106,7 +106,7 @@ LL |     if let Some(&Some(Some(&x))) = &Some(Some(&mut Some(0))) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:73:17
+  --> $DIR/well-typed-edition-2024.rs:75:17
    |
 LL |     if let Some(&Some(x)) = &mut Some(Some(0)) {
    |                 ^^^^^^^^    ------------------ this expression has type `&mut Option<Option<{integer}>>`
@@ -117,7 +117,7 @@ LL |     if let Some(&Some(x)) = &mut Some(Some(0)) {
            found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:80:17
+  --> $DIR/well-typed-edition-2024.rs:82:17
    |
 LL |     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
    |                 ^^^^^^^^^    ------------------- this expression has type `&Option<&mut Option<{integer}>>`
@@ -128,7 +128,7 @@ LL |     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
                       found reference `&_`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:85:23
+  --> $DIR/well-typed-edition-2024.rs:88:23
    |
 LL |     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
    |                       ^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
@@ -144,7 +144,7 @@ LL +     if let Some(&Some(x)) = &mut Some(&Some(0)) {
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:93:10
+  --> $DIR/well-typed-edition-2024.rs:96:10
    |
 LL |     let [&mut x] = &mut [&0];
    |          ^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -154,7 +154,7 @@ LL |     let [&mut x] = &mut [&0];
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:93:10
+  --> $DIR/well-typed-edition-2024.rs:96:10
    |
 LL |     let [&mut x] = &mut [&0];
    |          ^^^^^^
@@ -165,7 +165,7 @@ LL +     let [x] = &mut [&0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:98:10
+  --> $DIR/well-typed-edition-2024.rs:102:10
    |
 LL |     let [&mut ref x] = &mut [&0];
    |          ^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -175,7 +175,7 @@ LL |     let [&mut ref x] = &mut [&0];
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:98:10
+  --> $DIR/well-typed-edition-2024.rs:102:10
    |
 LL |     let [&mut ref x] = &mut [&0];
    |          ^^^^^^^^^^
@@ -186,28 +186,7 @@ LL +     let [ref x] = &mut [&0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:103:10
-   |
-LL |     let [&mut ref mut x] = &mut [&0];
-   |          ^^^^^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
-   |          |
-   |          types differ in mutability
-   |
-   = note:      expected reference `&{integer}`
-           found mutable reference `&mut _`
-note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:103:10
-   |
-LL |     let [&mut ref mut x] = &mut [&0];
-   |          ^^^^^^^^^^^^^^
-help: consider removing `&mut` from the pattern
-   |
-LL -     let [&mut ref mut x] = &mut [&0];
-LL +     let [ref mut x] = &mut [&0];
-   |
-
-error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:108:10
+  --> $DIR/well-typed-edition-2024.rs:117:10
    |
 LL |     let [&mut mut x] = &mut [&0];
    |          ^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -217,7 +196,7 @@ LL |     let [&mut mut x] = &mut [&0];
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
 note: to declare a mutable binding use: `mut x`
-  --> $DIR/well-typed-edition-2024.rs:108:10
+  --> $DIR/well-typed-edition-2024.rs:117:10
    |
 LL |     let [&mut mut x] = &mut [&0];
    |          ^^^^^^^^^^
@@ -228,7 +207,7 @@ LL +     let [mut x] = &mut [&0];
    |
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:113:10
+  --> $DIR/well-typed-edition-2024.rs:123:10
    |
 LL |     let [&mut &x] = &mut [&0];
    |          ^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -239,7 +218,7 @@ LL |     let [&mut &x] = &mut [&0];
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:118:10
+  --> $DIR/well-typed-edition-2024.rs:129:10
    |
 LL |     let [&mut &ref x] = &mut [&0];
    |          ^^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -250,7 +229,7 @@ LL |     let [&mut &ref x] = &mut [&0];
            found mutable reference `&mut _`
 
 error[E0308]: mismatched types
-  --> $DIR/well-typed-edition-2024.rs:123:10
+  --> $DIR/well-typed-edition-2024.rs:135:10
    |
 LL |     let [&mut &(mut x)] = &mut [&0];
    |          ^^^^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
@@ -260,6 +239,27 @@ LL |     let [&mut &(mut x)] = &mut [&0];
    = note:      expected reference `&{integer}`
            found mutable reference `&mut _`
 
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:109:14
+   |
+LL |         let [&mut ref mut x] = &mut [&0];
+   |              ^^^^^^^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |              |
+   |              types differ in mutability
+   |
+   = note:      expected reference `&{integer}`
+           found mutable reference `&mut _`
+note: to declare a mutable binding use: `mut x`
+  --> $DIR/well-typed-edition-2024.rs:109:14
+   |
+LL |         let [&mut ref mut x] = &mut [&0];
+   |              ^^^^^^^^^^^^^^
+help: consider removing `&mut` from the pattern
+   |
+LL -         let [&mut ref mut x] = &mut [&0];
+LL +         let [ref mut x] = &mut [&0];
+   |
+
 error: aborting due to 17 previous errors
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr
new file mode 100644
index 0000000000000..f8c2bd9a92128
--- /dev/null
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/well-typed-edition-2024.structural2021.stderr
@@ -0,0 +1,122 @@
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:32:23
+   |
+LL |     if let Some(Some(&&x)) = &Some(Some(&0)) {
+   |                       ^^     --------------- this expression has type `&Option<Option<&{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(Some(&&x)) = &Some(Some(&0)) {
+LL +     if let Some(Some(&x)) = &Some(Some(&0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:63:23
+   |
+LL |     if let Some(&Some(&x)) = &Some(&Some(0)) {
+   |                       ^^     --------------- this expression has type `&Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &Some(&Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:82:23
+   |
+LL |     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+   |                       ^^     ------------------- this expression has type `&Option<&mut Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &Some(&mut Some(0)) {
+LL +     if let Some(&Some(x)) = &Some(&mut Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:88:23
+   |
+LL |     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+   |                       ^^     ------------------- this expression has type `&mut Option<&Option<{integer}>>`
+   |                       |
+   |                       expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     if let Some(&Some(&x)) = &mut Some(&Some(0)) {
+LL +     if let Some(&Some(x)) = &mut Some(&Some(0)) {
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:123:15
+   |
+LL |     let [&mut &x] = &mut [&0];
+   |               ^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &x] = &mut [&0];
+LL +     let [&mut x] = &mut [&0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:129:15
+   |
+LL |     let [&mut &ref x] = &mut [&0];
+   |               ^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &ref x] = &mut [&0];
+LL +     let [&mut ref x] = &mut [&0];
+   |
+
+error[E0308]: mismatched types
+  --> $DIR/well-typed-edition-2024.rs:135:15
+   |
+LL |     let [&mut &(mut x)] = &mut [&0];
+   |               ^^^^^^^^    --------- this expression has type `&mut [&{integer}; 1]`
+   |               |
+   |               expected integer, found `&_`
+   |
+   = note:   expected type `{integer}`
+           found reference `&_`
+help: consider removing `&` from the pattern
+   |
+LL -     let [&mut &(mut x)] = &mut [&0];
+LL +     let [&mut mut x)] = &mut [&0];
+   |
+
+error[E0596]: cannot borrow data in a `&` reference as mutable
+  --> $DIR/well-typed-edition-2024.rs:109:19
+   |
+LL |         let [&mut ref mut x] = &mut [&0];
+   |                   ^^^^^^^^^ cannot borrow as mutable
+
+error: aborting due to 8 previous errors
+
+Some errors have detailed explanations: E0308, E0596.
+For more information about an error, try `rustc --explain E0308`.
diff --git a/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs
new file mode 100644
index 0000000000000..432e3c0b77efc
--- /dev/null
+++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.rs
@@ -0,0 +1,123 @@
+// see also https://github.com/rust-lang/rust/issues/22692
+
+type Alias = Vec<u32>;
+
+mod foo {
+    fn bar() {}
+}
+
+fn main() {
+    let _ = String.new();
+    //~^ ERROR expected value, found struct `String`
+    //~| HELP use the path separator
+
+    let _ = String.default;
+    //~^ ERROR expected value, found struct `String`
+    //~| HELP use the path separator
+
+    let _ = Vec::<()>.with_capacity(1);
+    //~^ ERROR expected value, found struct `Vec`
+    //~| HELP use the path separator
+
+    let _ = Alias.new();
+    //~^ ERROR expected value, found type alias `Alias`
+    //~| HELP use the path separator
+
+    let _ = Alias.default;
+    //~^ ERROR expected value, found type alias `Alias`
+    //~| HELP use the path separator
+
+    let _ = foo.bar;
+    //~^ ERROR expected value, found module `foo`
+    //~| HELP use the path separator
+}
+
+macro_rules! Type {
+    () => {
+        ::std::cell::Cell
+        //~^ ERROR expected value, found struct `std::cell::Cell`
+        //~| ERROR expected value, found struct `std::cell::Cell`
+        //~| ERROR expected value, found struct `std::cell::Cell`
+    };
+    (alias) => {
+        Alias
+        //~^ ERROR expected value, found type alias `Alias`
+        //~| ERROR expected value, found type alias `Alias`
+        //~| ERROR expected value, found type alias `Alias`
+    };
+}
+
+macro_rules! create {
+    (type method) => {
+        Vec.new()
+        //~^ ERROR expected value, found struct `Vec`
+        //~| HELP use the path separator
+    };
+    (type field) => {
+        Vec.new
+        //~^ ERROR expected value, found struct `Vec`
+        //~| HELP use the path separator
+    };
+    (macro method) => {
+        Type!().new(0)
+        //~^ HELP use the path separator
+    };
+    (macro method alias) => {
+        Type!(alias).new(0)
+        //~^ HELP use the path separator
+    };
+}
+
+macro_rules! check_ty {
+    ($Ty:ident) => {
+        $Ty.foo
+        //~^ ERROR expected value, found type alias `Alias`
+        //~| HELP use the path separator
+    };
+}
+macro_rules! check_ident {
+    ($Ident:ident) => {
+        Alias.$Ident
+        //~^ ERROR expected value, found type alias `Alias`
+        //~| HELP use the path separator
+    };
+}
+macro_rules! check_ty_ident {
+    ($Ty:ident, $Ident:ident) => {
+        $Ty.$Ident
+        //~^ ERROR expected value, found type alias `Alias`
+        //~| HELP use the path separator
+    };
+}
+
+fn interaction_with_macros() {
+    //
+    // Verify that we do not only suggest to replace `.` with `::` if the receiver is a
+    // macro call but that we also correctly suggest to surround it with angle brackets.
+    //
+
+    Type!().get();
+    //~^ HELP use the path separator
+
+    Type! {}.get;
+    //~^ HELP use the path separator
+
+    Type!(alias).get();
+    //~^ HELP use the path separator
+
+    Type! {alias}.get;
+    //~^ HELP use the path separator
+
+    //
+    // Ensure that the suggestion is shown for expressions inside of macro definitions.
+    //
+
+    let _ = create!(type method);
+    let _ = create!(type field);
+    let _ = create!(macro method);
+    let _ = create!(macro method alias);
+
+    let _ = check_ty!(Alias);
+    let _ = check_ident!(foo);
+    let _ = check_ty_ident!(Alias, foo);
+}
diff --git a/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr
new file mode 100644
index 0000000000000..d74814dd876c2
--- /dev/null
+++ b/tests/ui/resolve/dot-notation-type-namespace-suggest-path-sep.stderr
@@ -0,0 +1,251 @@
+error[E0423]: expected value, found struct `String`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:10:13
+   |
+LL |     let _ = String.new();
+   |             ^^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = String.new();
+LL +     let _ = String::new();
+   |
+
+error[E0423]: expected value, found struct `String`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:14:13
+   |
+LL |     let _ = String.default;
+   |             ^^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = String.default;
+LL +     let _ = String::default;
+   |
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:18:13
+   |
+LL |     let _ = Vec::<()>.with_capacity(1);
+   |             ^^^^^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = Vec::<()>.with_capacity(1);
+LL +     let _ = Vec::<()>::with_capacity(1);
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:22:13
+   |
+LL |     let _ = Alias.new();
+   |             ^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = Alias.new();
+LL +     let _ = Alias::new();
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:26:13
+   |
+LL |     let _ = Alias.default;
+   |             ^^^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = Alias.default;
+LL +     let _ = Alias::default;
+   |
+
+error[E0423]: expected value, found module `foo`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:30:13
+   |
+LL |     let _ = foo.bar;
+   |             ^^^
+   |
+help: use the path separator to refer to an item
+   |
+LL -     let _ = foo.bar;
+LL +     let _ = foo::bar;
+   |
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     Type!().get();
+   |     ------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -     Type!().get();
+LL +     <Type!()>::get();
+   |
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     Type! {}.get;
+   |     -------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -     Type! {}.get;
+LL +     <Type! {}>::get;
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
+   |
+LL |         Alias
+   |         ^^^^^
+...
+LL |     Type!(alias).get();
+   |     ------------ in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -     Type!(alias).get();
+LL +     <Type!(alias)>::get();
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
+   |
+LL |         Alias
+   |         ^^^^^
+...
+LL |     Type! {alias}.get;
+   |     ------------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -     Type! {alias}.get;
+LL +     <Type! {alias}>::get;
+   |
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:52:9
+   |
+LL |         Vec.new()
+   |         ^^^
+...
+LL |     let _ = create!(type method);
+   |             -------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Vec.new()
+LL +         Vec::new()
+   |
+
+error[E0423]: expected value, found struct `Vec`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:57:9
+   |
+LL |         Vec.new
+   |         ^^^
+...
+LL |     let _ = create!(type field);
+   |             ------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Vec.new
+LL +         Vec::new
+   |
+
+error[E0423]: expected value, found struct `std::cell::Cell`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:37:9
+   |
+LL |         ::std::cell::Cell
+   |         ^^^^^^^^^^^^^^^^^
+...
+LL |     let _ = create!(macro method);
+   |             --------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Type!().new(0)
+LL +         <Type!()>::new(0)
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:43:9
+   |
+LL |         Alias
+   |         ^^^^^
+...
+LL |     let _ = create!(macro method alias);
+   |             --------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Type!(alias).new(0)
+LL +         <Type!(alias)>::new(0)
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:73:9
+   |
+LL |         $Ty.foo
+   |         ^^^
+...
+LL |     let _ = check_ty!(Alias);
+   |             ---------------- in this macro invocation
+   |
+   = note: this error originates in the macro `check_ty` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         $Ty.foo
+LL +         $Ty::foo
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:80:9
+   |
+LL |         Alias.$Ident
+   |         ^^^^^
+...
+LL |     let _ = check_ident!(foo);
+   |             ----------------- in this macro invocation
+   |
+   = note: this error originates in the macro `check_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         Alias.$Ident
+LL +         <Alias>::$Ident
+   |
+
+error[E0423]: expected value, found type alias `Alias`
+  --> $DIR/dot-notation-type-namespace-suggest-path-sep.rs:87:9
+   |
+LL |         $Ty.$Ident
+   |         ^^^
+...
+LL |     let _ = check_ty_ident!(Alias, foo);
+   |             --------------------------- in this macro invocation
+   |
+   = note: this error originates in the macro `check_ty_ident` (in Nightly builds, run with -Z macro-backtrace for more info)
+help: use the path separator to refer to an item
+   |
+LL -         $Ty.$Ident
+LL +         <$Ty>::$Ident
+   |
+
+error: aborting due to 17 previous errors
+
+For more information about this error, try `rustc --explain E0423`.
diff --git a/tests/ui/resolve/enum-expected-value-suggest-variants.rs b/tests/ui/resolve/enum-expected-value-suggest-variants.rs
new file mode 100644
index 0000000000000..9f86a0a1ecc76
--- /dev/null
+++ b/tests/ui/resolve/enum-expected-value-suggest-variants.rs
@@ -0,0 +1,58 @@
+enum Foo {
+    //~^ HELP consider importing this tuple variant
+    A(u32),
+    B(u32),
+}
+
+enum Bar {
+    C(u32),
+    D(u32),
+    E,
+    F,
+}
+
+fn main() {
+    let _: Foo = Foo(0);
+    //~^ ERROR expected function
+    //~| HELP try to construct one of the enum's variants
+
+    let _: Foo = Foo.A(0);
+    //~^ ERROR expected value, found enum `Foo`
+    //~| HELP use the path separator to refer to a variant
+
+    let _: Foo = Foo.Bad(0);
+    //~^ ERROR expected value, found enum `Foo`
+    //~| HELP the following enum variants are available
+
+    let _: Bar = Bar(0);
+    //~^ ERROR expected function
+    //~| HELP try to construct one of the enum's variants
+    //~| HELP you might have meant to construct one of the enum's non-tuple variants
+
+    let _: Bar = Bar.C(0);
+    //~^ ERROR expected value, found enum `Bar`
+    //~| HELP use the path separator to refer to a variant
+
+    let _: Bar = Bar.E;
+    //~^ ERROR expected value, found enum `Bar`
+    //~| HELP use the path separator to refer to a variant
+
+    let _: Bar = Bar.Bad(0);
+    //~^ ERROR expected value, found enum `Bar`
+    //~| HELP you might have meant to use one of the following enum variants
+    //~| HELP alternatively, the following enum variants are also available
+
+    let _: Bar = Bar.Bad;
+    //~^ ERROR expected value, found enum `Bar`
+    //~| HELP you might have meant to use one of the following enum variants
+    //~| HELP alternatively, the following enum variants are also available
+
+    match Foo::A(42) {
+        A(..) => {}
+        //~^ ERROR cannot find tuple struct or tuple variant `A` in this scope
+        Foo(..) => {}
+        //~^ ERROR expected tuple struct or tuple variant
+        //~| HELP try to match against one of the enum's variants
+        _ => {}
+    }
+}
diff --git a/tests/ui/resolve/enum-expected-value-suggest-variants.stderr b/tests/ui/resolve/enum-expected-value-suggest-variants.stderr
new file mode 100644
index 0000000000000..548a4c0e59320
--- /dev/null
+++ b/tests/ui/resolve/enum-expected-value-suggest-variants.stderr
@@ -0,0 +1,234 @@
+error[E0423]: expected value, found enum `Foo`
+  --> $DIR/enum-expected-value-suggest-variants.rs:19:18
+   |
+LL |     let _: Foo = Foo.A(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:1:1
+   |
+LL | / enum Foo {
+LL | |
+LL | |     A(u32),
+LL | |     B(u32),
+LL | | }
+   | |_^
+help: use the path separator to refer to a variant
+   |
+LL -     let _: Foo = Foo.A(0);
+LL +     let _: Foo = Foo::A(0);
+   |
+
+error[E0423]: expected value, found enum `Foo`
+  --> $DIR/enum-expected-value-suggest-variants.rs:23:18
+   |
+LL |     let _: Foo = Foo.Bad(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:1:1
+   |
+LL | / enum Foo {
+LL | |
+LL | |     A(u32),
+LL | |     B(u32),
+LL | | }
+   | |_^
+help: the following enum variants are available
+   |
+LL -     let _: Foo = Foo.Bad(0);
+LL +     let _: Foo = (Foo::A(/* fields */)).Bad(0);
+   |
+LL -     let _: Foo = Foo.Bad(0);
+LL +     let _: Foo = (Foo::B(/* fields */)).Bad(0);
+   |
+
+error[E0423]: expected value, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:32:18
+   |
+LL |     let _: Bar = Bar.C(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: use the path separator to refer to a variant
+   |
+LL -     let _: Bar = Bar.C(0);
+LL +     let _: Bar = Bar::C(0);
+   |
+
+error[E0423]: expected value, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:36:18
+   |
+LL |     let _: Bar = Bar.E;
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: use the path separator to refer to a variant
+   |
+LL -     let _: Bar = Bar.E;
+LL +     let _: Bar = Bar::E;
+   |
+
+error[E0423]: expected value, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:40:18
+   |
+LL |     let _: Bar = Bar.Bad(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: you might have meant to use one of the following enum variants
+   |
+LL |     let _: Bar = Bar::E.Bad(0);
+   |                     +++
+LL |     let _: Bar = Bar::F.Bad(0);
+   |                     +++
+help: alternatively, the following enum variants are also available
+   |
+LL -     let _: Bar = Bar.Bad(0);
+LL +     let _: Bar = (Bar::C(/* fields */)).Bad(0);
+   |
+LL -     let _: Bar = Bar.Bad(0);
+LL +     let _: Bar = (Bar::D(/* fields */)).Bad(0);
+   |
+
+error[E0423]: expected value, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:45:18
+   |
+LL |     let _: Bar = Bar.Bad;
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: you might have meant to use one of the following enum variants
+   |
+LL |     let _: Bar = Bar::E.Bad;
+   |                     +++
+LL |     let _: Bar = Bar::F.Bad;
+   |                     +++
+help: alternatively, the following enum variants are also available
+   |
+LL -     let _: Bar = Bar.Bad;
+LL +     let _: Bar = (Bar::C(/* fields */)).Bad;
+   |
+LL -     let _: Bar = Bar.Bad;
+LL +     let _: Bar = (Bar::D(/* fields */)).Bad;
+   |
+
+error[E0531]: cannot find tuple struct or tuple variant `A` in this scope
+  --> $DIR/enum-expected-value-suggest-variants.rs:51:9
+   |
+LL |         A(..) => {}
+   |         ^ not found in this scope
+   |
+help: consider importing this tuple variant
+   |
+LL + use Foo::A;
+   |
+
+error[E0532]: expected tuple struct or tuple variant, found enum `Foo`
+  --> $DIR/enum-expected-value-suggest-variants.rs:53:9
+   |
+LL |         Foo(..) => {}
+   |         ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:1:1
+   |
+LL | / enum Foo {
+LL | |
+LL | |     A(u32),
+LL | |     B(u32),
+LL | | }
+   | |_^
+help: try to match against one of the enum's variants
+   |
+LL |         Foo::A(..) => {}
+   |            +++
+LL |         Foo::B(..) => {}
+   |            +++
+
+error[E0423]: expected function, tuple struct or tuple variant, found enum `Foo`
+  --> $DIR/enum-expected-value-suggest-variants.rs:15:18
+   |
+LL |     let _: Foo = Foo(0);
+   |                  ^^^
+   |
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:1:1
+   |
+LL | / enum Foo {
+LL | |
+LL | |     A(u32),
+LL | |     B(u32),
+LL | | }
+   | |_^
+help: try to construct one of the enum's variants
+   |
+LL |     let _: Foo = Foo::A(0);
+   |                     +++
+LL |     let _: Foo = Foo::B(0);
+   |                     +++
+
+error[E0423]: expected function, tuple struct or tuple variant, found enum `Bar`
+  --> $DIR/enum-expected-value-suggest-variants.rs:27:18
+   |
+LL |     let _: Bar = Bar(0);
+   |                  ^^^
+   |
+   = help: you might have meant to construct one of the enum's non-tuple variants
+note: the enum is defined here
+  --> $DIR/enum-expected-value-suggest-variants.rs:7:1
+   |
+LL | / enum Bar {
+LL | |     C(u32),
+LL | |     D(u32),
+LL | |     E,
+LL | |     F,
+LL | | }
+   | |_^
+help: try to construct one of the enum's variants
+   |
+LL |     let _: Bar = Bar::C(0);
+   |                     +++
+LL |     let _: Bar = Bar::D(0);
+   |                     +++
+
+error: aborting due to 10 previous errors
+
+Some errors have detailed explanations: E0423, E0531, E0532.
+For more information about an error, try `rustc --explain E0423`.
diff --git a/tests/ui/resolve/issue-22692.rs b/tests/ui/resolve/issue-22692.rs
deleted file mode 100644
index 31a76261408ef..0000000000000
--- a/tests/ui/resolve/issue-22692.rs
+++ /dev/null
@@ -1,60 +0,0 @@
-fn main() {
-    let _ = String.new();
-    //~^ ERROR expected value, found struct `String`
-    //~| HELP use the path separator
-
-    let _ = String.default;
-    //~^ ERROR expected value, found struct `String`
-    //~| HELP use the path separator
-
-    let _ = Vec::<()>.with_capacity(1);
-    //~^ ERROR expected value, found struct `Vec`
-    //~| HELP use the path separator
-}
-
-macro_rules! Type {
-    () => {
-        ::std::cell::Cell
-        //~^ ERROR expected value, found struct `std::cell::Cell`
-        //~| ERROR expected value, found struct `std::cell::Cell`
-        //~| ERROR expected value, found struct `std::cell::Cell`
-    };
-}
-
-macro_rules! create {
-    (type method) => {
-        Vec.new()
-        //~^ ERROR expected value, found struct `Vec`
-        //~| HELP use the path separator
-    };
-    (type field) => {
-        Vec.new
-        //~^ ERROR expected value, found struct `Vec`
-        //~| HELP use the path separator
-    };
-    (macro method) => {
-        Type!().new(0)
-        //~^ HELP use the path separator
-    };
-}
-
-fn interaction_with_macros() {
-    //
-    // Verify that we do not only suggest to replace `.` with `::` if the receiver is a
-    // macro call but that we also correctly suggest to surround it with angle brackets.
-    //
-
-    Type!().get();
-    //~^ HELP use the path separator
-
-    Type! {}.get;
-    //~^ HELP use the path separator
-
-    //
-    // Ensure that the suggestion is shown for expressions inside of macro definitions.
-    //
-
-    let _ = create!(type method);
-    let _ = create!(type field);
-    let _ = create!(macro method);
-}
diff --git a/tests/ui/resolve/issue-22692.stderr b/tests/ui/resolve/issue-22692.stderr
deleted file mode 100644
index 546f12b35c156..0000000000000
--- a/tests/ui/resolve/issue-22692.stderr
+++ /dev/null
@@ -1,119 +0,0 @@
-error[E0423]: expected value, found struct `String`
-  --> $DIR/issue-22692.rs:2:13
-   |
-LL |     let _ = String.new();
-   |             ^^^^^^
-   |
-help: use the path separator to refer to an item
-   |
-LL -     let _ = String.new();
-LL +     let _ = String::new();
-   |
-
-error[E0423]: expected value, found struct `String`
-  --> $DIR/issue-22692.rs:6:13
-   |
-LL |     let _ = String.default;
-   |             ^^^^^^
-   |
-help: use the path separator to refer to an item
-   |
-LL -     let _ = String.default;
-LL +     let _ = String::default;
-   |
-
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-22692.rs:10:13
-   |
-LL |     let _ = Vec::<()>.with_capacity(1);
-   |             ^^^^^^^^^
-   |
-help: use the path separator to refer to an item
-   |
-LL -     let _ = Vec::<()>.with_capacity(1);
-LL +     let _ = Vec::<()>::with_capacity(1);
-   |
-
-error[E0423]: expected value, found struct `std::cell::Cell`
-  --> $DIR/issue-22692.rs:17:9
-   |
-LL |         ::std::cell::Cell
-   |         ^^^^^^^^^^^^^^^^^
-...
-LL |     Type!().get();
-   |     ------- in this macro invocation
-   |
-   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -     Type!().get();
-LL +     <Type!()>::get();
-   |
-
-error[E0423]: expected value, found struct `std::cell::Cell`
-  --> $DIR/issue-22692.rs:17:9
-   |
-LL |         ::std::cell::Cell
-   |         ^^^^^^^^^^^^^^^^^
-...
-LL |     Type! {}.get;
-   |     -------- in this macro invocation
-   |
-   = note: this error originates in the macro `Type` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -     Type! {}.get;
-LL +     <Type! {}>::get;
-   |
-
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-22692.rs:26:9
-   |
-LL |         Vec.new()
-   |         ^^^
-...
-LL |     let _ = create!(type method);
-   |             -------------------- in this macro invocation
-   |
-   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -         Vec.new()
-LL +         Vec::new()
-   |
-
-error[E0423]: expected value, found struct `Vec`
-  --> $DIR/issue-22692.rs:31:9
-   |
-LL |         Vec.new
-   |         ^^^
-...
-LL |     let _ = create!(type field);
-   |             ------------------- in this macro invocation
-   |
-   = note: this error originates in the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -         Vec.new
-LL +         Vec::new
-   |
-
-error[E0423]: expected value, found struct `std::cell::Cell`
-  --> $DIR/issue-22692.rs:17:9
-   |
-LL |         ::std::cell::Cell
-   |         ^^^^^^^^^^^^^^^^^
-...
-LL |     let _ = create!(macro method);
-   |             --------------------- in this macro invocation
-   |
-   = note: this error originates in the macro `Type` which comes from the expansion of the macro `create` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use the path separator to refer to an item
-   |
-LL -         Type!().new(0)
-LL +         <Type!()>::new(0)
-   |
-
-error: aborting due to 8 previous errors
-
-For more information about this error, try `rustc --explain E0423`.