about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--.github/workflows/ci.yml19
-rw-r--r--compiler/rustc_abi/src/callconv.rs77
-rw-r--r--compiler/rustc_abi/src/callconv/reg.rs63
-rw-r--r--compiler/rustc_abi/src/extern_abi.rs (renamed from compiler/rustc_abi/src/extern_abi/mod.rs)0
-rw-r--r--compiler/rustc_abi/src/layout/ty.rs12
-rw-r--r--compiler/rustc_codegen_llvm/src/llvm/ffi.rs29
-rw-r--r--compiler/rustc_feature/src/accepted.rs5
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs2
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs5
-rw-r--r--compiler/rustc_hir_pretty/src/lib.rs4
-rw-r--r--compiler/rustc_hir_typeck/src/coercion.rs23
-rw-r--r--compiler/rustc_hir_typeck/src/fallback.rs18
-rw-r--r--compiler/rustc_hir_typeck/src/pat.rs78
-rw-r--r--compiler/rustc_lint/src/deref_into_dyn_supertrait.rs25
-rw-r--r--compiler/rustc_lint/src/lib.rs2
-rw-r--r--compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp31
-rw-r--r--compiler/rustc_middle/src/lib.rs2
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs2
-rw-r--r--compiler/rustc_middle/src/ty/typeck_results.rs24
-rw-r--r--compiler/rustc_mir_build/messages.ftl11
-rw-r--r--compiler/rustc_mir_build/src/check_tail_calls.rs51
-rw-r--r--compiler/rustc_mir_build/src/errors.rs60
-rw-r--r--compiler/rustc_mir_build/src/thir/pattern/mod.rs146
-rw-r--r--compiler/rustc_mir_transform/src/validate.rs6
-rw-r--r--compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs2
-rw-r--r--compiler/rustc_parse/src/lexer/unicode_chars.rs2
-rw-r--r--compiler/rustc_target/src/asm/mod.rs2
-rw-r--r--compiler/rustc_target/src/callconv/aarch64.rs3
-rw-r--r--compiler/rustc_target/src/callconv/amdgpu.rs3
-rw-r--r--compiler/rustc_target/src/callconv/arm.rs3
-rw-r--r--compiler/rustc_target/src/callconv/loongarch.rs23
-rw-r--r--compiler/rustc_target/src/callconv/mips.rs3
-rw-r--r--compiler/rustc_target/src/callconv/mips64.rs33
-rw-r--r--compiler/rustc_target/src/callconv/mod.rs20
-rw-r--r--compiler/rustc_target/src/callconv/nvptx64.rs5
-rw-r--r--compiler/rustc_target/src/callconv/powerpc64.rs3
-rw-r--r--compiler/rustc_target/src/callconv/riscv.rs23
-rw-r--r--compiler/rustc_target/src/callconv/s390x.rs3
-rw-r--r--compiler/rustc_target/src/callconv/sparc.rs3
-rw-r--r--compiler/rustc_target/src/callconv/sparc64.rs40
-rw-r--r--compiler/rustc_target/src/callconv/wasm.rs3
-rw-r--r--compiler/rustc_target/src/callconv/x86.rs22
-rw-r--r--compiler/rustc_target/src/callconv/x86_64.rs16
-rw-r--r--compiler/rustc_target/src/callconv/xtensa.rs3
-rw-r--r--compiler/rustc_target/src/lib.rs5
-rw-r--r--compiler/rustc_target/src/spec/base/aix.rs3
-rw-r--r--compiler/rustc_target/src/spec/base/bpf.rs3
-rw-r--r--compiler/rustc_target/src/spec/base/xtensa.rs3
-rw-r--r--compiler/rustc_target/src/spec/mod.rs45
-rw-r--r--compiler/rustc_target/src/target_features.rs18
-rw-r--r--compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs63
-rw-r--r--compiler/rustc_transmute/src/lib.rs32
-rw-r--r--compiler/rustc_type_ir/src/solve/mod.rs4
-rw-r--r--library/alloc/tests/str.rs22
-rw-r--r--library/coretests/tests/bool.rs8
-rw-r--r--library/coretests/tests/lib.rs1
-rw-r--r--library/coretests/tests/ptr.rs6
-rw-r--r--library/std/src/io/cursor.rs4
-rw-r--r--library/std/tests/istr.rs4
-rw-r--r--library/std/tests/seq-compare.rs22
-rw-r--r--src/ci/docker/host-x86_64/dist-various-2/Dockerfile6
-rw-r--r--src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile6
-rwxr-xr-xsrc/ci/docker/scripts/freebsd-toolchain.sh6
-rw-r--r--src/doc/unstable-book/src/language-features/trait-upcasting.md26
-rw-r--r--src/tools/miri/src/lib.rs2
-rw-r--r--src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs3
-rw-r--r--src/tools/miri/tests/pass/binops.rs30
-rw-r--r--src/tools/miri/tests/pass/box-custom-alloc.rs3
-rw-r--r--src/tools/miri/tests/pass/dyn-upcast.rs3
-rwxr-xr-xsrc/tools/publish_toolstate.py19
-rw-r--r--tests/codegen/vtable-upcast.rs1
-rw-r--r--tests/crashes/131886.rs2
-rw-r--r--tests/crashes/134336.rs11
-rw-r--r--tests/ui/binding/expr-match-generic.rs2
-rw-r--r--tests/ui/binding/expr-match.rs13
-rw-r--r--tests/ui/binop/binops.rs30
-rw-r--r--tests/ui/binop/structured-compare.rs14
-rw-r--r--tests/ui/cfg/conditional-compile.rs2
-rw-r--r--tests/ui/codegen/issue-99551.rs1
-rw-r--r--tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs4
-rw-r--r--tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr11
-rw-r--r--tests/ui/dyn-star/upcast.rs2
-rw-r--r--tests/ui/dyn-star/upcast.stderr2
-rw-r--r--tests/ui/explicit-tail-calls/become-trait-fn.rs19
-rw-r--r--tests/ui/explicit-tail-calls/callee_is_track_caller.rs15
-rw-r--r--tests/ui/explicit-tail-calls/caller_is_track_caller.rs16
-rw-r--r--tests/ui/explicit-tail-calls/caller_is_track_caller.stderr14
-rw-r--r--tests/ui/expr/block.rs2
-rw-r--r--tests/ui/expr/if/expr-if.rs18
-rw-r--r--tests/ui/feature-gates/feature-gate-trait_upcasting.rs13
-rw-r--r--tests/ui/feature-gates/feature-gate-trait_upcasting.stderr14
-rw-r--r--tests/ui/for-loop-while/break.rs8
-rw-r--r--tests/ui/for-loop-while/while-cont.rs2
-rw-r--r--tests/ui/for-loop-while/while-loop-constraints-2.rs2
-rw-r--r--tests/ui/generics/generic-tag-match.rs2
-rw-r--r--tests/ui/impl-trait/unsized_coercion5.old.stderr2
-rw-r--r--tests/ui/impl-trait/unsized_coercion5.rs2
-rw-r--r--tests/ui/iterators/iter-range.rs2
-rw-r--r--tests/ui/macros/syntax-extension-source-utils.rs4
-rw-r--r--tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs20
-rw-r--r--tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr26
-rw-r--r--tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr4
-rw-r--r--tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr4
-rw-r--r--tests/ui/numbers-arithmetic/arith-unsigned.rs24
-rw-r--r--tests/ui/numbers-arithmetic/float-nan.rs2
-rw-r--r--tests/ui/numbers-arithmetic/float2.rs10
-rw-r--r--tests/ui/numbers-arithmetic/floatlits.rs8
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.classic2024.stderr48
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.rs33
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.stable2021.stderr6
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr121
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed132
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs130
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr423
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs14
-rw-r--r--tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr77
-rw-r--r--tests/ui/sanitizer/cfi/supertraits.rs1
-rw-r--r--tests/ui/structs-enums/class-impl-very-parameterized-trait.rs2
-rw-r--r--tests/ui/structs-enums/class-implement-trait-cross-crate.rs4
-rw-r--r--tests/ui/structs-enums/class-implement-traits.rs2
-rw-r--r--tests/ui/structs-enums/classes-cross-crate.rs4
-rw-r--r--tests/ui/structs-enums/classes.rs4
-rw-r--r--tests/ui/structs-enums/tag.rs2
-rw-r--r--tests/ui/tail-cps.rs2
-rw-r--r--tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs1
-rw-r--r--tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs1
-rw-r--r--tests/ui/traits/next-solver/upcast-right-substs.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/basic.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs35
-rw-r--r--tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr19
-rw-r--r--tests/ui/traits/trait-upcasting/deref-upcast-shadowing-lint.rs17
-rw-r--r--tests/ui/traits/trait-upcasting/deref-upcast-shadowing-lint.stderr17
-rw-r--r--tests/ui/traits/trait-upcasting/diamond.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/fewer-associated.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs5
-rw-r--r--tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/invalid-upcast.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/invalid-upcast.stderr30
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.current.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.next.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/issue-11515.rs3
-rw-r--r--tests/ui/traits/trait-upcasting/lifetime.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/lifetime.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs6
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny.rs25
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr19
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs4
-rw-r--r--tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr12
-rw-r--r--tests/ui/traits/trait-upcasting/mono-impossible.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs6
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs1
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs6
-rw-r--r--tests/ui/traits/trait-upcasting/normalization.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/prefer-lower-candidates.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/replace-vptr.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/replace-vptr.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/struct.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/subtrait-method.stderr20
-rw-r--r--tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-1.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-2.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-3.stderr4
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-4.stderr12
-rw-r--r--tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs2
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr14
-rw-r--r--tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs2
-rw-r--r--tests/ui/traits/upcast_reorder.rs2
-rw-r--r--tests/ui/traits/upcast_soundness_bug.rs1
-rw-r--r--tests/ui/traits/upcast_soundness_bug.stderr2
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/wrong-adt-assume.rs20
-rw-r--r--tests/ui/transmutability/malformed-program-gracefulness/wrong-adt-assume.stderr11
-rw-r--r--tests/ui/weird-exprs.rs6
-rw-r--r--triagebot.toml20
197 files changed, 1801 insertions, 1249 deletions
diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml
index 7a46d123c5d..0934e42b277 100644
--- a/.github/workflows/ci.yml
+++ b/.github/workflows/ci.yml
@@ -62,9 +62,6 @@ jobs:
     name: ${{ matrix.full_name }}
     needs: [ calculate_matrix ]
     runs-on: "${{ matrix.os }}"
-    defaults:
-      run:
-        shell: ${{ contains(matrix.os, 'windows') && 'msys2 {0}' || 'bash' }}
     timeout-minutes: 360
     env:
       CI_JOB_NAME: ${{ matrix.name }}
@@ -80,22 +77,6 @@ jobs:
         # Check the `calculate_matrix` job to see how is the matrix defined.
         include: ${{ fromJSON(needs.calculate_matrix.outputs.jobs) }}
     steps:
-      - if: contains(matrix.os, 'windows')
-        uses: msys2/setup-msys2@v2.22.0
-        with:
-          # i686 jobs use mingw32. x86_64 and cross-compile jobs use mingw64.
-          msystem: ${{ contains(matrix.name, 'i686') && 'mingw32' || 'mingw64' }}
-          # don't try to download updates for already installed packages
-          update: false
-          # don't try to use the msys that comes built-in to the github runner,
-          # so we can control what is installed (i.e. not python)
-          release: true
-          # Inherit the full path from the Windows environment, with MSYS2's */bin/
-          # dirs placed in front. This lets us run Windows-native Python etc.
-          path-type: inherit
-          install: >
-            make
-
       - name: disable git crlf conversion
         run: git config --global core.autocrlf false
 
diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs
index 400395f99ff..daa365bf6e1 100644
--- a/compiler/rustc_abi/src/callconv.rs
+++ b/compiler/rustc_abi/src/callconv.rs
@@ -1,73 +1,10 @@
-mod abi {
-    pub(crate) use crate::Primitive::*;
-    pub(crate) use crate::Variants;
-}
-
-#[cfg(feature = "nightly")]
-use rustc_macros::HashStable_Generic;
-
-use crate::{Align, HasDataLayout, Size};
 #[cfg(feature = "nightly")]
 use crate::{BackendRepr, FieldsShape, TyAbiInterface, TyAndLayout};
+use crate::{Primitive, Size, Variants};
 
-#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub enum RegKind {
-    Integer,
-    Float,
-    Vector,
-}
-
-#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
-#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
-pub struct Reg {
-    pub kind: RegKind,
-    pub size: Size,
-}
-
-macro_rules! reg_ctor {
-    ($name:ident, $kind:ident, $bits:expr) => {
-        pub fn $name() -> Reg {
-            Reg { kind: RegKind::$kind, size: Size::from_bits($bits) }
-        }
-    };
-}
-
-impl Reg {
-    reg_ctor!(i8, Integer, 8);
-    reg_ctor!(i16, Integer, 16);
-    reg_ctor!(i32, Integer, 32);
-    reg_ctor!(i64, Integer, 64);
-    reg_ctor!(i128, Integer, 128);
-
-    reg_ctor!(f32, Float, 32);
-    reg_ctor!(f64, Float, 64);
-}
+mod reg;
 
-impl Reg {
-    pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
-        let dl = cx.data_layout();
-        match self.kind {
-            RegKind::Integer => match self.size.bits() {
-                1 => dl.i1_align.abi,
-                2..=8 => dl.i8_align.abi,
-                9..=16 => dl.i16_align.abi,
-                17..=32 => dl.i32_align.abi,
-                33..=64 => dl.i64_align.abi,
-                65..=128 => dl.i128_align.abi,
-                _ => panic!("unsupported integer: {self:?}"),
-            },
-            RegKind::Float => match self.size.bits() {
-                16 => dl.f16_align.abi,
-                32 => dl.f32_align.abi,
-                64 => dl.f64_align.abi,
-                128 => dl.f128_align.abi,
-                _ => panic!("unsupported float: {self:?}"),
-            },
-            RegKind::Vector => dl.vector_align(self.size).abi,
-        }
-    }
-}
+pub use reg::{Reg, RegKind};
 
 /// Return value from the `homogeneous_aggregate` test function.
 #[derive(Copy, Clone, Debug)]
@@ -134,8 +71,8 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
             // The primitive for this algorithm.
             BackendRepr::Scalar(scalar) => {
                 let kind = match scalar.primitive() {
-                    abi::Int(..) | abi::Pointer(_) => RegKind::Integer,
-                    abi::Float(_) => RegKind::Float,
+                    Primitive::Int(..) | Primitive::Pointer(_) => RegKind::Integer,
+                    Primitive::Float(_) => RegKind::Float,
                 };
                 Ok(HomogeneousAggregate::Homogeneous(Reg { kind, size: self.size }))
             }
@@ -206,8 +143,8 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
                 let (mut result, mut total) = from_fields_at(*self, Size::ZERO)?;
 
                 match &self.variants {
-                    abi::Variants::Single { .. } | abi::Variants::Empty => {}
-                    abi::Variants::Multiple { variants, .. } => {
+                    Variants::Single { .. } | Variants::Empty => {}
+                    Variants::Multiple { variants, .. } => {
                         // Treat enum variants like union members.
                         // HACK(eddyb) pretend the `enum` field (discriminant)
                         // is at the start of every variant (otherwise the gap
diff --git a/compiler/rustc_abi/src/callconv/reg.rs b/compiler/rustc_abi/src/callconv/reg.rs
new file mode 100644
index 00000000000..66f47c52c15
--- /dev/null
+++ b/compiler/rustc_abi/src/callconv/reg.rs
@@ -0,0 +1,63 @@
+#[cfg(feature = "nightly")]
+use rustc_macros::HashStable_Generic;
+
+use crate::{Align, HasDataLayout, Size};
+
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub enum RegKind {
+    Integer,
+    Float,
+    Vector,
+}
+
+#[cfg_attr(feature = "nightly", derive(HashStable_Generic))]
+#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
+pub struct Reg {
+    pub kind: RegKind,
+    pub size: Size,
+}
+
+macro_rules! reg_ctor {
+    ($name:ident, $kind:ident, $bits:expr) => {
+        pub fn $name() -> Reg {
+            Reg { kind: RegKind::$kind, size: Size::from_bits($bits) }
+        }
+    };
+}
+
+impl Reg {
+    reg_ctor!(i8, Integer, 8);
+    reg_ctor!(i16, Integer, 16);
+    reg_ctor!(i32, Integer, 32);
+    reg_ctor!(i64, Integer, 64);
+    reg_ctor!(i128, Integer, 128);
+
+    reg_ctor!(f32, Float, 32);
+    reg_ctor!(f64, Float, 64);
+}
+
+impl Reg {
+    pub fn align<C: HasDataLayout>(&self, cx: &C) -> Align {
+        let dl = cx.data_layout();
+        match self.kind {
+            RegKind::Integer => match self.size.bits() {
+                1 => dl.i1_align.abi,
+                2..=8 => dl.i8_align.abi,
+                9..=16 => dl.i16_align.abi,
+                17..=32 => dl.i32_align.abi,
+                33..=64 => dl.i64_align.abi,
+                65..=128 => dl.i128_align.abi,
+                _ => panic!("unsupported integer: {self:?}"),
+            },
+            RegKind::Float => match self.size.bits() {
+                16 => dl.f16_align.abi,
+                32 => dl.f32_align.abi,
+                64 => dl.f64_align.abi,
+                128 => dl.f128_align.abi,
+                _ => panic!("unsupported float: {self:?}"),
+            },
+            RegKind::Vector => dl.vector_align(self.size).abi,
+        }
+    }
+}
diff --git a/compiler/rustc_abi/src/extern_abi/mod.rs b/compiler/rustc_abi/src/extern_abi.rs
index 130834d560f..130834d560f 100644
--- a/compiler/rustc_abi/src/extern_abi/mod.rs
+++ b/compiler/rustc_abi/src/extern_abi.rs
diff --git a/compiler/rustc_abi/src/layout/ty.rs b/compiler/rustc_abi/src/layout/ty.rs
index d188750bfe1..221e990ae86 100644
--- a/compiler/rustc_abi/src/layout/ty.rs
+++ b/compiler/rustc_abi/src/layout/ty.rs
@@ -1,13 +1,15 @@
 use std::fmt;
 use std::ops::Deref;
 
-use Float::*;
-use Primitive::*;
 use rustc_data_structures::intern::Interned;
 use rustc_macros::HashStable_Generic;
 
+use crate::{
+    AbiAndPrefAlign, Align, BackendRepr, FieldsShape, Float, HasDataLayout, LayoutData, Niche,
+    PointeeInfo, Primitive, Scalar, Size, TargetDataLayout, Variants,
+};
+
 // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
-use crate::{Float, *};
 
 rustc_index::newtype_index! {
     /// The *source-order* index of a field in a variant.
@@ -197,7 +199,9 @@ impl<'a, Ty> TyAndLayout<'a, Ty> {
         C: HasDataLayout,
     {
         match self.backend_repr {
-            BackendRepr::Scalar(scalar) => matches!(scalar.primitive(), Float(F32 | F64)),
+            BackendRepr::Scalar(scalar) => {
+                matches!(scalar.primitive(), Primitive::Float(Float::F32 | Float::F64))
+            }
             BackendRepr::Memory { .. } => {
                 if self.fields.count() == 1 && self.fields.offset(0).bytes() == 0 {
                     self.field(cx, 0).is_single_fp_element(cx)
diff --git a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
index 0d04f770bc6..50a40c9c309 100644
--- a/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
+++ b/compiler/rustc_codegen_llvm/src/llvm/ffi.rs
@@ -69,19 +69,6 @@ pub enum LLVMRustResult {
     Failure,
 }
 
-/// Translation of LLVM's MachineTypes enum, defined in llvm\include\llvm\BinaryFormat\COFF.h.
-///
-/// We include only architectures supported on Windows.
-#[derive(Copy, Clone, PartialEq)]
-#[repr(C)]
-pub enum LLVMMachineType {
-    AMD64 = 0x8664,
-    I386 = 0x14c,
-    ARM64 = 0xaa64,
-    ARM64EC = 0xa641,
-    ARM = 0x01c0,
-}
-
 /// Must match the layout of `LLVMRustModuleFlagMergeBehavior`.
 ///
 /// When merging modules (e.g. during LTO), their metadata flags are combined. Conflicts are
@@ -645,16 +632,6 @@ pub enum ThreadLocalMode {
     LocalExec,
 }
 
-/// LLVMRustTailCallKind
-#[derive(Copy, Clone)]
-#[repr(C)]
-pub enum TailCallKind {
-    None,
-    Tail,
-    MustTail,
-    NoTail,
-}
-
 /// LLVMRustChecksumKind
 #[derive(Copy, Clone)]
 #[repr(C)]
@@ -773,7 +750,6 @@ pub struct Builder<'a>(InvariantOpaque<'a>);
 #[repr(C)]
 pub struct PassManager<'a>(InvariantOpaque<'a>);
 unsafe extern "C" {
-    pub type Pass;
     pub type TargetMachine;
     pub type Archive;
 }
@@ -799,7 +775,6 @@ unsafe extern "C" {
 }
 
 pub type DiagnosticHandlerTy = unsafe extern "C" fn(&DiagnosticInfo, *mut c_void);
-pub type InlineAsmDiagHandlerTy = unsafe extern "C" fn(&SMDiagnostic, *const c_void, c_uint);
 
 pub mod debuginfo {
     use std::ptr;
@@ -853,7 +828,6 @@ pub mod debuginfo {
     pub type DIFile = DIScope;
     pub type DILexicalBlock = DIScope;
     pub type DISubprogram = DIScope;
-    pub type DINameSpace = DIScope;
     pub type DIType = DIDescriptor;
     pub type DIBasicType = DIType;
     pub type DIDerivedType = DIType;
@@ -1809,7 +1783,6 @@ unsafe extern "C" {
         Name: *const c_char,
         NameLen: size_t,
     ) -> Option<&Value>;
-    pub fn LLVMRustSetTailCallKind(CallInst: &Value, TKC: TailCallKind);
 
     // Operations on attributes
     pub fn LLVMRustCreateAttrNoValue(C: &Context, attr: AttributeKind) -> &Attribute;
@@ -2586,8 +2559,6 @@ unsafe extern "C" {
 
     pub fn LLVMRustGetElementTypeArgIndex(CallSite: &Value) -> i32;
 
-    pub fn LLVMRustIsBitcode(ptr: *const u8, len: usize) -> bool;
-
     pub fn LLVMRustLLVMHasZlibCompressionForDebugSymbols() -> bool;
 
     pub fn LLVMRustLLVMHasZstdCompressionForDebugSymbols() -> bool;
diff --git a/compiler/rustc_feature/src/accepted.rs b/compiler/rustc_feature/src/accepted.rs
index 217a7aeb2d7..822cf4982b5 100644
--- a/compiler/rustc_feature/src/accepted.rs
+++ b/compiler/rustc_feature/src/accepted.rs
@@ -9,7 +9,7 @@ macro_rules! declare_features {
         $(#[doc = $doc:tt])* (accepted, $feature:ident, $ver:expr, $issue:expr),
     )+) => {
         /// Formerly unstable features that have now been accepted (stabilized).
-        pub const ACCEPTED_LANG_FEATURES: &[Feature] = &[
+        pub static ACCEPTED_LANG_FEATURES: &[Feature] = &[
             $(Feature {
                 name: sym::$feature,
                 since: $ver,
@@ -400,6 +400,9 @@ declare_features! (
     /// Allows `#[track_caller]` to be used which provides
     /// accurate caller location reporting during panic (RFC 2091).
     (accepted, track_caller, "1.46.0", Some(47809)),
+    /// Allows dyn upcasting trait objects via supertraits.
+    /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
+    (accepted, trait_upcasting, "CURRENT_RUSTC_VERSION", Some(65991)),
     /// Allows #[repr(transparent)] on univariant enums (RFC 2645).
     (accepted, transparent_enums, "1.42.0", Some(60405)),
     /// Allows indexing tuples.
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index 67eb96e4d56..eb5fac96af2 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -318,7 +318,7 @@ pub struct BuiltinAttribute {
 
 /// Attributes that have a special meaning to rustc or rustdoc.
 #[rustfmt::skip]
-pub const BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
+pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     // ==========================================================================
     // Stable attributes:
     // ==========================================================================
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 081638715df..2fb0c8e4344 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -14,7 +14,7 @@ macro_rules! declare_features {
         $(#[doc = $doc:tt])* (removed, $feature:ident, $ver:expr, $issue:expr, $reason:expr),
     )+) => {
         /// Formerly unstable features that have now been removed.
-        pub const REMOVED_LANG_FEATURES: &[RemovedFeature] = &[
+        pub static REMOVED_LANG_FEATURES: &[RemovedFeature] = &[
             $(RemovedFeature {
                 feature: Feature {
                     name: sym::$feature,
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index af3570ae77a..a4c5e4800eb 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -104,7 +104,7 @@ macro_rules! declare_features {
     )+) => {
         /// Unstable language features that are being implemented or being
         /// considered for acceptance (stabilization) or removal.
-        pub const UNSTABLE_LANG_FEATURES: &[Feature] = &[
+        pub static UNSTABLE_LANG_FEATURES: &[Feature] = &[
             $(Feature {
                 name: sym::$feature,
                 since: $ver,
@@ -636,9 +636,6 @@ declare_features! (
     (unstable, thread_local, "1.0.0", Some(29594)),
     /// Allows defining `trait X = A + B;` alias items.
     (unstable, trait_alias, "1.24.0", Some(41517)),
-    /// Allows dyn upcasting trait objects via supertraits.
-    /// Dyn upcasting is casting, e.g., `dyn Foo -> dyn Bar` where `Foo: Bar`.
-    (unstable, trait_upcasting, "1.56.0", Some(65991)),
     /// Allows for transmuting between arrays with sizes that contain generic consts.
     (unstable, transmute_generic_consts, "1.70.0", Some(109929)),
     /// Allows #[repr(transparent)] on unions (RFC 2645).
diff --git a/compiler/rustc_hir_pretty/src/lib.rs b/compiler/rustc_hir_pretty/src/lib.rs
index 8efef0c612b..fb1df518a88 100644
--- a/compiler/rustc_hir_pretty/src/lib.rs
+++ b/compiler/rustc_hir_pretty/src/lib.rs
@@ -325,6 +325,10 @@ pub fn expr_to_string(ann: &dyn PpAnn, pat: &hir::Expr<'_>) -> String {
     to_string(ann, |s| s.print_expr(pat))
 }
 
+pub fn item_to_string(ann: &dyn PpAnn, pat: &hir::Item<'_>) -> String {
+    to_string(ann, |s| s.print_item(pat))
+}
+
 impl<'a> State<'a> {
     fn bclose_maybe_open(&mut self, span: rustc_span::Span, close_box: bool) {
         self.maybe_print_comment(span.hi());
diff --git a/compiler/rustc_hir_typeck/src/coercion.rs b/compiler/rustc_hir_typeck/src/coercion.rs
index 83acc7dd6af..56cc9b6d551 100644
--- a/compiler/rustc_hir_typeck/src/coercion.rs
+++ b/compiler/rustc_hir_typeck/src/coercion.rs
@@ -605,7 +605,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         )];
 
         let mut has_unsized_tuple_coercion = false;
-        let mut has_trait_upcasting_coercion = None;
 
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -690,13 +689,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                     // these here and emit a feature error if coercion doesn't fail
                     // due to another reason.
                     match impl_source {
-                        traits::ImplSource::Builtin(
-                            BuiltinImplSource::TraitUpcasting { .. },
-                            _,
-                        ) => {
-                            has_trait_upcasting_coercion =
-                                Some((trait_pred.self_ty(), trait_pred.trait_ref.args.type_at(1)));
-                        }
                         traits::ImplSource::Builtin(BuiltinImplSource::TupleUnsizing, _) => {
                             has_unsized_tuple_coercion = true;
                         }
@@ -707,21 +699,6 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             }
         }
 
-        if let Some((sub, sup)) = has_trait_upcasting_coercion
-            && !self.tcx().features().trait_upcasting()
-        {
-            // Renders better when we erase regions, since they're not really the point here.
-            let (sub, sup) = self.tcx.erase_regions((sub, sup));
-            let mut err = feature_err(
-                &self.tcx.sess,
-                sym::trait_upcasting,
-                self.cause.span,
-                format!("cannot cast `{sub}` to `{sup}`, trait upcasting coercion is experimental"),
-            );
-            err.note(format!("required when coercing `{source}` into `{target}`"));
-            err.emit();
-        }
-
         if has_unsized_tuple_coercion && !self.tcx.features().unsized_tuple_coercion() {
             feature_err(
                 &self.tcx.sess,
diff --git a/compiler/rustc_hir_typeck/src/fallback.rs b/compiler/rustc_hir_typeck/src/fallback.rs
index 1f3f03b9929..4618c5d3849 100644
--- a/compiler/rustc_hir_typeck/src/fallback.rs
+++ b/compiler/rustc_hir_typeck/src/fallback.rs
@@ -651,6 +651,7 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
         if let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(inf_id)
             && let Some(vid) = self.fcx.root_vid(ty)
             && self.reachable_vids.contains(&vid)
+            && inf_span.can_be_used_for_suggestions()
         {
             return ControlFlow::Break(errors::SuggestAnnotation::Unit(inf_span));
         }
@@ -662,7 +663,7 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
         &mut self,
         qpath: &'tcx rustc_hir::QPath<'tcx>,
         id: HirId,
-        _span: Span,
+        span: Span,
     ) -> Self::Result {
         let arg_segment = match qpath {
             hir::QPath::Resolved(_, path) => {
@@ -674,13 +675,21 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
             }
         };
         // Alternatively, try to turbofish `::<_, (), _>`.
-        if let Some(def_id) = self.fcx.typeck_results.borrow().qpath_res(qpath, id).opt_def_id() {
+        if let Some(def_id) = self.fcx.typeck_results.borrow().qpath_res(qpath, id).opt_def_id()
+            && span.can_be_used_for_suggestions()
+        {
             self.suggest_for_segment(arg_segment, def_id, id)?;
         }
         hir::intravisit::walk_qpath(self, qpath, id)
     }
 
     fn visit_expr(&mut self, expr: &'tcx hir::Expr<'tcx>) -> Self::Result {
+        if let hir::ExprKind::Closure(&hir::Closure { body, .. })
+        | hir::ExprKind::ConstBlock(hir::ConstBlock { body, .. }) = expr.kind
+        {
+            self.visit_body(self.fcx.tcx.hir().body(body))?;
+        }
+
         // Try to suggest adding an explicit qself `()` to a trait method path.
         // i.e. changing `Default::default()` to `<() as Default>::default()`.
         if let hir::ExprKind::Path(hir::QPath::Resolved(None, path)) = expr.kind
@@ -691,17 +700,21 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
             && let Some(vid) = self.fcx.root_vid(self_ty)
             && self.reachable_vids.contains(&vid)
             && let [.., trait_segment, _method_segment] = path.segments
+            && expr.span.can_be_used_for_suggestions()
         {
             let span = path.span.shrink_to_lo().to(trait_segment.ident.span);
             return ControlFlow::Break(errors::SuggestAnnotation::Path(span));
         }
+
         // Or else, try suggesting turbofishing the method args.
         if let hir::ExprKind::MethodCall(segment, ..) = expr.kind
             && let Some(def_id) =
                 self.fcx.typeck_results.borrow().type_dependent_def_id(expr.hir_id)
+            && expr.span.can_be_used_for_suggestions()
         {
             self.suggest_for_segment(segment, def_id, expr.hir_id)?;
         }
+
         hir::intravisit::walk_expr(self, expr)
     }
 
@@ -712,6 +725,7 @@ impl<'tcx> Visitor<'tcx> for AnnotateUnitFallbackVisitor<'_, 'tcx> {
             && let Some(ty) = self.fcx.typeck_results.borrow().node_type_opt(local.hir_id)
             && let Some(vid) = self.fcx.root_vid(ty)
             && self.reachable_vids.contains(&vid)
+            && local.span.can_be_used_for_suggestions()
         {
             return ControlFlow::Break(errors::SuggestAnnotation::Local(
                 local.pat.span.shrink_to_hi(),
diff --git a/compiler/rustc_hir_typeck/src/pat.rs b/compiler/rustc_hir_typeck/src/pat.rs
index 2e7415cec5d..7c2a2b3fdf7 100644
--- a/compiler/rustc_hir_typeck/src/pat.rs
+++ b/compiler/rustc_hir_typeck/src/pat.rs
@@ -812,7 +812,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
         // Determine the binding mode...
         let bm = match user_bind_annot {
-            BindingMode(ByRef::No, Mutability::Mut) if matches!(def_br, ByRef::Yes(_)) => {
+            BindingMode(ByRef::No, Mutability::Mut) if let ByRef::Yes(def_br_mutbl) = def_br => {
                 // Only mention the experimental `mut_ref` feature if if we're in edition 2024 and
                 // using other experimental matching features compatible with it.
                 if pat.span.at_least_rust_2024()
@@ -834,22 +834,22 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     // `mut` resets the binding mode on edition <= 2021
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
-                        pat.span,
+                        pat,
                         ident.span,
-                        "requires binding by-value, but the implicit default is by-reference",
+                        def_br_mutbl,
                     );
                     BindingMode(ByRef::No, Mutability::Mut)
                 }
             }
             BindingMode(ByRef::No, mutbl) => BindingMode(def_br, mutbl),
             BindingMode(ByRef::Yes(_), _) => {
-                if matches!(def_br, ByRef::Yes(_)) {
+                if let ByRef::Yes(def_br_mutbl) = def_br {
                     // `ref`/`ref mut` overrides the binding mode on edition <= 2021
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
-                        pat.span,
+                        pat,
                         ident.span,
-                        "cannot override to bind by-reference when that is the implicit default",
+                        def_br_mutbl,
                     );
                 }
                 user_bind_annot
@@ -2386,9 +2386,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     pat_info.binding_mode = ByRef::No;
                     self.add_rust_2024_migration_desugared_pat(
                         pat_info.top_info.hir_id,
-                        pat.span,
+                        pat,
                         inner.span,
-                        "cannot implicitly match against multiple layers of reference",
+                        inh_mut,
                     )
                 }
             }
@@ -2778,33 +2778,65 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn add_rust_2024_migration_desugared_pat(
         &self,
         pat_id: HirId,
-        subpat_span: Span,
+        subpat: &'tcx Pat<'tcx>,
         cutoff_span: Span,
-        detailed_label: &str,
+        def_br_mutbl: Mutability,
     ) {
         // Try to trim the span we're labeling to just the `&` or binding mode that's an issue.
         // If the subpattern's span is is from an expansion, the emitted label will not be trimmed.
         let source_map = self.tcx.sess.source_map();
         let cutoff_span = source_map
-            .span_extend_prev_while(cutoff_span, char::is_whitespace)
+            .span_extend_prev_while(cutoff_span, |c| c.is_whitespace() || c == '(')
             .unwrap_or(cutoff_span);
-        // Ensure we use the syntax context and thus edition of `subpat_span`; this will be a hard
+        // Ensure we use the syntax context and thus edition of `subpat.span`; this will be a hard
         // error if the subpattern is of edition >= 2024.
-        let trimmed_span = subpat_span.until(cutoff_span).with_ctxt(subpat_span.ctxt());
+        let trimmed_span = subpat.span.until(cutoff_span).with_ctxt(subpat.span.ctxt());
+
+        let mut typeck_results = self.typeck_results.borrow_mut();
+        let mut table = typeck_results.rust_2024_migration_desugared_pats_mut();
+        // FIXME(ref_pat_eat_one_layer_2024): The migration diagnostic doesn't know how to track the
+        // default binding mode in the presence of Rule 3 or Rule 5. As a consequence, the labels it
+        // gives for default binding modes are wrong, as well as suggestions based on the default
+        // binding mode. This keeps it from making those suggestions, as doing so could panic.
+        let info = table.entry(pat_id).or_insert_with(|| ty::Rust2024IncompatiblePatInfo {
+            primary_labels: Vec::new(),
+            bad_modifiers: false,
+            bad_ref_pats: false,
+            suggest_eliding_modes: !self.tcx.features().ref_pat_eat_one_layer_2024()
+                && !self.tcx.features().ref_pat_eat_one_layer_2024_structural(),
+        });
 
         // Only provide a detailed label if the problematic subpattern isn't from an expansion.
         // In the case that it's from a macro, we'll add a more detailed note in the emitter.
-        let desc = if subpat_span.from_expansion() {
-            "default binding mode is reset within expansion"
+        let from_expansion = subpat.span.from_expansion();
+        let primary_label = if from_expansion {
+            // NB: This wording assumes the only expansions that can produce problematic reference
+            // patterns and bindings are macros. If a desugaring or AST pass is added that can do
+            // so, we may want to inspect the span's source callee or macro backtrace.
+            "occurs within macro expansion".to_owned()
         } else {
-            detailed_label
+            let pat_kind = if let PatKind::Binding(user_bind_annot, _, _, _) = subpat.kind {
+                info.bad_modifiers |= true;
+                // If the user-provided binding modifier doesn't match the default binding mode, we'll
+                // need to suggest reference patterns, which can affect other bindings.
+                // For simplicity, we opt to suggest making the pattern fully explicit.
+                info.suggest_eliding_modes &=
+                    user_bind_annot == BindingMode(ByRef::Yes(def_br_mutbl), Mutability::Not);
+                "binding modifier"
+            } else {
+                info.bad_ref_pats |= true;
+                // For simplicity, we don't try to suggest eliding reference patterns. Thus, we'll
+                // suggest adding them instead, which can affect the types assigned to bindings.
+                // As such, we opt to suggest making the pattern fully explicit.
+                info.suggest_eliding_modes = false;
+                "reference pattern"
+            };
+            let dbm_str = match def_br_mutbl {
+                Mutability::Not => "ref",
+                Mutability::Mut => "ref mut",
+            };
+            format!("{pat_kind} not allowed under `{dbm_str}` default binding mode")
         };
-
-        self.typeck_results
-            .borrow_mut()
-            .rust_2024_migration_desugared_pats_mut()
-            .entry(pat_id)
-            .or_default()
-            .push((trimmed_span, desc.to_owned()));
+        info.primary_labels.push((trimmed_span, primary_label));
     }
 }
diff --git a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
index 657642e093c..181f44fb4de 100644
--- a/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
+++ b/compiler/rustc_lint/src/deref_into_dyn_supertrait.rs
@@ -1,6 +1,5 @@
 use rustc_hir::{self as hir, LangItem};
 use rustc_middle::ty;
-use rustc_session::lint::FutureIncompatibilityReason;
 use rustc_session::{declare_lint, declare_lint_pass};
 use rustc_span::sym;
 use rustc_trait_selection::traits::supertraits;
@@ -9,11 +8,12 @@ use crate::lints::{SupertraitAsDerefTarget, SupertraitAsDerefTargetLabel};
 use crate::{LateContext, LateLintPass, LintContext};
 
 declare_lint! {
-    /// The `deref_into_dyn_supertrait` lint is output whenever there is a use of the
-    /// `Deref` implementation with a `dyn SuperTrait` type as `Output`.
+    /// The `deref_into_dyn_supertrait` lint is emitted whenever there is a `Deref` implementation
+    /// for `dyn SubTrait` with a `dyn SuperTrait` type as the `Output` type.
     ///
-    /// These implementations will become shadowed when the `trait_upcasting` feature is stabilized.
-    /// The `deref` functions will no longer be called implicitly, so there might be behavior change.
+    /// These implementations are "shadowed" by trait upcasting (stabilized since
+    /// CURRENT_RUSTC_VERSION). The `deref` functions is no longer called implicitly, which might
+    /// change behavior compared to previous rustc versions.
     ///
     /// ### Example
     ///
@@ -43,15 +43,14 @@ declare_lint! {
     ///
     /// ### Explanation
     ///
-    /// The dyn upcasting coercion feature adds new coercion rules, taking priority
-    /// over certain other coercion rules, which will cause some behavior change.
+    /// The trait upcasting coercion added a new coercion rule, taking priority over certain other
+    /// coercion rules, which causes some behavior change compared to older `rustc` versions.
+    ///
+    /// `deref` can be still called explicitly, it just isn't called as part of a deref coercion
+    /// (since trait upcasting coercion takes priority).
     pub DEREF_INTO_DYN_SUPERTRAIT,
-    Warn,
-    "`Deref` implementation usage with a supertrait trait object for output might be shadowed in the future",
-    @future_incompatible = FutureIncompatibleInfo {
-        reason: FutureIncompatibilityReason::FutureReleaseSemanticsChange,
-        reference: "issue #89460 <https://github.com/rust-lang/rust/issues/89460>",
-    };
+    Allow,
+    "`Deref` implementation with a supertrait trait object for output is shadowed by trait upcasting",
 }
 
 declare_lint_pass!(DerefIntoDynSupertrait => [DEREF_INTO_DYN_SUPERTRAIT]);
diff --git a/compiler/rustc_lint/src/lib.rs b/compiler/rustc_lint/src/lib.rs
index fd6c17735c5..3e97f4c86ba 100644
--- a/compiler/rustc_lint/src/lib.rs
+++ b/compiler/rustc_lint/src/lib.rs
@@ -21,6 +21,7 @@
 
 // tidy-alphabetical-start
 #![allow(internal_features)]
+#![cfg_attr(bootstrap, feature(trait_upcasting))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(array_windows)]
@@ -32,7 +33,6 @@
 #![feature(let_chains)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
-#![feature(trait_upcasting)]
 #![warn(unreachable_pub)]
 // tidy-alphabetical-end
 
diff --git a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
index 76ad7fc8909..b8cef6a7e25 100644
--- a/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
+++ b/compiler/rustc_llvm/llvm-wrapper/RustWrapper.cpp
@@ -195,33 +195,6 @@ LLVMRustVerifyFunction(LLVMValueRef Fn, LLVMRustVerifierFailureAction Action) {
   return LLVMVerifyFunction(Fn, fromRust(Action));
 }
 
-enum class LLVMRustTailCallKind {
-  None,
-  Tail,
-  MustTail,
-  NoTail,
-};
-
-static CallInst::TailCallKind fromRust(LLVMRustTailCallKind Kind) {
-  switch (Kind) {
-  case LLVMRustTailCallKind::None:
-    return CallInst::TailCallKind::TCK_None;
-  case LLVMRustTailCallKind::Tail:
-    return CallInst::TailCallKind::TCK_Tail;
-  case LLVMRustTailCallKind::MustTail:
-    return CallInst::TailCallKind::TCK_MustTail;
-  case LLVMRustTailCallKind::NoTail:
-    return CallInst::TailCallKind::TCK_NoTail;
-  default:
-    report_fatal_error("bad CallInst::TailCallKind.");
-  }
-}
-
-extern "C" void LLVMRustSetTailCallKind(LLVMValueRef Call,
-                                        LLVMRustTailCallKind TCK) {
-  unwrap<CallInst>(Call)->setTailCallKind(fromRust(TCK));
-}
-
 extern "C" LLVMValueRef LLVMRustGetOrInsertFunction(LLVMModuleRef M,
                                                     const char *Name,
                                                     size_t NameLen,
@@ -1976,10 +1949,6 @@ extern "C" int32_t LLVMRustGetElementTypeArgIndex(LLVMValueRef CallSite) {
   return -1;
 }
 
-extern "C" bool LLVMRustIsBitcode(char *ptr, size_t len) {
-  return identify_magic(StringRef(ptr, len)) == file_magic::bitcode;
-}
-
 extern "C" bool LLVMRustIsNonGVFunctionPointerTy(LLVMValueRef V) {
   if (unwrap<Value>(V)->getType()->isPointerTy()) {
     if (auto *GV = dyn_cast<GlobalValue>(unwrap<Value>(V))) {
diff --git a/compiler/rustc_middle/src/lib.rs b/compiler/rustc_middle/src/lib.rs
index 7a6d329fd47..95128a5d903 100644
--- a/compiler/rustc_middle/src/lib.rs
+++ b/compiler/rustc_middle/src/lib.rs
@@ -29,6 +29,7 @@
 #![allow(rustc::diagnostic_outside_of_impl)]
 #![allow(rustc::potential_query_instability)]
 #![allow(rustc::untranslatable_diagnostic)]
+#![cfg_attr(bootstrap, feature(trait_upcasting))]
 #![doc(html_root_url = "https://doc.rust-lang.org/nightly/nightly-rustc/")]
 #![doc(rust_logo)]
 #![feature(allocator_api)]
@@ -56,7 +57,6 @@
 #![feature(ptr_alignment_type)]
 #![feature(rustc_attrs)]
 #![feature(rustdoc_internals)]
-#![feature(trait_upcasting)]
 #![feature(trusted_len)]
 #![feature(try_blocks)]
 #![feature(try_trait_v2)]
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index 88eea6101b5..6fe1502c66d 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -94,7 +94,7 @@ pub use self::sty::{
 pub use self::trait_def::TraitDef;
 pub use self::typeck_results::{
     CanonicalUserType, CanonicalUserTypeAnnotation, CanonicalUserTypeAnnotations, IsIdentity,
-    TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind,
+    Rust2024IncompatiblePatInfo, TypeckResults, UserType, UserTypeAnnotationIndex, UserTypeKind,
 };
 pub use self::visit::{TypeSuperVisitable, TypeVisitable, TypeVisitableExt, TypeVisitor};
 use crate::error::{OpaqueHiddenTypeMismatch, TypeMismatchReason};
diff --git a/compiler/rustc_middle/src/ty/typeck_results.rs b/compiler/rustc_middle/src/ty/typeck_results.rs
index 3c6ed997845..49bdb5e9dc3 100644
--- a/compiler/rustc_middle/src/ty/typeck_results.rs
+++ b/compiler/rustc_middle/src/ty/typeck_results.rs
@@ -73,9 +73,9 @@ pub struct TypeckResults<'tcx> {
     /// Stores the actual binding mode for all instances of [`BindingMode`].
     pat_binding_modes: ItemLocalMap<BindingMode>,
 
-    /// Top-level patterns whose match ergonomics need to be desugared by the Rust 2021 -> 2024
-    /// migration lint. Problematic subpatterns are stored in the `Vec` for the lint to highlight.
-    rust_2024_migration_desugared_pats: ItemLocalMap<Vec<(Span, String)>>,
+    /// Top-level patterns incompatible with Rust 2024's match ergonomics. These will be translated
+    /// to a form valid in all Editions, either as a lint diagnostic or hard error.
+    rust_2024_migration_desugared_pats: ItemLocalMap<Rust2024IncompatiblePatInfo>,
 
     /// Stores the types which were implicitly dereferenced in pattern binding modes
     /// for later usage in THIR lowering. For example,
@@ -420,7 +420,7 @@ impl<'tcx> TypeckResults<'tcx> {
 
     pub fn rust_2024_migration_desugared_pats(
         &self,
-    ) -> LocalTableInContext<'_, Vec<(Span, String)>> {
+    ) -> LocalTableInContext<'_, Rust2024IncompatiblePatInfo> {
         LocalTableInContext {
             hir_owner: self.hir_owner,
             data: &self.rust_2024_migration_desugared_pats,
@@ -429,7 +429,7 @@ impl<'tcx> TypeckResults<'tcx> {
 
     pub fn rust_2024_migration_desugared_pats_mut(
         &mut self,
-    ) -> LocalTableInContextMut<'_, Vec<(Span, String)>> {
+    ) -> LocalTableInContextMut<'_, Rust2024IncompatiblePatInfo> {
         LocalTableInContextMut {
             hir_owner: self.hir_owner,
             data: &mut self.rust_2024_migration_desugared_pats,
@@ -811,3 +811,17 @@ impl<'tcx> std::fmt::Display for UserTypeKind<'tcx> {
         }
     }
 }
+
+/// Information on a pattern incompatible with Rust 2024, for use by the error/migration diagnostic
+/// emitted during THIR construction.
+#[derive(TyEncodable, TyDecodable, Debug, HashStable)]
+pub struct Rust2024IncompatiblePatInfo {
+    /// Labeled spans for `&`s, `&mut`s, and binding modifiers incompatible with Rust 2024.
+    pub primary_labels: Vec<(Span, String)>,
+    /// Whether any binding modifiers occur under a non-`move` default binding mode.
+    pub bad_modifiers: bool,
+    /// Whether any `&` or `&mut` patterns occur under a non-`move` default binding mode.
+    pub bad_ref_pats: bool,
+    /// If `true`, we can give a simpler suggestion solely by eliding explicit binding modifiers.
+    pub suggest_eliding_modes: bool,
+}
diff --git a/compiler/rustc_mir_build/messages.ftl b/compiler/rustc_mir_build/messages.ftl
index 3cf3c332893..fae159103e7 100644
--- a/compiler/rustc_mir_build/messages.ftl
+++ b/compiler/rustc_mir_build/messages.ftl
@@ -285,7 +285,16 @@ mir_build_pointer_pattern = function pointers and raw pointers not derived from
 
 mir_build_privately_uninhabited = pattern `{$witness_1}` is currently uninhabited, but this variant contains private fields which may become inhabited in the future
 
-mir_build_rust_2024_incompatible_pat = this pattern relies on behavior which may change in edition 2024
+mir_build_rust_2024_incompatible_pat = {$bad_modifiers ->
+        *[true] binding modifiers{$bad_ref_pats ->
+            *[true] {" "}and reference patterns
+            [false] {""}
+        }
+        [false] reference patterns
+    } may only be written when the default binding mode is `move`{$is_hard_error ->
+        *[true] {""}
+        [false] {" "}in Rust 2024
+    }
 
 mir_build_static_in_pattern = statics cannot be referenced in patterns
     .label = can't be used in patterns
diff --git a/compiler/rustc_mir_build/src/check_tail_calls.rs b/compiler/rustc_mir_build/src/check_tail_calls.rs
index 921205428db..18db8c1debb 100644
--- a/compiler/rustc_mir_build/src/check_tail_calls.rs
+++ b/compiler/rustc_mir_build/src/check_tail_calls.rs
@@ -132,11 +132,24 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
         }
 
         {
+            // `#[track_caller]` affects the ABI of a function (by adding a location argument),
+            // so a `track_caller` can only tail call other `track_caller` functions.
+            //
+            // The issue is however that we can't know if a function is `track_caller` or not at
+            // this point (THIR can be polymorphic, we may have an unresolved trait function).
+            // We could only allow functions that we *can* resolve and *are* `track_caller`,
+            // but that would turn changing `track_caller`-ness into a breaking change,
+            // which is probably undesirable.
+            //
+            // Also note that we don't check callee's `track_caller`-ness at all, mostly for the
+            // reasons above, but also because we can always tailcall the shim we'd generate for
+            // coercing the function to an `fn()` pointer. (although in that case the tailcall is
+            // basically useless -- the shim calls the actual function, so tailcalling the shim is
+            // equivalent to calling the function)
             let caller_needs_location = self.needs_location(self.caller_ty);
-            let callee_needs_location = self.needs_location(ty);
 
-            if caller_needs_location != callee_needs_location {
-                self.report_track_caller_mismatch(expr.span, caller_needs_location);
+            if caller_needs_location {
+                self.report_track_caller_caller(expr.span);
             }
         }
 
@@ -150,7 +163,9 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
     }
 
     /// Returns true if function of type `ty` needs location argument
-    /// (i.e. if a function is marked as `#[track_caller]`)
+    /// (i.e. if a function is marked as `#[track_caller]`).
+    ///
+    /// Panics if the function's instance can't be immediately resolved.
     fn needs_location(&self, ty: Ty<'tcx>) -> bool {
         if let &ty::FnDef(did, substs) = ty.kind() {
             let instance =
@@ -293,25 +308,15 @@ impl<'tcx> TailCallCkVisitor<'_, 'tcx> {
         self.found_errors = Err(err);
     }
 
-    fn report_track_caller_mismatch(&mut self, sp: Span, caller_needs_location: bool) {
-        let err = match caller_needs_location {
-            true => self
-                .tcx
-                .dcx()
-                .struct_span_err(
-                    sp,
-                    "a function marked with `#[track_caller]` cannot tail-call one that is not",
-                )
-                .emit(),
-            false => self
-                .tcx
-                .dcx()
-                .struct_span_err(
-                    sp,
-                    "a function mot marked with `#[track_caller]` cannot tail-call one that is",
-                )
-                .emit(),
-        };
+    fn report_track_caller_caller(&mut self, sp: Span) {
+        let err = self
+            .tcx
+            .dcx()
+            .struct_span_err(
+                sp,
+                "a function marked with `#[track_caller]` cannot perform a tail-call",
+            )
+            .emit();
 
         self.found_errors = Err(err);
     }
diff --git a/compiler/rustc_mir_build/src/errors.rs b/compiler/rustc_mir_build/src/errors.rs
index af6f33d9cdd..07bdc59756a 100644
--- a/compiler/rustc_mir_build/src/errors.rs
+++ b/compiler/rustc_mir_build/src/errors.rs
@@ -1,3 +1,4 @@
+use rustc_data_structures::fx::FxIndexMap;
 use rustc_errors::codes::*;
 use rustc_errors::{
     Applicability, Diag, DiagArgValue, DiagCtxtHandle, Diagnostic, EmissionGuarantee, Level,
@@ -1097,41 +1098,70 @@ pub(crate) enum MiscPatternSuggestion {
 
 #[derive(LintDiagnostic)]
 #[diag(mir_build_rust_2024_incompatible_pat)]
-pub(crate) struct Rust2024IncompatiblePat<'a> {
+pub(crate) struct Rust2024IncompatiblePat {
     #[subdiagnostic]
-    pub(crate) sugg: Rust2024IncompatiblePatSugg<'a>,
+    pub(crate) sugg: Rust2024IncompatiblePatSugg,
+    pub(crate) bad_modifiers: bool,
+    pub(crate) bad_ref_pats: bool,
+    pub(crate) is_hard_error: bool,
 }
 
-pub(crate) struct Rust2024IncompatiblePatSugg<'a> {
+pub(crate) struct Rust2024IncompatiblePatSugg {
+    /// If true, our suggestion is to elide explicit binding modifiers.
+    /// If false, our suggestion is to make the pattern fully explicit.
+    pub(crate) suggest_eliding_modes: bool,
     pub(crate) suggestion: Vec<(Span, String)>,
     pub(crate) ref_pattern_count: usize,
     pub(crate) binding_mode_count: usize,
-    /// Labeled spans for subpatterns invalid in Rust 2024.
-    pub(crate) labels: &'a [(Span, String)],
+    /// Internal state: the ref-mutability of the default binding mode at the subpattern being
+    /// lowered, with the span where it was introduced. `None` for a by-value default mode.
+    pub(crate) default_mode_span: Option<(Span, ty::Mutability)>,
+    /// Labels for where incompatibility-causing by-ref default binding modes were introduced.
+    pub(crate) default_mode_labels: FxIndexMap<Span, ty::Mutability>,
 }
 
-impl<'a> Subdiagnostic for Rust2024IncompatiblePatSugg<'a> {
+impl Subdiagnostic for Rust2024IncompatiblePatSugg {
     fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
         self,
         diag: &mut Diag<'_, G>,
         _f: &F,
     ) {
+        // Format and emit explanatory notes about default binding modes. Reversing the spans' order
+        // means if we have nested spans, the innermost ones will be visited first.
+        for (span, def_br_mutbl) in self.default_mode_labels.into_iter().rev() {
+            // Don't point to a macro call site.
+            if !span.from_expansion() {
+                let note_msg = "matching on a reference type with a non-reference pattern changes the default binding mode";
+                let label_msg =
+                    format!("this matches on type `{}_`", def_br_mutbl.ref_prefix_str());
+                let mut label = MultiSpan::from(span);
+                label.push_span_label(span, label_msg);
+                diag.span_note(label, note_msg);
+            }
+        }
+
+        // Format and emit the suggestion.
         let applicability =
             if self.suggestion.iter().all(|(span, _)| span.can_be_used_for_suggestions()) {
                 Applicability::MachineApplicable
             } else {
                 Applicability::MaybeIncorrect
             };
-        let plural_derefs = pluralize!(self.ref_pattern_count);
-        let and_modes = if self.binding_mode_count > 0 {
-            format!(" and variable binding mode{}", pluralize!(self.binding_mode_count))
+        let msg = if self.suggest_eliding_modes {
+            let plural_modes = pluralize!(self.binding_mode_count);
+            format!("remove the unnecessary binding modifier{plural_modes}")
         } else {
-            String::new()
+            let plural_derefs = pluralize!(self.ref_pattern_count);
+            let and_modes = if self.binding_mode_count > 0 {
+                format!(" and variable binding mode{}", pluralize!(self.binding_mode_count))
+            } else {
+                String::new()
+            };
+            format!("make the implied reference pattern{plural_derefs}{and_modes} explicit")
         };
-        diag.multipart_suggestion_verbose(
-            format!("make the implied reference pattern{plural_derefs}{and_modes} explicit"),
-            self.suggestion,
-            applicability,
-        );
+        // FIXME(dianne): for peace of mind, don't risk emitting a 0-part suggestion (that panics!)
+        if !self.suggestion.is_empty() {
+            diag.multipart_suggestion_verbose(msg, self.suggestion, applicability);
+        }
     }
 }
diff --git a/compiler/rustc_mir_build/src/thir/pattern/mod.rs b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
index c862d012f4e..83fef7b0de6 100644
--- a/compiler/rustc_mir_build/src/thir/pattern/mod.rs
+++ b/compiler/rustc_mir_build/src/thir/pattern/mod.rs
@@ -35,7 +35,7 @@ struct PatCtxt<'a, 'tcx> {
     typeck_results: &'a ty::TypeckResults<'tcx>,
 
     /// Used by the Rust 2024 migration lint.
-    rust_2024_migration_suggestion: Option<Rust2024IncompatiblePatSugg<'a>>,
+    rust_2024_migration_suggestion: Option<Rust2024IncompatiblePatSugg>,
 }
 
 pub(super) fn pat_from_hir<'a, 'tcx>(
@@ -44,25 +44,30 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
     typeck_results: &'a ty::TypeckResults<'tcx>,
     pat: &'tcx hir::Pat<'tcx>,
 ) -> Box<Pat<'tcx>> {
+    let migration_info = typeck_results.rust_2024_migration_desugared_pats().get(pat.hir_id);
     let mut pcx = PatCtxt {
         tcx,
         typing_env,
         typeck_results,
-        rust_2024_migration_suggestion: typeck_results
-            .rust_2024_migration_desugared_pats()
-            .get(pat.hir_id)
-            .map(|labels| Rust2024IncompatiblePatSugg {
+        rust_2024_migration_suggestion: migration_info.and_then(|info| {
+            Some(Rust2024IncompatiblePatSugg {
+                suggest_eliding_modes: info.suggest_eliding_modes,
                 suggestion: Vec::new(),
                 ref_pattern_count: 0,
                 binding_mode_count: 0,
-                labels: labels.as_slice(),
-            }),
+                default_mode_span: None,
+                default_mode_labels: Default::default(),
+            })
+        }),
     };
     let result = pcx.lower_pattern(pat);
     debug!("pat_from_hir({:?}) = {:?}", pat, result);
-    if let Some(sugg) = pcx.rust_2024_migration_suggestion {
-        let mut spans = MultiSpan::from_spans(sugg.labels.iter().map(|(span, _)| *span).collect());
-        for (span, label) in sugg.labels {
+    if let Some(info) = migration_info
+        && let Some(sugg) = pcx.rust_2024_migration_suggestion
+    {
+        let mut spans =
+            MultiSpan::from_spans(info.primary_labels.iter().map(|(span, _)| *span).collect());
+        for (span, label) in &info.primary_labels {
             spans.push_span_label(*span, label.clone());
         }
         // If a relevant span is from at least edition 2024, this is a hard error.
@@ -70,10 +75,13 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
         if is_hard_error {
             let mut err =
                 tcx.dcx().struct_span_err(spans, fluent::mir_build_rust_2024_incompatible_pat);
-            if let Some(info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible {
+            if let Some(lint_info) = lint::builtin::RUST_2024_INCOMPATIBLE_PAT.future_incompatible {
                 // provide the same reference link as the lint
-                err.note(format!("for more information, see {}", info.reference));
+                err.note(format!("for more information, see {}", lint_info.reference));
             }
+            err.arg("bad_modifiers", info.bad_modifiers);
+            err.arg("bad_ref_pats", info.bad_ref_pats);
+            err.arg("is_hard_error", true);
             err.subdiagnostic(sugg);
             err.emit();
         } else {
@@ -81,7 +89,12 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
                 lint::builtin::RUST_2024_INCOMPATIBLE_PAT,
                 pat.hir_id,
                 spans,
-                Rust2024IncompatiblePat { sugg },
+                Rust2024IncompatiblePat {
+                    sugg,
+                    bad_modifiers: info.bad_modifiers,
+                    bad_ref_pats: info.bad_ref_pats,
+                    is_hard_error,
+                },
             );
         }
     }
@@ -90,6 +103,35 @@ pub(super) fn pat_from_hir<'a, 'tcx>(
 
 impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
     fn lower_pattern(&mut self, pat: &'tcx hir::Pat<'tcx>) -> Box<Pat<'tcx>> {
+        let adjustments: &[Ty<'tcx>] =
+            self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
+
+        let mut opt_old_mode_span = None;
+        if let Some(s) = &mut self.rust_2024_migration_suggestion
+            && !adjustments.is_empty()
+        {
+            let implicit_deref_mutbls = adjustments.iter().map(|ref_ty| {
+                let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
+                    span_bug!(pat.span, "pattern implicitly dereferences a non-ref type");
+                };
+                mutbl
+            });
+
+            if !s.suggest_eliding_modes {
+                let suggestion_str: String =
+                    implicit_deref_mutbls.clone().map(|mutbl| mutbl.ref_prefix_str()).collect();
+                s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str));
+                s.ref_pattern_count += adjustments.len();
+            }
+
+            // Remember if this changed the default binding mode, in case we want to label it.
+            let min_mutbl = implicit_deref_mutbls.min().unwrap();
+            if s.default_mode_span.is_none_or(|(_, old_mutbl)| min_mutbl < old_mutbl) {
+                opt_old_mode_span = Some(s.default_mode_span);
+                s.default_mode_span = Some((pat.span, min_mutbl));
+            }
+        };
+
         // When implicit dereferences have been inserted in this pattern, the unadjusted lowered
         // pattern has the type that results *after* dereferencing. For example, in this code:
         //
@@ -118,8 +160,6 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
             _ => self.lower_pattern_unadjusted(pat),
         };
 
-        let adjustments: &[Ty<'tcx>] =
-            self.typeck_results.pat_adjustments().get(pat.hir_id).map_or(&[], |v| &**v);
         let adjusted_pat = adjustments.iter().rev().fold(unadjusted_pat, |thir_pat, ref_ty| {
             debug!("{:?}: wrapping pattern with type {:?}", thir_pat, ref_ty);
             Box::new(Pat {
@@ -130,24 +170,10 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
         });
 
         if let Some(s) = &mut self.rust_2024_migration_suggestion
-            && !adjustments.is_empty()
+            && let Some(old_mode_span) = opt_old_mode_span
         {
-            let suggestion_str: String = adjustments
-                .iter()
-                .map(|ref_ty| {
-                    let &ty::Ref(_, _, mutbl) = ref_ty.kind() else {
-                        span_bug!(pat.span, "pattern implicitly dereferences a non-ref type");
-                    };
-
-                    match mutbl {
-                        ty::Mutability::Not => "&",
-                        ty::Mutability::Mut => "&mut ",
-                    }
-                })
-                .collect();
-            s.suggestion.push((pat.span.shrink_to_lo(), suggestion_str));
-            s.ref_pattern_count += adjustments.len();
-        };
+            s.default_mode_span = old_mode_span;
+        }
 
         adjusted_pat
     }
@@ -340,7 +366,22 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                 let mutability = if mutable { hir::Mutability::Mut } else { hir::Mutability::Not };
                 PatKind::DerefPattern { subpattern: self.lower_pattern(subpattern), mutability }
             }
-            hir::PatKind::Ref(subpattern, _) | hir::PatKind::Box(subpattern) => {
+            hir::PatKind::Ref(subpattern, _) => {
+                // Track the default binding mode for the Rust 2024 migration suggestion.
+                let old_mode_span = self.rust_2024_migration_suggestion.as_mut().and_then(|s| {
+                    if let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span {
+                        // If this eats a by-ref default binding mode, label the binding mode.
+                        s.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
+                    }
+                    s.default_mode_span.take()
+                });
+                let subpattern = self.lower_pattern(subpattern);
+                if let Some(s) = &mut self.rust_2024_migration_suggestion {
+                    s.default_mode_span = old_mode_span;
+                }
+                PatKind::Deref { subpattern }
+            }
+            hir::PatKind::Box(subpattern) => {
                 PatKind::Deref { subpattern: self.lower_pattern(subpattern) }
             }
 
@@ -367,19 +408,32 @@ impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
                     .get(pat.hir_id)
                     .expect("missing binding mode");
 
-                if let Some(s) = &mut self.rust_2024_migration_suggestion
-                    && explicit_ba.0 == ByRef::No
-                    && let ByRef::Yes(mutbl) = mode.0
-                {
-                    let sugg_str = match mutbl {
-                        Mutability::Not => "ref ",
-                        Mutability::Mut => "ref mut ",
-                    };
-                    s.suggestion.push((
-                        pat.span.with_lo(ident.span.lo()).shrink_to_lo(),
-                        sugg_str.to_owned(),
-                    ));
-                    s.binding_mode_count += 1;
+                if let Some(s) = &mut self.rust_2024_migration_suggestion {
+                    if explicit_ba != hir::BindingMode::NONE
+                        && let Some((default_mode_span, default_ref_mutbl)) = s.default_mode_span
+                    {
+                        // If this overrides a by-ref default binding mode, label the binding mode.
+                        s.default_mode_labels.insert(default_mode_span, default_ref_mutbl);
+                        // If our suggestion is to elide redundnt modes, this will be one of them.
+                        if s.suggest_eliding_modes {
+                            s.suggestion.push((pat.span.with_hi(ident.span.lo()), String::new()));
+                            s.binding_mode_count += 1;
+                        }
+                    }
+                    if !s.suggest_eliding_modes
+                        && explicit_ba.0 == ByRef::No
+                        && let ByRef::Yes(mutbl) = mode.0
+                    {
+                        let sugg_str = match mutbl {
+                            Mutability::Not => "ref ",
+                            Mutability::Mut => "ref mut ",
+                        };
+                        s.suggestion.push((
+                            pat.span.with_lo(ident.span.lo()).shrink_to_lo(),
+                            sugg_str.to_owned(),
+                        ));
+                        s.binding_mode_count += 1;
+                    }
                 }
 
                 // A ref x pattern is the same node used for x, and as such it has
diff --git a/compiler/rustc_mir_transform/src/validate.rs b/compiler/rustc_mir_transform/src/validate.rs
index b7a3770fc6b..4ac3a268c9c 100644
--- a/compiler/rustc_mir_transform/src/validate.rs
+++ b/compiler/rustc_mir_transform/src/validate.rs
@@ -97,6 +97,12 @@ impl<'tcx> crate::MirPass<'tcx> for Validator {
     }
 }
 
+/// This checker covers basic properties of the control-flow graph, (dis)allowed statements and terminators.
+/// Everything checked here must be stable under substitution of generic parameters. In other words,
+/// this is about the *structure* of the MIR, not the *contents*.
+///
+/// Everything that depends on types, or otherwise can be affected by generic parameters,
+/// must be checked in `TypeChecker`.
 struct CfgChecker<'a, 'tcx> {
     when: &'a str,
     body: &'a Body<'tcx>,
diff --git a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
index a0d41110d96..0bfd72c6848 100644
--- a/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
+++ b/compiler/rustc_next_trait_solver/src/solve/eval_ctxt/canonical.rs
@@ -142,7 +142,7 @@ where
         // Remove any trivial region constraints once we've resolved regions
         external_constraints
             .region_constraints
-            .retain(|outlives| outlives.0.as_region().map_or(true, |re| re != outlives.1));
+            .retain(|outlives| outlives.0.as_region().is_none_or(|re| re != outlives.1));
 
         let canonical = Canonicalizer::canonicalize_response(
             self.delegate,
diff --git a/compiler/rustc_parse/src/lexer/unicode_chars.rs b/compiler/rustc_parse/src/lexer/unicode_chars.rs
index ef8d0f96b61..648a352efd9 100644
--- a/compiler/rustc_parse/src/lexer/unicode_chars.rs
+++ b/compiler/rustc_parse/src/lexer/unicode_chars.rs
@@ -8,7 +8,7 @@ use crate::errors::TokenSubstitution;
 use crate::token::{self, Delimiter};
 
 #[rustfmt::skip] // for line breaks
-pub(super) const UNICODE_ARRAY: &[(char, &str, &str)] = &[
+pub(super) static UNICODE_ARRAY: &[(char, &str, &str)] = &[
     ('
', "Line Separator", " "),
     ('
', "Paragraph Separator", " "),
     (' ', "Ogham Space mark", " "),
diff --git a/compiler/rustc_target/src/asm/mod.rs b/compiler/rustc_target/src/asm/mod.rs
index f17452b3ba0..0a4ffb15219 100644
--- a/compiler/rustc_target/src/asm/mod.rs
+++ b/compiler/rustc_target/src/asm/mod.rs
@@ -1,11 +1,11 @@
 use std::fmt;
 use std::str::FromStr;
 
+use rustc_abi::Size;
 use rustc_data_structures::fx::{FxHashMap, FxIndexSet};
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
 use rustc_span::Symbol;
 
-use crate::abi::Size;
 use crate::spec::{RelocModel, Target};
 
 pub struct ModifierInfo {
diff --git a/compiler/rustc_target/src/callconv/aarch64.rs b/compiler/rustc_target/src/callconv/aarch64.rs
index 67345f0d47b..d712bec9b78 100644
--- a/compiler/rustc_target/src/callconv/aarch64.rs
+++ b/compiler/rustc_target/src/callconv/aarch64.rs
@@ -1,9 +1,8 @@
 use std::iter;
 
-use rustc_abi::{BackendRepr, Primitive};
+use rustc_abi::{BackendRepr, HasDataLayout, Primitive, TyAbiInterface};
 
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, TyAbiInterface};
 use crate::spec::{HasTargetSpec, Target};
 
 /// Indicates the variant of the AArch64 ABI we are compiling for.
diff --git a/compiler/rustc_target/src/callconv/amdgpu.rs b/compiler/rustc_target/src/callconv/amdgpu.rs
index 3007a729a8b..91ac00e0250 100644
--- a/compiler/rustc_target/src/callconv/amdgpu.rs
+++ b/compiler/rustc_target/src/callconv/amdgpu.rs
@@ -1,5 +1,6 @@
+use rustc_abi::{HasDataLayout, TyAbiInterface};
+
 use crate::abi::call::{ArgAbi, FnAbi};
-use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn classify_ret<'a, Ty, C>(_cx: &C, ret: &mut ArgAbi<'a, Ty>)
 where
diff --git a/compiler/rustc_target/src/callconv/arm.rs b/compiler/rustc_target/src/callconv/arm.rs
index bd6f781fb81..75797daba69 100644
--- a/compiler/rustc_target/src/callconv/arm.rs
+++ b/compiler/rustc_target/src/callconv/arm.rs
@@ -1,5 +1,6 @@
+use rustc_abi::{HasDataLayout, TyAbiInterface};
+
 use crate::abi::call::{ArgAbi, Conv, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{HasDataLayout, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 fn is_homogeneous_aggregate<'a, Ty, C>(cx: &C, arg: &mut ArgAbi<'a, Ty>) -> Option<Uniform>
diff --git a/compiler/rustc_target/src/callconv/loongarch.rs b/compiler/rustc_target/src/callconv/loongarch.rs
index 8bf61cb1337..47566bde6b4 100644
--- a/compiler/rustc_target/src/callconv/loongarch.rs
+++ b/compiler/rustc_target/src/callconv/loongarch.rs
@@ -1,9 +1,10 @@
-use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
-use crate::abi::{
-    self, BackendRepr, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout,
+use rustc_abi::{
+    BackendRepr, ExternAbi, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size,
+    TyAbiInterface, TyAndLayout, Variants,
 };
+
+use crate::callconv::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform};
 use crate::spec::HasTargetSpec;
-use crate::spec::abi::Abi as SpecAbi;
 
 #[derive(Copy, Clone)]
 enum RegPassKind {
@@ -42,7 +43,7 @@ where
 {
     match arg_layout.backend_repr {
         BackendRepr::Scalar(scalar) => match scalar.primitive() {
-            abi::Int(..) | abi::Pointer(_) => {
+            Primitive::Int(..) | Primitive::Pointer(_) => {
                 if arg_layout.size.bits() > xlen {
                     return Err(CannotUseFpConv);
                 }
@@ -62,7 +63,7 @@ where
                     _ => return Err(CannotUseFpConv),
                 }
             }
-            abi::Float(_) => {
+            Primitive::Float(_) => {
                 if arg_layout.size.bits() > flen {
                     return Err(CannotUseFpConv);
                 }
@@ -115,8 +116,8 @@ where
             }
             FieldsShape::Arbitrary { .. } => {
                 match arg_layout.variants {
-                    abi::Variants::Multiple { .. } => return Err(CannotUseFpConv),
-                    abi::Variants::Single { .. } | abi::Variants::Empty => (),
+                    Variants::Multiple { .. } => return Err(CannotUseFpConv),
+                    Variants::Single { .. } | Variants::Empty => (),
                 }
                 for i in arg_layout.fields.index_by_increasing_offset() {
                     let field = arg_layout.field(cx, i);
@@ -314,7 +315,7 @@ fn classify_arg<'a, Ty, C>(
 
 fn extend_integer_width<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
     if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
-        if let abi::Int(i, _) = scalar.primitive() {
+        if let Primitive::Int(i, _) = scalar.primitive() {
             // 32-bit integers are always sign-extended
             if i.size().bits() == 32 && xlen > 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
@@ -363,12 +364,12 @@ where
     }
 }
 
-pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: SpecAbi)
+pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
 {
-    if abi == SpecAbi::RustIntrinsic {
+    if abi == ExternAbi::RustIntrinsic {
         return;
     }
 
diff --git a/compiler/rustc_target/src/callconv/mips.rs b/compiler/rustc_target/src/callconv/mips.rs
index 37980a91c76..f7d68822155 100644
--- a/compiler/rustc_target/src/callconv/mips.rs
+++ b/compiler/rustc_target/src/callconv/mips.rs
@@ -1,5 +1,6 @@
+use rustc_abi::{HasDataLayout, Size};
+
 use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
-use crate::abi::{HasDataLayout, Size};
 
 fn classify_ret<Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
diff --git a/compiler/rustc_target/src/callconv/mips64.rs b/compiler/rustc_target/src/callconv/mips64.rs
index 5bdf4c2ad77..89f324bc313 100644
--- a/compiler/rustc_target/src/callconv/mips64.rs
+++ b/compiler/rustc_target/src/callconv/mips64.rs
@@ -1,12 +1,15 @@
-use crate::abi::call::{
-    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, Reg, Uniform,
+use rustc_abi::{
+    BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Size, TyAbiInterface,
+};
+
+use crate::callconv::{
+    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, PassMode, Uniform,
 };
-use crate::abi::{self, HasDataLayout, Size, TyAbiInterface};
 
 fn extend_integer_width_mips<Ty>(arg: &mut ArgAbi<'_, Ty>, bits: u64) {
     // Always sign extend u32 values on 64-bit mips
-    if let abi::BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
-        if let abi::Int(i, signed) = scalar.primitive() {
+    if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
+        if let Primitive::Int(i, signed) = scalar.primitive() {
             if !signed && i.size().bits() == 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
                     attrs.ext(ArgExtension::Sext);
@@ -25,9 +28,9 @@ where
     C: HasDataLayout,
 {
     match ret.layout.field(cx, i).backend_repr {
-        abi::BackendRepr::Scalar(scalar) => match scalar.primitive() {
-            abi::Float(abi::F32) => Some(Reg::f32()),
-            abi::Float(abi::F64) => Some(Reg::f64()),
+        BackendRepr::Scalar(scalar) => match scalar.primitive() {
+            Primitive::Float(Float::F32) => Some(Reg::f32()),
+            Primitive::Float(Float::F64) => Some(Reg::f64()),
             _ => None,
         },
         _ => None,
@@ -51,7 +54,7 @@ where
         // use of float registers to structures (not unions) containing exactly one or two
         // float fields.
 
-        if let abi::FieldsShape::Arbitrary { .. } = ret.layout.fields {
+        if let FieldsShape::Arbitrary { .. } = ret.layout.fields {
             if ret.layout.fields.count() == 1 {
                 if let Some(reg) = float_reg(cx, ret, 0) {
                     ret.cast_to(reg);
@@ -90,16 +93,16 @@ where
     let mut prefix_index = 0;
 
     match arg.layout.fields {
-        abi::FieldsShape::Primitive => unreachable!(),
-        abi::FieldsShape::Array { .. } => {
+        FieldsShape::Primitive => unreachable!(),
+        FieldsShape::Array { .. } => {
             // Arrays are passed indirectly
             arg.make_indirect();
             return;
         }
-        abi::FieldsShape::Union(_) => {
+        FieldsShape::Union(_) => {
             // Unions and are always treated as a series of 64-bit integer chunks
         }
-        abi::FieldsShape::Arbitrary { .. } => {
+        FieldsShape::Arbitrary { .. } => {
             // Structures are split up into a series of 64-bit integer chunks, but any aligned
             // doubles not part of another aggregate are passed as floats.
             let mut last_offset = Size::ZERO;
@@ -109,8 +112,8 @@ where
                 let offset = arg.layout.fields.offset(i);
 
                 // We only care about aligned doubles
-                if let abi::BackendRepr::Scalar(scalar) = field.backend_repr {
-                    if scalar.primitive() == abi::Float(abi::F64) {
+                if let BackendRepr::Scalar(scalar) = field.backend_repr {
+                    if scalar.primitive() == Primitive::Float(Float::F64) {
                         if offset.is_aligned(dl.f64_align.abi) {
                             // Insert enough integers to cover [last_offset, offset)
                             assert!(last_offset.is_aligned(dl.f64_align.abi));
diff --git a/compiler/rustc_target/src/callconv/mod.rs b/compiler/rustc_target/src/callconv/mod.rs
index 41b78d9121d..9e651376cd7 100644
--- a/compiler/rustc_target/src/callconv/mod.rs
+++ b/compiler/rustc_target/src/callconv/mod.rs
@@ -1,14 +1,14 @@
 use std::str::FromStr;
 use std::{fmt, iter};
 
-pub use rustc_abi::{ExternAbi, Reg, RegKind};
+use rustc_abi::{
+    AddressSpace, Align, BackendRepr, ExternAbi, HasDataLayout, Scalar, Size, TyAbiInterface,
+    TyAndLayout,
+};
+pub use rustc_abi::{Primitive, Reg, RegKind};
 use rustc_macros::HashStable_Generic;
 use rustc_span::Symbol;
 
-use crate::abi::{
-    self, AddressSpace, Align, BackendRepr, HasDataLayout, Pointer, Size, TyAbiInterface,
-    TyAndLayout,
-};
 use crate::spec::{HasTargetSpec, HasWasmCAbiOpt, HasX86AbiOpt, WasmCAbi};
 
 mod aarch64;
@@ -349,7 +349,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
     pub fn new(
         cx: &impl HasDataLayout,
         layout: TyAndLayout<'a, Ty>,
-        scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, abi::Scalar, Size) -> ArgAttributes,
+        scalar_attrs: impl Fn(&TyAndLayout<'a, Ty>, Scalar, Size) -> ArgAttributes,
     ) -> Self {
         let mode = match layout.backend_repr {
             BackendRepr::Uninhabited => PassMode::Ignore,
@@ -464,7 +464,7 @@ impl<'a, Ty> ArgAbi<'a, Ty> {
     pub fn extend_integer_width_to(&mut self, bits: u64) {
         // Only integers have signedness
         if let BackendRepr::Scalar(scalar) = self.layout.backend_repr {
-            if let abi::Int(i, signed) = scalar.primitive() {
+            if let Primitive::Int(i, signed) = scalar.primitive() {
                 if i.size().bits() < bits {
                     if let PassMode::Direct(ref mut attrs) = self.mode {
                         if signed {
@@ -756,7 +756,9 @@ impl<'a, Ty> FnAbi<'a, Ty> {
                 continue;
             }
 
-            if arg_idx.is_none() && arg.layout.size > Pointer(AddressSpace::DATA).size(cx) * 2 {
+            if arg_idx.is_none()
+                && arg.layout.size > Primitive::Pointer(AddressSpace::DATA).size(cx) * 2
+            {
                 // Return values larger than 2 registers using a return area
                 // pointer. LLVM and Cranelift disagree about how to return
                 // values that don't fit in the registers designated for return
@@ -837,7 +839,7 @@ impl<'a, Ty> FnAbi<'a, Ty> {
             assert!(is_indirect_not_on_stack);
 
             let size = arg.layout.size;
-            if !arg.layout.is_unsized() && size <= Pointer(AddressSpace::DATA).size(cx) {
+            if !arg.layout.is_unsized() && size <= Primitive::Pointer(AddressSpace::DATA).size(cx) {
                 // We want to pass small aggregates as immediates, but using
                 // an LLVM aggregate type for this leads to bad optimizations,
                 // so we pick an appropriately sized integer type instead.
diff --git a/compiler/rustc_target/src/callconv/nvptx64.rs b/compiler/rustc_target/src/callconv/nvptx64.rs
index c64164372a1..c5da1855658 100644
--- a/compiler/rustc_target/src/callconv/nvptx64.rs
+++ b/compiler/rustc_target/src/callconv/nvptx64.rs
@@ -1,6 +1,7 @@
+use rustc_abi::{HasDataLayout, Reg, Size, TyAbiInterface};
+
 use super::{ArgAttribute, ArgAttributes, ArgExtension, CastTarget};
-use crate::abi::call::{ArgAbi, FnAbi, Reg, Size, Uniform};
-use crate::abi::{HasDataLayout, TyAbiInterface};
+use crate::abi::call::{ArgAbi, FnAbi, Uniform};
 
 fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
     if ret.layout.is_aggregate() && ret.layout.is_sized() {
diff --git a/compiler/rustc_target/src/callconv/powerpc64.rs b/compiler/rustc_target/src/callconv/powerpc64.rs
index 92c1f6e7148..7a66ce8529a 100644
--- a/compiler/rustc_target/src/callconv/powerpc64.rs
+++ b/compiler/rustc_target/src/callconv/powerpc64.rs
@@ -2,8 +2,9 @@
 // Alignment of 128 bit types is not currently handled, this will
 // need to be fixed when PowerPC vector support is added.
 
+use rustc_abi::{Endian, HasDataLayout, TyAbiInterface};
+
 use crate::abi::call::{Align, ArgAbi, FnAbi, Reg, RegKind, Uniform};
-use crate::abi::{Endian, HasDataLayout, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 #[derive(Debug, Clone, Copy, PartialEq)]
diff --git a/compiler/rustc_target/src/callconv/riscv.rs b/compiler/rustc_target/src/callconv/riscv.rs
index 4d858392c97..24531b0ef63 100644
--- a/compiler/rustc_target/src/callconv/riscv.rs
+++ b/compiler/rustc_target/src/callconv/riscv.rs
@@ -4,12 +4,13 @@
 // Reference: Clang RISC-V ELF psABI lowering code
 // https://github.com/llvm/llvm-project/blob/8e780252a7284be45cf1ba224cabd884847e8e92/clang/lib/CodeGen/TargetInfo.cpp#L9311-L9773
 
-use rustc_abi::{BackendRepr, FieldsShape, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
+use rustc_abi::{
+    BackendRepr, ExternAbi, FieldsShape, HasDataLayout, Primitive, Reg, RegKind, Size,
+    TyAbiInterface, TyAndLayout, Variants,
+};
 
-use crate::abi;
-use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Reg, RegKind, Uniform};
+use crate::abi::call::{ArgAbi, ArgExtension, CastTarget, FnAbi, PassMode, Uniform};
 use crate::spec::HasTargetSpec;
-use crate::spec::abi::Abi as SpecAbi;
 
 #[derive(Copy, Clone)]
 enum RegPassKind {
@@ -48,7 +49,7 @@ where
 {
     match arg_layout.backend_repr {
         BackendRepr::Scalar(scalar) => match scalar.primitive() {
-            abi::Int(..) | abi::Pointer(_) => {
+            Primitive::Int(..) | Primitive::Pointer(_) => {
                 if arg_layout.size.bits() > xlen {
                     return Err(CannotUseFpConv);
                 }
@@ -68,7 +69,7 @@ where
                     _ => return Err(CannotUseFpConv),
                 }
             }
-            abi::Float(_) => {
+            Primitive::Float(_) => {
                 if arg_layout.size.bits() > flen {
                     return Err(CannotUseFpConv);
                 }
@@ -121,8 +122,8 @@ where
             }
             FieldsShape::Arbitrary { .. } => {
                 match arg_layout.variants {
-                    abi::Variants::Multiple { .. } => return Err(CannotUseFpConv),
-                    abi::Variants::Single { .. } | abi::Variants::Empty => (),
+                    Variants::Multiple { .. } => return Err(CannotUseFpConv),
+                    Variants::Single { .. } | Variants::Empty => (),
                 }
                 for i in arg_layout.fields.index_by_increasing_offset() {
                     let field = arg_layout.field(cx, i);
@@ -320,7 +321,7 @@ fn classify_arg<'a, Ty, C>(
 
 fn extend_integer_width<Ty>(arg: &mut ArgAbi<'_, Ty>, xlen: u64) {
     if let BackendRepr::Scalar(scalar) = arg.layout.backend_repr {
-        if let abi::Int(i, _) = scalar.primitive() {
+        if let Primitive::Int(i, _) = scalar.primitive() {
             // 32-bit integers are always sign-extended
             if i.size().bits() == 32 && xlen > 32 {
                 if let PassMode::Direct(ref mut attrs) = arg.mode {
@@ -369,12 +370,12 @@ where
     }
 }
 
-pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: SpecAbi)
+pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
 {
-    if abi == SpecAbi::RustIntrinsic {
+    if abi == ExternAbi::RustIntrinsic {
         return;
     }
 
diff --git a/compiler/rustc_target/src/callconv/s390x.rs b/compiler/rustc_target/src/callconv/s390x.rs
index a73c1a0f46c..edf57098d6d 100644
--- a/compiler/rustc_target/src/callconv/s390x.rs
+++ b/compiler/rustc_target/src/callconv/s390x.rs
@@ -1,8 +1,9 @@
 // Reference: ELF Application Binary Interface s390x Supplement
 // https://github.com/IBM/s390x-abi
 
+use rustc_abi::{BackendRepr, HasDataLayout, TyAbiInterface};
+
 use crate::abi::call::{ArgAbi, FnAbi, Reg, RegKind};
-use crate::abi::{BackendRepr, HasDataLayout, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 fn classify_ret<Ty>(ret: &mut ArgAbi<'_, Ty>) {
diff --git a/compiler/rustc_target/src/callconv/sparc.rs b/compiler/rustc_target/src/callconv/sparc.rs
index 37980a91c76..f7d68822155 100644
--- a/compiler/rustc_target/src/callconv/sparc.rs
+++ b/compiler/rustc_target/src/callconv/sparc.rs
@@ -1,5 +1,6 @@
+use rustc_abi::{HasDataLayout, Size};
+
 use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
-use crate::abi::{HasDataLayout, Size};
 
 fn classify_ret<Ty, C>(cx: &C, ret: &mut ArgAbi<'_, Ty>, offset: &mut Size)
 where
diff --git a/compiler/rustc_target/src/callconv/sparc64.rs b/compiler/rustc_target/src/callconv/sparc64.rs
index 313d8730399..392fb5156fc 100644
--- a/compiler/rustc_target/src/callconv/sparc64.rs
+++ b/compiler/rustc_target/src/callconv/sparc64.rs
@@ -1,9 +1,13 @@
 // FIXME: This needs an audit for correctness and completeness.
 
+use rustc_abi::{
+    BackendRepr, FieldsShape, Float, HasDataLayout, Primitive, Reg, Scalar, Size, TyAbiInterface,
+    TyAndLayout,
+};
+
 use crate::abi::call::{
-    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Reg, Uniform,
+    ArgAbi, ArgAttribute, ArgAttributes, ArgExtension, CastTarget, FnAbi, Uniform,
 };
-use crate::abi::{self, HasDataLayout, Scalar, Size, TyAbiInterface, TyAndLayout};
 use crate::spec::HasTargetSpec;
 
 #[derive(Clone, Debug)]
@@ -21,7 +25,7 @@ where
 {
     let dl = cx.data_layout();
 
-    if !matches!(scalar.primitive(), abi::Float(abi::F32 | abi::F64)) {
+    if !matches!(scalar.primitive(), Primitive::Float(Float::F32 | Float::F64)) {
         return data;
     }
 
@@ -57,7 +61,7 @@ where
         return data;
     }
 
-    if scalar.primitive() == abi::Float(abi::F32) {
+    if scalar.primitive() == Primitive::Float(Float::F32) {
         data.arg_attribute = ArgAttribute::InReg;
         data.prefix[data.prefix_index] = Some(Reg::f32());
         data.last_offset = offset + Reg::f32().size;
@@ -81,14 +85,16 @@ where
 {
     data = arg_scalar(cx, scalar1, offset, data);
     match (scalar1.primitive(), scalar2.primitive()) {
-        (abi::Float(abi::F32), _) => offset += Reg::f32().size,
-        (_, abi::Float(abi::F64)) => offset += Reg::f64().size,
-        (abi::Int(i, _signed), _) => offset += i.size(),
-        (abi::Pointer(_), _) => offset += Reg::i64().size,
+        (Primitive::Float(Float::F32), _) => offset += Reg::f32().size,
+        (_, Primitive::Float(Float::F64)) => offset += Reg::f64().size,
+        (Primitive::Int(i, _signed), _) => offset += i.size(),
+        (Primitive::Pointer(_), _) => offset += Reg::i64().size,
         _ => {}
     }
 
-    if (offset.bytes() % 4) != 0 && matches!(scalar2.primitive(), abi::Float(abi::F32 | abi::F64)) {
+    if (offset.bytes() % 4) != 0
+        && matches!(scalar2.primitive(), Primitive::Float(Float::F32 | Float::F64))
+    {
         offset += Size::from_bytes(4 - (offset.bytes() % 4));
     }
     data = arg_scalar(cx, scalar2, offset, data);
@@ -105,15 +111,15 @@ where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout,
 {
-    if let abi::FieldsShape::Union(_) = layout.fields {
+    if let FieldsShape::Union(_) = layout.fields {
         return data;
     }
 
     match layout.backend_repr {
-        abi::BackendRepr::Scalar(scalar) => {
+        BackendRepr::Scalar(scalar) => {
             data = arg_scalar(cx, &scalar, offset, data);
         }
-        abi::BackendRepr::Memory { .. } => {
+        BackendRepr::Memory { .. } => {
             for i in 0..layout.fields.count() {
                 if offset < layout.fields.offset(i) {
                     offset = layout.fields.offset(i);
@@ -122,7 +128,7 @@ where
             }
         }
         _ => {
-            if let abi::BackendRepr::ScalarPair(scalar1, scalar2) = &layout.backend_repr {
+            if let BackendRepr::ScalarPair(scalar1, scalar2) = &layout.backend_repr {
                 data = arg_scalar_pair(cx, scalar1, scalar2, offset, data);
             }
         }
@@ -148,16 +154,16 @@ where
     }
 
     match arg.layout.fields {
-        abi::FieldsShape::Primitive => unreachable!(),
-        abi::FieldsShape::Array { .. } => {
+        FieldsShape::Primitive => unreachable!(),
+        FieldsShape::Array { .. } => {
             // Arrays are passed indirectly
             arg.make_indirect();
             return;
         }
-        abi::FieldsShape::Union(_) => {
+        FieldsShape::Union(_) => {
             // Unions and are always treated as a series of 64-bit integer chunks
         }
-        abi::FieldsShape::Arbitrary { .. } => {
+        FieldsShape::Arbitrary { .. } => {
             // Structures with floating point numbers need special care.
 
             let mut data = parse_structure(
diff --git a/compiler/rustc_target/src/callconv/wasm.rs b/compiler/rustc_target/src/callconv/wasm.rs
index d01b59cbb03..56cd7a3f93d 100644
--- a/compiler/rustc_target/src/callconv/wasm.rs
+++ b/compiler/rustc_target/src/callconv/wasm.rs
@@ -1,7 +1,6 @@
-use rustc_abi::{BackendRepr, Float, Integer, Primitive};
+use rustc_abi::{BackendRepr, Float, HasDataLayout, Integer, Primitive, TyAbiInterface};
 
 use crate::abi::call::{ArgAbi, FnAbi};
-use crate::abi::{HasDataLayout, TyAbiInterface};
 
 fn unwrap_trivial_aggregate<'a, Ty, C>(cx: &C, val: &mut ArgAbi<'a, Ty>) -> bool
 where
diff --git a/compiler/rustc_target/src/callconv/x86.rs b/compiler/rustc_target/src/callconv/x86.rs
index cd8465c09ca..7c88d9b55cf 100644
--- a/compiler/rustc_target/src/callconv/x86.rs
+++ b/compiler/rustc_target/src/callconv/x86.rs
@@ -1,9 +1,10 @@
-use crate::abi::call::{ArgAttribute, FnAbi, PassMode, Reg, RegKind};
-use crate::abi::{
-    AddressSpace, Align, BackendRepr, Float, HasDataLayout, Pointer, TyAbiInterface, TyAndLayout,
+use rustc_abi::{
+    AddressSpace, Align, BackendRepr, ExternAbi, HasDataLayout, Primitive, Reg, RegKind,
+    TyAbiInterface, TyAndLayout,
 };
+
+use crate::abi::call::{ArgAttribute, FnAbi, PassMode};
 use crate::spec::HasTargetSpec;
-use crate::spec::abi::Abi as SpecAbi;
 
 #[derive(PartialEq)]
 pub(crate) enum Flavor {
@@ -214,7 +215,7 @@ pub(crate) fn fill_inregs<'a, Ty, C>(
     }
 }
 
-pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: SpecAbi)
+pub(crate) fn compute_rust_abi_info<'a, Ty, C>(cx: &C, fn_abi: &mut FnAbi<'a, Ty>, abi: ExternAbi)
 where
     Ty: TyAbiInterface<'a, C> + Copy,
     C: HasDataLayout + HasTargetSpec,
@@ -223,18 +224,19 @@ where
     // registers will quiet signalling NaNs. Also avoid using SSE registers since they
     // are not always available (depending on target features).
     if !fn_abi.ret.is_ignore()
-        // Intrinsics themselves are not actual "real" functions, so theres no need to change their ABIs.
-        && abi != SpecAbi::RustIntrinsic
+        // Intrinsics themselves are not "real" functions, so theres no need to change their ABIs.
+        && abi != ExternAbi::RustIntrinsic
     {
         let has_float = match fn_abi.ret.layout.backend_repr {
-            BackendRepr::Scalar(s) => matches!(s.primitive(), Float(_)),
+            BackendRepr::Scalar(s) => matches!(s.primitive(), Primitive::Float(_)),
             BackendRepr::ScalarPair(s1, s2) => {
-                matches!(s1.primitive(), Float(_)) || matches!(s2.primitive(), Float(_))
+                matches!(s1.primitive(), Primitive::Float(_))
+                    || matches!(s2.primitive(), Primitive::Float(_))
             }
             _ => false, // anyway not passed via registers on x86
         };
         if has_float {
-            if fn_abi.ret.layout.size <= Pointer(AddressSpace::DATA).size(cx) {
+            if fn_abi.ret.layout.size <= Primitive::Pointer(AddressSpace::DATA).size(cx) {
                 // Same size or smaller than pointer, return in a register.
                 fn_abi.ret.cast_to(Reg { kind: RegKind::Integer, size: fn_abi.ret.layout.size });
             } else {
diff --git a/compiler/rustc_target/src/callconv/x86_64.rs b/compiler/rustc_target/src/callconv/x86_64.rs
index 37aecf323a1..6e9b4690a2c 100644
--- a/compiler/rustc_target/src/callconv/x86_64.rs
+++ b/compiler/rustc_target/src/callconv/x86_64.rs
@@ -1,10 +1,12 @@
 // The classification code for the x86_64 ABI is taken from the clay language
 // https://github.com/jckarter/clay/blob/db0bd2702ab0b6e48965cd85f8859bbd5f60e48e/compiler/externals.cpp
 
-use rustc_abi::{BackendRepr, HasDataLayout, Size, TyAbiInterface, TyAndLayout};
+use rustc_abi::{
+    BackendRepr, HasDataLayout, Primitive, Reg, RegKind, Size, TyAbiInterface, TyAndLayout,
+    Variants,
+};
 
-use crate::abi;
-use crate::abi::call::{ArgAbi, CastTarget, FnAbi, Reg, RegKind};
+use crate::abi::call::{ArgAbi, CastTarget, FnAbi};
 
 /// Classification of "eightbyte" components.
 // N.B., the order of the variants is from general to specific,
@@ -52,8 +54,8 @@ where
             BackendRepr::Uninhabited => return Ok(()),
 
             BackendRepr::Scalar(scalar) => match scalar.primitive() {
-                abi::Int(..) | abi::Pointer(_) => Class::Int,
-                abi::Float(_) => Class::Sse,
+                Primitive::Int(..) | Primitive::Pointer(_) => Class::Int,
+                Primitive::Float(_) => Class::Sse,
             },
 
             BackendRepr::Vector { .. } => Class::Sse,
@@ -65,8 +67,8 @@ where
                 }
 
                 match &layout.variants {
-                    abi::Variants::Single { .. } | abi::Variants::Empty => {}
-                    abi::Variants::Multiple { variants, .. } => {
+                    Variants::Single { .. } | Variants::Empty => {}
+                    Variants::Multiple { variants, .. } => {
                         // Treat enum variants like union members.
                         for variant_idx in variants.indices() {
                             classify(cx, layout.for_variant(cx, variant_idx), cls, off)?;
diff --git a/compiler/rustc_target/src/callconv/xtensa.rs b/compiler/rustc_target/src/callconv/xtensa.rs
index 9d313d16500..2542713bc11 100644
--- a/compiler/rustc_target/src/callconv/xtensa.rs
+++ b/compiler/rustc_target/src/callconv/xtensa.rs
@@ -5,8 +5,9 @@
 //! Section 8.1.4 & 8.1.5 of the Xtensa ISA reference manual, as well as snippets from
 //! Section 2.3 from the Xtensa programmers guide.
 
+use rustc_abi::{BackendRepr, HasDataLayout, Size, TyAbiInterface};
+
 use crate::abi::call::{ArgAbi, FnAbi, Reg, Uniform};
-use crate::abi::{BackendRepr, HasDataLayout, Size, TyAbiInterface};
 use crate::spec::HasTargetSpec;
 
 const NUM_ARG_GPRS: u64 = 6;
diff --git a/compiler/rustc_target/src/lib.rs b/compiler/rustc_target/src/lib.rs
index 50679ab8cc8..11fc09d26e4 100644
--- a/compiler/rustc_target/src/lib.rs
+++ b/compiler/rustc_target/src/lib.rs
@@ -31,10 +31,7 @@ pub mod target_features;
 mod tests;
 
 pub mod abi {
-    pub(crate) use Float::*;
-    pub(crate) use Primitive::*;
-    // Explicitly import `Float` to avoid ambiguity with `Primitive::Float`.
-    pub use rustc_abi::{Float, *};
+    pub use rustc_abi::*;
 
     pub use crate::callconv as call;
 }
diff --git a/compiler/rustc_target/src/spec/base/aix.rs b/compiler/rustc_target/src/spec/base/aix.rs
index fe37d313294..a92d104f910 100644
--- a/compiler/rustc_target/src/spec/base/aix.rs
+++ b/compiler/rustc_target/src/spec/base/aix.rs
@@ -1,4 +1,5 @@
-use crate::abi::Endian;
+use rustc_abi::Endian;
+
 use crate::spec::{Cc, CodeModel, LinkOutputKind, LinkerFlavor, TargetOptions, crt_objects, cvs};
 
 pub(crate) fn opts() -> TargetOptions {
diff --git a/compiler/rustc_target/src/spec/base/bpf.rs b/compiler/rustc_target/src/spec/base/bpf.rs
index 17d5e75ef6d..7c0e2e165b6 100644
--- a/compiler/rustc_target/src/spec/base/bpf.rs
+++ b/compiler/rustc_target/src/spec/base/bpf.rs
@@ -1,4 +1,5 @@
-use crate::abi::Endian;
+use rustc_abi::Endian;
+
 use crate::spec::{LinkerFlavor, MergeFunctions, PanicStrategy, TargetOptions};
 
 pub(crate) fn opts(endian: Endian) -> TargetOptions {
diff --git a/compiler/rustc_target/src/spec/base/xtensa.rs b/compiler/rustc_target/src/spec/base/xtensa.rs
index 280dd16e264..47a532dfdd4 100644
--- a/compiler/rustc_target/src/spec/base/xtensa.rs
+++ b/compiler/rustc_target/src/spec/base/xtensa.rs
@@ -1,4 +1,5 @@
-use crate::abi::Endian;
+use rustc_abi::Endian;
+
 use crate::spec::{Cc, LinkerFlavor, Lld, PanicStrategy, RelocModel, TargetOptions};
 
 pub(crate) fn opts() -> TargetOptions {
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index 72600225e7a..e95c4dbd2cf 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -42,6 +42,7 @@ use std::path::{Path, PathBuf};
 use std::str::FromStr;
 use std::{fmt, io};
 
+use rustc_abi::{Endian, ExternAbi, Integer, Size, TargetDataLayout, TargetDataLayoutErrors};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_fs_util::try_canonicalize;
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
@@ -51,9 +52,7 @@ use serde_json::Value;
 use tracing::debug;
 
 use crate::abi::call::Conv;
-use crate::abi::{Endian, Integer, Size, TargetDataLayout, TargetDataLayoutErrors};
 use crate::json::{Json, ToJson};
-use crate::spec::abi::Abi;
 use crate::spec::crt_objects::CrtObjects;
 
 pub mod crt_objects;
@@ -1651,7 +1650,7 @@ macro_rules! supported_targets {
         }
 
         /// List of supported targets
-        pub const TARGETS: &[&str] = &[$($tuple),+];
+        pub static TARGETS: &[&str] = &[$($tuple),+];
 
         fn load_builtin(target: &str) -> Option<Target> {
             let t = match target {
@@ -2845,44 +2844,40 @@ impl DerefMut for Target {
 
 impl Target {
     /// Given a function ABI, turn it into the correct ABI for this target.
-    pub fn adjust_abi(&self, abi: Abi, c_variadic: bool) -> Abi {
+    pub fn adjust_abi(&self, abi: ExternAbi, c_variadic: bool) -> ExternAbi {
+        use ExternAbi::*;
         match abi {
             // On Windows, `extern "system"` behaves like msvc's `__stdcall`.
             // `__stdcall` only applies on x86 and on non-variadic functions:
             // https://learn.microsoft.com/en-us/cpp/cpp/stdcall?view=msvc-170
-            Abi::System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => {
-                Abi::Stdcall { unwind }
+            System { unwind } if self.is_like_windows && self.arch == "x86" && !c_variadic => {
+                Stdcall { unwind }
             }
-            Abi::System { unwind } => Abi::C { unwind },
-            Abi::EfiApi if self.arch == "arm" => Abi::Aapcs { unwind: false },
-            Abi::EfiApi if self.arch == "x86_64" => Abi::Win64 { unwind: false },
-            Abi::EfiApi => Abi::C { unwind: false },
-
-            // See commentary in `is_abi_supported`: we map these ABIs to "C" when they do not make sense.
-            Abi::Stdcall { .. } | Abi::Thiscall { .. } | Abi::Fastcall { .. }
-                if self.arch == "x86" =>
-            {
-                abi
-            }
-            Abi::Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
-            Abi::Stdcall { unwind }
-            | Abi::Thiscall { unwind }
-            | Abi::Fastcall { unwind }
-            | Abi::Vectorcall { unwind } => Abi::C { unwind },
+            System { unwind } => C { unwind },
+            EfiApi if self.arch == "arm" => Aapcs { unwind: false },
+            EfiApi if self.arch == "x86_64" => Win64 { unwind: false },
+            EfiApi => C { unwind: false },
+
+            // See commentary in `is_abi_supported`.
+            Stdcall { .. } | Thiscall { .. } if self.arch == "x86" => abi,
+            Stdcall { unwind } | Thiscall { unwind } => C { unwind },
+            Fastcall { .. } if self.arch == "x86" => abi,
+            Vectorcall { .. } if ["x86", "x86_64"].contains(&&self.arch[..]) => abi,
+            Fastcall { unwind } | Vectorcall { unwind } => C { unwind },
 
             // The Windows x64 calling convention we use for `extern "Rust"`
             // <https://learn.microsoft.com/en-us/cpp/build/x64-software-conventions#register-volatility-and-preservation>
             // expects the callee to save `xmm6` through `xmm15`, but `PreserveMost`
             // (that we use by default for `extern "rust-cold"`) doesn't save any of those.
             // So to avoid bloating callers, just use the Rust convention here.
-            Abi::RustCold if self.is_like_windows && self.arch == "x86_64" => Abi::Rust,
+            RustCold if self.is_like_windows && self.arch == "x86_64" => Rust,
 
             abi => abi,
         }
     }
 
-    pub fn is_abi_supported(&self, abi: Abi) -> bool {
-        use Abi::*;
+    pub fn is_abi_supported(&self, abi: ExternAbi) -> bool {
+        use ExternAbi::*;
         match abi {
             Rust
             | C { .. }
diff --git a/compiler/rustc_target/src/target_features.rs b/compiler/rustc_target/src/target_features.rs
index eb2417e0a20..e423ca71dfc 100644
--- a/compiler/rustc_target/src/target_features.rs
+++ b/compiler/rustc_target/src/target_features.rs
@@ -131,7 +131,7 @@ impl Stability {
 // Both of these are also applied transitively.
 type ImpliedFeatures = &'static [&'static str];
 
-const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("aclass", Unstable(sym::arm_target_feature), &[]),
     ("aes", Unstable(sym::arm_target_feature), &["neon"]),
@@ -175,7 +175,7 @@ const ARM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static AARCH64_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     // FEAT_AES & FEAT_PMULL
     ("aes", Stable, &["neon"]),
@@ -371,7 +371,7 @@ const AARCH64_TIED_FEATURES: &[&[&str]] = &[
     &["paca", "pacg"], // Together these represent `pauth` in LLVM
 ];
 
-const X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static X86_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("adx", Stable, &[]),
     ("aes", Stable, &["sse2"]),
@@ -453,7 +453,7 @@ const HEXAGON_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static POWERPC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("altivec", Unstable(sym::powerpc_target_feature), &[]),
     ("partword-atomics", Unstable(sym::powerpc_target_feature), &[]),
@@ -476,7 +476,7 @@ const MIPS_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("a", Stable, &["zaamo", "zalrsc"]),
     ("c", Stable, &[]),
@@ -521,7 +521,7 @@ const RISCV_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("atomics", Unstable(sym::wasm_target_feature), &[]),
     ("bulk-memory", Stable, &[]),
@@ -542,7 +542,7 @@ const WASM_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
 const BPF_FEATURES: &[(&str, Stability, ImpliedFeatures)] =
     &[("alu32", Unstable(sym::bpf_target_feature), &[])];
 
-const CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("10e60", Unstable(sym::csky_target_feature), &["7e10"]),
     ("2e3", Unstable(sym::csky_target_feature), &["e2"]),
@@ -589,7 +589,7 @@ const CSKY_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static LOONGARCH_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("d", Unstable(sym::loongarch_target_feature), &["f"]),
     ("f", Unstable(sym::loongarch_target_feature), &[]),
@@ -618,7 +618,7 @@ const SPARC_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-end
 ];
 
-const M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
+static M68K_FEATURES: &[(&str, Stability, ImpliedFeatures)] = &[
     // tidy-alphabetical-start
     ("isa-68000", Unstable(sym::m68k_target_feature), &[]),
     ("isa-68010", Unstable(sym::m68k_target_feature), &["isa-68000"]),
diff --git a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
index 13a6744c2e9..e495bdbf782 100644
--- a/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
+++ b/compiler/rustc_trait_selection/src/traits/select/candidate_assembly.rs
@@ -12,9 +12,7 @@ use hir::LangItem;
 use hir::def_id::DefId;
 use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
 use rustc_hir as hir;
-use rustc_infer::traits::{
-    Obligation, ObligationCause, PolyTraitObligation, PredicateObligations, SelectionError,
-};
+use rustc_infer::traits::{Obligation, PolyTraitObligation, SelectionError};
 use rustc_middle::ty::fast_reject::DeepRejectCtxt;
 use rustc_middle::ty::{self, Ty, TypeVisitableExt, TypingMode};
 use rustc_middle::{bug, span_bug};
@@ -23,8 +21,6 @@ use tracing::{debug, instrument, trace};
 
 use super::SelectionCandidate::*;
 use super::{BuiltinImplConditions, SelectionCandidateSet, SelectionContext, TraitObligationStack};
-use crate::traits;
-use crate::traits::query::evaluate_obligation::InferCtxtExt;
 use crate::traits::util;
 
 impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
@@ -904,54 +900,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         })
     }
 
-    /// Temporary migration for #89190
-    fn need_migrate_deref_output_trait_object(
-        &mut self,
-        ty: Ty<'tcx>,
-        param_env: ty::ParamEnv<'tcx>,
-        cause: &ObligationCause<'tcx>,
-    ) -> Option<ty::PolyExistentialTraitRef<'tcx>> {
-        // Don't drop any candidates in intercrate mode, as it's incomplete.
-        // (Not that it matters, since `Unsize` is not a stable trait.)
-        //
-        // FIXME(@lcnr): This should probably only trigger during analysis,
-        // disabling candidates during codegen is also questionable.
-        if let TypingMode::Coherence = self.infcx.typing_mode() {
-            return None;
-        }
-
-        let tcx = self.tcx();
-        if tcx.features().trait_upcasting() {
-            return None;
-        }
-
-        // <ty as Deref>
-        let trait_ref = ty::TraitRef::new(tcx, tcx.lang_items().deref_trait()?, [ty]);
-
-        let obligation =
-            traits::Obligation::new(tcx, cause.clone(), param_env, ty::Binder::dummy(trait_ref));
-        if !self.infcx.predicate_may_hold(&obligation) {
-            return None;
-        }
-
-        self.infcx.probe(|_| {
-            let ty = traits::normalize_projection_ty(
-                self,
-                param_env,
-                ty::AliasTy::new_from_args(tcx, tcx.lang_items().deref_target()?, trait_ref.args),
-                cause.clone(),
-                0,
-                // We're *intentionally* throwing these away,
-                // since we don't actually use them.
-                &mut PredicateObligations::new(),
-            )
-            .as_type()
-            .unwrap();
-
-            if let ty::Dynamic(data, ..) = ty.kind() { data.principal() } else { None }
-        })
-    }
-
     /// Searches for unsizing that might apply to `obligation`.
     fn assemble_candidates_for_unsizing(
         &mut self,
@@ -1019,15 +967,6 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     let principal_a = a_data.principal().unwrap();
                     let target_trait_did = principal_def_id_b.unwrap();
                     let source_trait_ref = principal_a.with_self_ty(self.tcx(), source);
-                    if let Some(deref_trait_ref) = self.need_migrate_deref_output_trait_object(
-                        source,
-                        obligation.param_env,
-                        &obligation.cause,
-                    ) {
-                        if deref_trait_ref.def_id() == target_trait_did {
-                            return;
-                        }
-                    }
 
                     for (idx, upcast_trait_ref) in
                         util::supertraits(self.tcx(), source_trait_ref).enumerate()
diff --git a/compiler/rustc_transmute/src/lib.rs b/compiler/rustc_transmute/src/lib.rs
index a50cc8f5932..f9537f708ef 100644
--- a/compiler/rustc_transmute/src/lib.rs
+++ b/compiler/rustc_transmute/src/lib.rs
@@ -84,7 +84,7 @@ mod rustc {
     use rustc_infer::infer::InferCtxt;
     use rustc_macros::TypeVisitable;
     use rustc_middle::traits::ObligationCause;
-    use rustc_middle::ty::{Const, ParamEnv, Ty, TyCtxt, ValTree};
+    use rustc_middle::ty::{Const, ParamEnv, Ty, TyCtxt};
 
     use super::*;
 
@@ -139,25 +139,21 @@ mod rustc {
 
             let adt_def = cv.ty.ty_adt_def()?;
 
-            assert_eq!(
-                tcx.require_lang_item(LangItem::TransmuteOpts, None),
-                adt_def.did(),
-                "The given `Const` was not marked with the `{}` lang item.",
-                LangItem::TransmuteOpts.name(),
-            );
+            if !tcx.is_lang_item(adt_def.did(), LangItem::TransmuteOpts) {
+                tcx.dcx().delayed_bug(format!(
+                    "The given `const` was not marked with the `{}` lang item.",
+                    LangItem::TransmuteOpts.name()
+                ));
+                return Some(Self {
+                    alignment: true,
+                    lifetimes: true,
+                    safety: true,
+                    validity: true,
+                });
+            }
 
             let variant = adt_def.non_enum_variant();
-            let fields = match cv.valtree {
-                ValTree::Branch(branch) => branch,
-                _ => {
-                    return Some(Self {
-                        alignment: true,
-                        lifetimes: true,
-                        safety: true,
-                        validity: true,
-                    });
-                }
-            };
+            let fields = cv.valtree.unwrap_branch();
 
             let get_field = |name| {
                 let (field_idx, _) = variant
diff --git a/compiler/rustc_type_ir/src/solve/mod.rs b/compiler/rustc_type_ir/src/solve/mod.rs
index c06004d4d0f..a562b751d8a 100644
--- a/compiler/rustc_type_ir/src/solve/mod.rs
+++ b/compiler/rustc_type_ir/src/solve/mod.rs
@@ -179,9 +179,7 @@ pub enum BuiltinImplSource {
     Object(usize),
     /// A built-in implementation of `Upcast` for trait objects to other trait objects.
     ///
-    /// This can be removed when `feature(dyn_upcasting)` is stabilized, since we only
-    /// use it to detect when upcasting traits in hir typeck. The index is only used
-    /// for winnowing.
+    /// The index is only used for winnowing.
     TraitUpcasting(usize),
     /// Unsizing a tuple like `(A, B, ..., X)` to `(A, B, ..., Y)` if `X` unsizes to `Y`.
     ///
diff --git a/library/alloc/tests/str.rs b/library/alloc/tests/str.rs
index 6f930ab0853..5720d3ffd97 100644
--- a/library/alloc/tests/str.rs
+++ b/library/alloc/tests/str.rs
@@ -2297,21 +2297,21 @@ fn utf8_chars() {
     assert_eq!(schs.len(), 4);
     assert_eq!(schs.iter().cloned().collect::<String>(), s);
 
-    assert!((from_utf8(s.as_bytes()).is_ok()));
+    assert!(from_utf8(s.as_bytes()).is_ok());
     // invalid prefix
-    assert!((!from_utf8(&[0x80]).is_ok()));
+    assert!(!from_utf8(&[0x80]).is_ok());
     // invalid 2 byte prefix
-    assert!((!from_utf8(&[0xc0]).is_ok()));
-    assert!((!from_utf8(&[0xc0, 0x10]).is_ok()));
+    assert!(!from_utf8(&[0xc0]).is_ok());
+    assert!(!from_utf8(&[0xc0, 0x10]).is_ok());
     // invalid 3 byte prefix
-    assert!((!from_utf8(&[0xe0]).is_ok()));
-    assert!((!from_utf8(&[0xe0, 0x10]).is_ok()));
-    assert!((!from_utf8(&[0xe0, 0xff, 0x10]).is_ok()));
+    assert!(!from_utf8(&[0xe0]).is_ok());
+    assert!(!from_utf8(&[0xe0, 0x10]).is_ok());
+    assert!(!from_utf8(&[0xe0, 0xff, 0x10]).is_ok());
     // invalid 4 byte prefix
-    assert!((!from_utf8(&[0xf0]).is_ok()));
-    assert!((!from_utf8(&[0xf0, 0x10]).is_ok()));
-    assert!((!from_utf8(&[0xf0, 0xff, 0x10]).is_ok()));
-    assert!((!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok()));
+    assert!(!from_utf8(&[0xf0]).is_ok());
+    assert!(!from_utf8(&[0xf0, 0x10]).is_ok());
+    assert!(!from_utf8(&[0xf0, 0xff, 0x10]).is_ok());
+    assert!(!from_utf8(&[0xf0, 0xff, 0xff, 0x10]).is_ok());
 }
 
 #[test]
diff --git a/library/coretests/tests/bool.rs b/library/coretests/tests/bool.rs
index 47f6459915b..bcd6dc2abac 100644
--- a/library/coretests/tests/bool.rs
+++ b/library/coretests/tests/bool.rs
@@ -71,14 +71,14 @@ fn test_bool() {
 #[test]
 pub fn test_bool_not() {
     if !false {
-        assert!((true));
+        assert!(true);
     } else {
-        assert!((false));
+        assert!(false);
     }
     if !true {
-        assert!((false));
+        assert!(false);
     } else {
-        assert!((true));
+        assert!(true);
     }
 }
 
diff --git a/library/coretests/tests/lib.rs b/library/coretests/tests/lib.rs
index 7fe72862608..f1bbed3de30 100644
--- a/library/coretests/tests/lib.rs
+++ b/library/coretests/tests/lib.rs
@@ -81,7 +81,6 @@
 #![feature(strict_provenance_atomic_ptr)]
 #![feature(strict_provenance_lints)]
 #![feature(test)]
-#![feature(trait_upcasting)]
 #![feature(trusted_len)]
 #![feature(trusted_random_access)]
 #![feature(try_blocks)]
diff --git a/library/coretests/tests/ptr.rs b/library/coretests/tests/ptr.rs
index 7cefb615d03..345bec345d1 100644
--- a/library/coretests/tests/ptr.rs
+++ b/library/coretests/tests/ptr.rs
@@ -42,11 +42,11 @@ fn test() {
         let mut v1 = vec![0u16, 0u16, 0u16];
 
         copy(v0.as_ptr().offset(1), v1.as_mut_ptr().offset(1), 1);
-        assert!((v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16));
+        assert!(v1[0] == 0u16 && v1[1] == 32001u16 && v1[2] == 0u16);
         copy(v0.as_ptr().offset(2), v1.as_mut_ptr(), 1);
-        assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16));
+        assert!(v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 0u16);
         copy(v0.as_ptr(), v1.as_mut_ptr().offset(2), 1);
-        assert!((v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16));
+        assert!(v1[0] == 32002u16 && v1[1] == 32001u16 && v1[2] == 32000u16);
     }
 }
 
diff --git a/library/std/src/io/cursor.rs b/library/std/src/io/cursor.rs
index b2ffeb0f95d..606099c8bc6 100644
--- a/library/std/src/io/cursor.rs
+++ b/library/std/src/io/cursor.rs
@@ -153,7 +153,7 @@ impl<T> Cursor<T> {
     /// let reference = buff.get_mut();
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_mut_cursor", issue = "130801")]
+    #[rustc_const_stable(feature = "const_mut_cursor", since = "CURRENT_RUSTC_VERSION")]
     pub const fn get_mut(&mut self) -> &mut T {
         &mut self.inner
     }
@@ -201,7 +201,7 @@ impl<T> Cursor<T> {
     /// assert_eq!(buff.position(), 4);
     /// ```
     #[stable(feature = "rust1", since = "1.0.0")]
-    #[rustc_const_unstable(feature = "const_mut_cursor", issue = "130801")]
+    #[rustc_const_stable(feature = "const_mut_cursor", since = "CURRENT_RUSTC_VERSION")]
     pub const fn set_position(&mut self, pos: u64) {
         self.pos = pos;
     }
diff --git a/library/std/tests/istr.rs b/library/std/tests/istr.rs
index 9a127ae803e..e481872977a 100644
--- a/library/std/tests/istr.rs
+++ b/library/std/tests/istr.rs
@@ -5,7 +5,7 @@ fn test_stack_assign() {
     let t: String = "a".to_string();
     assert_eq!(s, t);
     let u: String = "b".to_string();
-    assert!((s != u));
+    assert!(s != u);
 }
 
 #[test]
@@ -19,7 +19,7 @@ fn test_heap_assign() {
     let t: String = "a big ol' string".to_string();
     assert_eq!(s, t);
     let u: String = "a bad ol' string".to_string();
-    assert!((s != u));
+    assert!(s != u);
 }
 
 #[test]
diff --git a/library/std/tests/seq-compare.rs b/library/std/tests/seq-compare.rs
index 221f1c7cabd..ec39c5b603c 100644
--- a/library/std/tests/seq-compare.rs
+++ b/library/std/tests/seq-compare.rs
@@ -1,15 +1,15 @@
 #[test]
 fn seq_compare() {
-    assert!(("hello".to_string() < "hellr".to_string()));
-    assert!(("hello ".to_string() > "hello".to_string()));
-    assert!(("hello".to_string() != "there".to_string()));
-    assert!((vec![1, 2, 3, 4] > vec![1, 2, 3]));
-    assert!((vec![1, 2, 3] < vec![1, 2, 3, 4]));
-    assert!((vec![1, 2, 4, 4] > vec![1, 2, 3, 4]));
-    assert!((vec![1, 2, 3, 4] < vec![1, 2, 4, 4]));
-    assert!((vec![1, 2, 3] <= vec![1, 2, 3]));
-    assert!((vec![1, 2, 3] <= vec![1, 2, 3, 3]));
-    assert!((vec![1, 2, 3, 4] > vec![1, 2, 3]));
+    assert!("hello".to_string() < "hellr".to_string());
+    assert!("hello ".to_string() > "hello".to_string());
+    assert!("hello".to_string() != "there".to_string());
+    assert!(vec![1, 2, 3, 4] > vec![1, 2, 3]);
+    assert!(vec![1, 2, 3] < vec![1, 2, 3, 4]);
+    assert!(vec![1, 2, 4, 4] > vec![1, 2, 3, 4]);
+    assert!(vec![1, 2, 3, 4] < vec![1, 2, 4, 4]);
+    assert!(vec![1, 2, 3] <= vec![1, 2, 3]);
+    assert!(vec![1, 2, 3] <= vec![1, 2, 3, 3]);
+    assert!(vec![1, 2, 3, 4] > vec![1, 2, 3]);
     assert_eq!(vec![1, 2, 3], vec![1, 2, 3]);
-    assert!((vec![1, 2, 3] != vec![1, 1, 3]));
+    assert!(vec![1, 2, 3] != vec![1, 1, 3]);
 }
diff --git a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
index 6c9071b4191..03ec77f507e 100644
--- a/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-various-2/Dockerfile
@@ -56,9 +56,9 @@ ENV \
     CFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
     CXX_x86_64_fortanix_unknown_sgx=clang++-11 \
     CXXFLAGS_x86_64_fortanix_unknown_sgx="-D__ELF__ -isystem/usr/include/x86_64-linux-gnu -mlvi-hardening -mllvm -x86-experimental-lvi-inline-asm-hardening" \
-    AR_i686_unknown_freebsd=i686-unknown-freebsd13-ar \
-    CC_i686_unknown_freebsd=i686-unknown-freebsd13-clang \
-    CXX_i686_unknown_freebsd=i686-unknown-freebsd13-clang++ \
+    AR_i686_unknown_freebsd=i686-unknown-freebsd12-ar \
+    CC_i686_unknown_freebsd=i686-unknown-freebsd12-clang \
+    CXX_i686_unknown_freebsd=i686-unknown-freebsd12-clang++ \
     CC_aarch64_unknown_uefi=clang-11 \
     CXX_aarch64_unknown_uefi=clang++-11 \
     CC_i686_unknown_uefi=clang-11 \
diff --git a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
index fd0f5da8c49..f42e6f770eb 100644
--- a/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
+++ b/src/ci/docker/host-x86_64/dist-x86_64-freebsd/Dockerfile
@@ -29,9 +29,9 @@ COPY scripts/cmake.sh /scripts/
 RUN /scripts/cmake.sh
 
 ENV \
-    AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-ar \
-    CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-clang \
-    CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd13-clang++
+    AR_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-ar \
+    CC_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-clang \
+    CXX_x86_64_unknown_freebsd=x86_64-unknown-freebsd12-clang++
 
 ENV HOSTS=x86_64-unknown-freebsd
 
diff --git a/src/ci/docker/scripts/freebsd-toolchain.sh b/src/ci/docker/scripts/freebsd-toolchain.sh
index b927658b4fd..0d02636db91 100755
--- a/src/ci/docker/scripts/freebsd-toolchain.sh
+++ b/src/ci/docker/scripts/freebsd-toolchain.sh
@@ -5,8 +5,8 @@ set -eux
 
 arch=$1
 binutils_version=2.40
-freebsd_version=13.4
-triple=$arch-unknown-freebsd13
+freebsd_version=12.3
+triple=$arch-unknown-freebsd12
 sysroot=/usr/local/$triple
 
 hide_output() {
@@ -59,7 +59,7 @@ done
 
 # Originally downloaded from:
 # URL=https://download.freebsd.org/ftp/releases/${freebsd_arch}/${freebsd_version}-RELEASE/base.txz
-URL=https://ci-mirrors.rust-lang.org/rustc/2024-09-13-freebsd-${freebsd_version}-${freebsd_arch}-base.txz
+URL=https://ci-mirrors.rust-lang.org/rustc/2022-05-06-freebsd-${freebsd_version}-${freebsd_arch}-base.txz
 curl "$URL" | tar xJf - -C "$sysroot" --wildcards "${files_to_extract[@]}"
 
 # Clang can do cross-builds out of the box, if we give it the right
diff --git a/src/doc/unstable-book/src/language-features/trait-upcasting.md b/src/doc/unstable-book/src/language-features/trait-upcasting.md
deleted file mode 100644
index a5f99cc86f2..00000000000
--- a/src/doc/unstable-book/src/language-features/trait-upcasting.md
+++ /dev/null
@@ -1,26 +0,0 @@
-# `trait_upcasting`
-
-The tracking issue for this feature is: [#65991]
-
-[#65991]: https://github.com/rust-lang/rust/issues/65991
-
-------------------------
-
-The `trait_upcasting` feature adds support for trait upcasting coercion. This allows a
-trait object of type `dyn Bar` to be cast to a trait object of type `dyn Foo`
-so long as `Bar: Foo`.
-
-```rust,edition2018
-#![feature(trait_upcasting)]
-
-trait Foo {}
-
-trait Bar: Foo {}
-
-impl Foo for i32 {}
-
-impl<T: Foo + ?Sized> Bar for T {}
-
-let bar: &dyn Bar = &123;
-let foo: &dyn Foo = bar;
-```
diff --git a/src/tools/miri/src/lib.rs b/src/tools/miri/src/lib.rs
index feab5a9a2f7..8c4b15a65c1 100644
--- a/src/tools/miri/src/lib.rs
+++ b/src/tools/miri/src/lib.rs
@@ -1,3 +1,4 @@
+#![cfg_attr(bootstrap, feature(trait_upcasting))]
 #![feature(rustc_private)]
 #![feature(cfg_match)]
 #![feature(cell_update)]
@@ -10,7 +11,6 @@
 #![feature(yeet_expr)]
 #![feature(nonzero_ops)]
 #![feature(let_chains)]
-#![feature(trait_upcasting)]
 #![feature(strict_overflow_ops)]
 #![feature(pointer_is_aligned_to)]
 #![feature(unqualified_local_imports)]
diff --git a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
index f450e7e652c..1fd791a91f0 100644
--- a/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
+++ b/src/tools/miri/tests/fail/dyn-upcast-trait-mismatch.rs
@@ -1,9 +1,6 @@
 // Validation stops this too early.
 //@compile-flags: -Zmiri-disable-validation
 
-#![feature(trait_upcasting)]
-#![allow(incomplete_features)]
-
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     #[allow(dead_code)]
     fn a(&self) -> i32 {
diff --git a/src/tools/miri/tests/pass/binops.rs b/src/tools/miri/tests/pass/binops.rs
index 0988d7ccc4c..0aff7acb29d 100644
--- a/src/tools/miri/tests/pass/binops.rs
+++ b/src/tools/miri/tests/pass/binops.rs
@@ -2,23 +2,23 @@
 
 fn test_nil() {
     assert_eq!((), ());
-    assert!((!(() != ())));
-    assert!((!(() < ())));
-    assert!((() <= ()));
-    assert!((!(() > ())));
-    assert!((() >= ()));
+    assert!(!(() != ()));
+    assert!(!(() < ()));
+    assert!(() <= ());
+    assert!(!(() > ()));
+    assert!(() >= ());
 }
 
 fn test_bool() {
-    assert!((!(true < false)));
-    assert!((!(true <= false)));
-    assert!((true > false));
-    assert!((true >= false));
+    assert!(!(true < false));
+    assert!(!(true <= false));
+    assert!(true > false);
+    assert!(true >= false);
 
-    assert!((false < true));
-    assert!((false <= true));
-    assert!((!(false > true)));
-    assert!((!(false >= true)));
+    assert!(false < true);
+    assert!(false <= true);
+    assert!(!(false > true));
+    assert!(!(false >= true));
 
     // Bools support bitwise binops
     assert_eq!(false & false, false);
@@ -65,9 +65,9 @@ fn test_class() {
 
     assert_eq!(q, r);
     r.y = 17;
-    assert!((r.y != q.y));
+    assert!(r.y != q.y);
     assert_eq!(r.y, 17);
-    assert!((q != r));
+    assert!(q != r);
 }
 
 pub fn main() {
diff --git a/src/tools/miri/tests/pass/box-custom-alloc.rs b/src/tools/miri/tests/pass/box-custom-alloc.rs
index 71ce019187c..f0614313e50 100644
--- a/src/tools/miri/tests/pass/box-custom-alloc.rs
+++ b/src/tools/miri/tests/pass/box-custom-alloc.rs
@@ -1,7 +1,6 @@
 //@revisions: stack tree
 //@[tree]compile-flags: -Zmiri-tree-borrows
-#![allow(incomplete_features)] // for trait upcasting
-#![feature(allocator_api, trait_upcasting)]
+#![feature(allocator_api)]
 
 use std::alloc::{AllocError, Allocator, Layout};
 use std::cell::Cell;
diff --git a/src/tools/miri/tests/pass/dyn-upcast.rs b/src/tools/miri/tests/pass/dyn-upcast.rs
index f100c4d6a86..6f8adc09640 100644
--- a/src/tools/miri/tests/pass/dyn-upcast.rs
+++ b/src/tools/miri/tests/pass/dyn-upcast.rs
@@ -1,6 +1,3 @@
-#![feature(trait_upcasting)]
-#![allow(incomplete_features)]
-
 use std::fmt;
 
 fn main() {
diff --git a/src/tools/publish_toolstate.py b/src/tools/publish_toolstate.py
index a639dc20a60..3688513987d 100755
--- a/src/tools/publish_toolstate.py
+++ b/src/tools/publish_toolstate.py
@@ -30,13 +30,18 @@ except ImportError:
 # These should be collaborators of the rust-lang/rust repository (with at least
 # read privileges on it). CI will fail otherwise.
 MAINTAINERS = {
-    "book": {"carols10cents"},
-    "nomicon": {"frewsxcv", "Gankra", "JohnTitor"},
-    "reference": {"Havvy", "matthewjasper", "ehuss"},
-    "rust-by-example": {"marioidival"},
-    "embedded-book": {"adamgreig", "andre-richter", "jamesmunns", "therealprof"},
+    "book": {"ehuss", "chriskrycho", "carols10cents"},
+    "nomicon": {"ehuss", "JohnTitor"},
+    "reference": {"ehuss"},
+    "rust-by-example": {"ehuss", "marioidival"},
+    "embedded-book": {
+        "ehuss",
+        "adamgreig",
+        "andre-richter",
+        "jamesmunns",
+        "therealprof",
+    },
     "edition-guide": {"ehuss"},
-    "rustc-dev-guide": {"spastorino", "amanjeev", "JohnTitor"},
 }
 
 LABELS = {
@@ -46,7 +51,6 @@ LABELS = {
     "rust-by-example": ["C-bug"],
     "embedded-book": ["C-bug"],
     "edition-guide": ["C-bug"],
-    "rustc-dev-guide": ["C-bug"],
 }
 
 REPOS = {
@@ -56,7 +60,6 @@ REPOS = {
     "rust-by-example": "https://github.com/rust-lang/rust-by-example",
     "embedded-book": "https://github.com/rust-embedded/book",
     "edition-guide": "https://github.com/rust-lang/edition-guide",
-    "rustc-dev-guide": "https://github.com/rust-lang/rustc-dev-guide",
 }
 
 
diff --git a/tests/codegen/vtable-upcast.rs b/tests/codegen/vtable-upcast.rs
index ae7b4bf7aee..9e13e8dd68a 100644
--- a/tests/codegen/vtable-upcast.rs
+++ b/tests/codegen/vtable-upcast.rs
@@ -2,7 +2,6 @@
 //@ compile-flags: -C no-prepopulate-passes -Copt-level=0
 
 #![crate_type = "lib"]
-#![feature(trait_upcasting)]
 
 pub trait Base {
     fn base(&self);
diff --git a/tests/crashes/131886.rs b/tests/crashes/131886.rs
index c31c2d6aa8b..2c692dfb777 100644
--- a/tests/crashes/131886.rs
+++ b/tests/crashes/131886.rs
@@ -1,6 +1,6 @@
 //@ known-bug: #131886
 //@ compile-flags: -Zvalidate-mir --crate-type=lib
-#![feature(trait_upcasting, type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
 
 type Tait = impl Sized;
 
diff --git a/tests/crashes/134336.rs b/tests/crashes/134336.rs
deleted file mode 100644
index 14b88e14f04..00000000000
--- a/tests/crashes/134336.rs
+++ /dev/null
@@ -1,11 +0,0 @@
-//@ known-bug: #134336
-#![expect(incomplete_features)]
-#![feature(explicit_tail_calls)]
-
-trait Tr {
-    fn f();
-}
-
-fn g<T: Tr>() {
-    become T::f();
-}
diff --git a/tests/ui/binding/expr-match-generic.rs b/tests/ui/binding/expr-match-generic.rs
index 975eec42fd0..dcc069b9fb3 100644
--- a/tests/ui/binding/expr-match-generic.rs
+++ b/tests/ui/binding/expr-match-generic.rs
@@ -5,7 +5,7 @@ type compare<T> = extern "Rust" fn(T, T) -> bool;
 
 fn test_generic<T:Clone>(expected: T, eq: compare<T>) {
   let actual: T = match true { true => { expected.clone() }, _ => panic!("wat") };
-    assert!((eq(expected, actual)));
+    assert!(eq(expected, actual));
 }
 
 fn test_bool() {
diff --git a/tests/ui/binding/expr-match.rs b/tests/ui/binding/expr-match.rs
index 049beaaf51b..ce502ae1490 100644
--- a/tests/ui/binding/expr-match.rs
+++ b/tests/ui/binding/expr-match.rs
@@ -1,20 +1,17 @@
 //@ run-pass
 
-
-
-
 // Tests for using match as an expression
 
 fn test_basic() {
     let mut rs: bool = match true { true => { true } false => { false } };
-    assert!((rs));
+    assert!(rs);
     rs = match false { true => { false } false => { true } };
-    assert!((rs));
+    assert!(rs);
 }
 
 fn test_inferrence() {
     let rs = match true { true => { true } false => { false } };
-    assert!((rs));
+    assert!(rs);
 }
 
 fn test_alt_as_alt_head() {
@@ -25,7 +22,7 @@ fn test_alt_as_alt_head() {
           true => { false }
           false => { true }
         };
-    assert!((rs));
+    assert!(rs);
 }
 
 fn test_alt_as_block_result() {
@@ -34,7 +31,7 @@ fn test_alt_as_block_result() {
           true => { false }
           false => { match true { true => { true } false => { false } } }
         };
-    assert!((rs));
+    assert!(rs);
 }
 
 pub fn main() {
diff --git a/tests/ui/binop/binops.rs b/tests/ui/binop/binops.rs
index 0adbb49b14a..7142190a45b 100644
--- a/tests/ui/binop/binops.rs
+++ b/tests/ui/binop/binops.rs
@@ -5,23 +5,23 @@
 
 fn test_nil() {
     assert_eq!((), ());
-    assert!((!(() != ())));
-    assert!((!(() < ())));
-    assert!((() <= ()));
-    assert!((!(() > ())));
-    assert!((() >= ()));
+    assert!(!(() != ()));
+    assert!(!(() < ()));
+    assert!(() <= ());
+    assert!(!(() > ()));
+    assert!(() >= ());
 }
 
 fn test_bool() {
-    assert!((!(true < false)));
-    assert!((!(true <= false)));
-    assert!((true > false));
-    assert!((true >= false));
+    assert!(!(true < false));
+    assert!(!(true <= false));
+    assert!(true > false);
+    assert!(true >= false);
 
-    assert!((false < true));
-    assert!((false <= true));
-    assert!((!(false > true)));
-    assert!((!(false >= true)));
+    assert!(false < true);
+    assert!(false <= true);
+    assert!(!(false > true));
+    assert!(!(false >= true));
 
     // Bools support bitwise binops
     assert_eq!(false & false, false);
@@ -76,9 +76,9 @@ fn test_class() {
   }
   assert_eq!(q, r);
   r.y = 17;
-  assert!((r.y != q.y));
+  assert!(r.y != q.y);
   assert_eq!(r.y, 17);
-  assert!((q != r));
+  assert!(q != r);
 }
 
 pub fn main() {
diff --git a/tests/ui/binop/structured-compare.rs b/tests/ui/binop/structured-compare.rs
index 164760cd7a0..7d1eff45302 100644
--- a/tests/ui/binop/structured-compare.rs
+++ b/tests/ui/binop/structured-compare.rs
@@ -17,14 +17,14 @@ pub fn main() {
     let a = (1, 2, 3);
     let b = (1, 2, 3);
     assert_eq!(a, b);
-    assert!((a != (1, 2, 4)));
-    assert!((a < (1, 2, 4)));
-    assert!((a <= (1, 2, 4)));
-    assert!(((1, 2, 4) > a));
-    assert!(((1, 2, 4) >= a));
+    assert!(a != (1, 2, 4));
+    assert!(a < (1, 2, 4));
+    assert!(a <= (1, 2, 4));
+    assert!((1, 2, 4) > a);
+    assert!((1, 2, 4) >= a);
     let x = foo::large;
     let y = foo::small;
-    assert!((x != y));
+    assert!(x != y);
     assert_eq!(x, foo::large);
-    assert!((x != foo::small));
+    assert!(x != foo::small);
 }
diff --git a/tests/ui/cfg/conditional-compile.rs b/tests/ui/cfg/conditional-compile.rs
index a4f334dd696..dff280054d6 100644
--- a/tests/ui/cfg/conditional-compile.rs
+++ b/tests/ui/cfg/conditional-compile.rs
@@ -85,7 +85,7 @@ pub fn main() {
 pub fn main() {
     // Exercise some of the configured items in ways that wouldn't be possible
     // if they had the FALSE definition
-    assert!((b));
+    assert!(b);
     let _x: t = true;
     let _y: tg = tg::bar;
 
diff --git a/tests/ui/codegen/issue-99551.rs b/tests/ui/codegen/issue-99551.rs
index 9bacbaa6edc..f498718310d 100644
--- a/tests/ui/codegen/issue-99551.rs
+++ b/tests/ui/codegen/issue-99551.rs
@@ -1,5 +1,4 @@
 //@ build-pass
-#![feature(trait_upcasting)]
 
 pub trait A {}
 pub trait B {}
diff --git a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
index a4eb669e321..1702fc1ed49 100644
--- a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
+++ b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.rs
@@ -1,5 +1,5 @@
-#![feature(dyn_star, trait_upcasting)]
-//~^ WARN the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
+#![expect(incomplete_features)]
+#![feature(dyn_star)]
 
 trait A: B {}
 trait B {}
diff --git a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
index 1f7bfb1d5bd..289d85072e6 100644
--- a/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
+++ b/tests/ui/dyn-star/no-unsize-coerce-dyn-trait.stderr
@@ -1,12 +1,3 @@
-warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
-  --> $DIR/no-unsize-coerce-dyn-trait.rs:1:12
-   |
-LL | #![feature(dyn_star, trait_upcasting)]
-   |            ^^^^^^^^
-   |
-   = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
-   = note: `#[warn(incomplete_features)]` on by default
-
 error[E0308]: mismatched types
   --> $DIR/no-unsize-coerce-dyn-trait.rs:11:26
    |
@@ -18,6 +9,6 @@ LL |     let y: Box<dyn* B> = x;
    = note: expected struct `Box<dyn* B>`
               found struct `Box<dyn* A>`
 
-error: aborting due to 1 previous error; 1 warning emitted
+error: aborting due to 1 previous error
 
 For more information about this error, try `rustc --explain E0308`.
diff --git a/tests/ui/dyn-star/upcast.rs b/tests/ui/dyn-star/upcast.rs
index e8e89fc5101..01e1b94f87e 100644
--- a/tests/ui/dyn-star/upcast.rs
+++ b/tests/ui/dyn-star/upcast.rs
@@ -1,6 +1,6 @@
 //@ known-bug: #104800
 
-#![feature(dyn_star, trait_upcasting)]
+#![feature(dyn_star)]
 
 trait Foo: Bar {
     fn hello(&self);
diff --git a/tests/ui/dyn-star/upcast.stderr b/tests/ui/dyn-star/upcast.stderr
index 801e1c233c1..3f244d4b6ae 100644
--- a/tests/ui/dyn-star/upcast.stderr
+++ b/tests/ui/dyn-star/upcast.stderr
@@ -1,7 +1,7 @@
 warning: the feature `dyn_star` is incomplete and may not be safe to use and/or cause compiler crashes
   --> $DIR/upcast.rs:3:12
    |
-LL | #![feature(dyn_star, trait_upcasting)]
+LL | #![feature(dyn_star)]
    |            ^^^^^^^^
    |
    = note: see issue #102425 <https://github.com/rust-lang/rust/issues/102425> for more information
diff --git a/tests/ui/explicit-tail-calls/become-trait-fn.rs b/tests/ui/explicit-tail-calls/become-trait-fn.rs
new file mode 100644
index 00000000000..03255f15dd0
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/become-trait-fn.rs
@@ -0,0 +1,19 @@
+// regression test for <https://github.com/rust-lang/rust/issues/134336>
+// this previously caused an ICE, because we would compare `#[track_caller]` of
+// the callee and the caller (in tailcalls specifically), leading to a problem
+// since `T::f`'s instance can't be resolved (we do not know if the function is
+// or isn't marked with `#[track_caller]`!)
+//
+//@ check-pass
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+
+trait Tr {
+    fn f();
+}
+
+fn g<T: Tr>() {
+    become T::f();
+}
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/callee_is_track_caller.rs b/tests/ui/explicit-tail-calls/callee_is_track_caller.rs
new file mode 100644
index 00000000000..bcb93fda8c8
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/callee_is_track_caller.rs
@@ -0,0 +1,15 @@
+//@ check-pass
+// FIXME(explicit_tail_calls): make this run-pass, once tail calls are properly implemented
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+
+fn a(x: u32) -> u32 {
+    become b(x);
+}
+
+#[track_caller]
+fn b(x: u32) -> u32 { x + 42 }
+
+fn main() {
+    assert_eq!(a(12), 54);
+}
diff --git a/tests/ui/explicit-tail-calls/caller_is_track_caller.rs b/tests/ui/explicit-tail-calls/caller_is_track_caller.rs
new file mode 100644
index 00000000000..4e5f3f12f83
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/caller_is_track_caller.rs
@@ -0,0 +1,16 @@
+#![expect(incomplete_features)]
+#![feature(explicit_tail_calls)]
+
+#[track_caller]
+fn a() {
+    become b(); //~ error: a function marked with `#[track_caller]` cannot perform a tail-call
+}
+
+fn b() {}
+
+#[track_caller]
+fn c() {
+    become a(); //~ error: a function marked with `#[track_caller]` cannot perform a tail-call
+}
+
+fn main() {}
diff --git a/tests/ui/explicit-tail-calls/caller_is_track_caller.stderr b/tests/ui/explicit-tail-calls/caller_is_track_caller.stderr
new file mode 100644
index 00000000000..79b9b45986c
--- /dev/null
+++ b/tests/ui/explicit-tail-calls/caller_is_track_caller.stderr
@@ -0,0 +1,14 @@
+error: a function marked with `#[track_caller]` cannot perform a tail-call
+  --> $DIR/caller_is_track_caller.rs:6:5
+   |
+LL |     become b();
+   |     ^^^^^^^^^^
+
+error: a function marked with `#[track_caller]` cannot perform a tail-call
+  --> $DIR/caller_is_track_caller.rs:13:5
+   |
+LL |     become a();
+   |     ^^^^^^^^^^
+
+error: aborting due to 2 previous errors
+
diff --git a/tests/ui/expr/block.rs b/tests/ui/expr/block.rs
index bf626c9ead3..70f5c274c21 100644
--- a/tests/ui/expr/block.rs
+++ b/tests/ui/expr/block.rs
@@ -4,7 +4,7 @@
 
 // Tests for standalone blocks as expressions
 
-fn test_basic() { let rs: bool = { true }; assert!((rs)); }
+fn test_basic() { let rs: bool = { true }; assert!(rs); }
 
 struct RS { v1: isize, v2: isize }
 
diff --git a/tests/ui/expr/if/expr-if.rs b/tests/ui/expr/if/expr-if.rs
index ae869c4b77a..68c2fc22130 100644
--- a/tests/ui/expr/if/expr-if.rs
+++ b/tests/ui/expr/if/expr-if.rs
@@ -1,43 +1,43 @@
 //@ run-pass
 // Tests for if as expressions
 
-fn test_if() { let rs: bool = if true { true } else { false }; assert!((rs)); }
+fn test_if() { let rs: bool = if true { true } else { false }; assert!(rs); }
 
 fn test_else() {
     let rs: bool = if false { false } else { true };
-    assert!((rs));
+    assert!(rs);
 }
 
 fn test_elseif1() {
     let rs: bool = if true { true } else if true { false } else { false };
-    assert!((rs));
+    assert!(rs);
 }
 
 fn test_elseif2() {
     let rs: bool = if false { false } else if true { true } else { false };
-    assert!((rs));
+    assert!(rs);
 }
 
 fn test_elseif3() {
     let rs: bool = if false { false } else if false { false } else { true };
-    assert!((rs));
+    assert!(rs);
 }
 
 fn test_inferrence() {
     let rs = if true { true } else { false };
-    assert!((rs));
+    assert!(rs);
 }
 
 fn test_if_as_if_condition() {
     let rs1 = if if false { false } else { true } { true } else { false };
-    assert!((rs1));
+    assert!(rs1);
     let rs2 = if if true { false } else { true } { false } else { true };
-    assert!((rs2));
+    assert!(rs2);
 }
 
 fn test_if_as_block_result() {
     let rs = if true { if false { false } else { true } } else { false };
-    assert!((rs));
+    assert!(rs);
 }
 
 pub fn main() {
diff --git a/tests/ui/feature-gates/feature-gate-trait_upcasting.rs b/tests/ui/feature-gates/feature-gate-trait_upcasting.rs
deleted file mode 100644
index e4102f1cfa7..00000000000
--- a/tests/ui/feature-gates/feature-gate-trait_upcasting.rs
+++ /dev/null
@@ -1,13 +0,0 @@
-trait Foo {}
-
-trait Bar: Foo {}
-
-impl Foo for () {}
-
-impl Bar for () {}
-
-fn main() {
-    let bar: &dyn Bar = &();
-    let foo: &dyn Foo = bar;
-    //~^ ERROR trait upcasting coercion is experimental [E0658]
-}
diff --git a/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr b/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr
deleted file mode 100644
index 6fd277ae8cc..00000000000
--- a/tests/ui/feature-gates/feature-gate-trait_upcasting.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: cannot cast `dyn Bar` to `dyn Foo`, trait upcasting coercion is experimental
-  --> $DIR/feature-gate-trait_upcasting.rs:11:25
-   |
-LL |     let foo: &dyn Foo = bar;
-   |                         ^^^
-   |
-   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
-   = help: add `#![feature(trait_upcasting)]` 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: required when coercing `&dyn Bar` into `&dyn Foo`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/for-loop-while/break.rs b/tests/ui/for-loop-while/break.rs
index 77774792262..442e07e148c 100644
--- a/tests/ui/for-loop-while/break.rs
+++ b/tests/ui/for-loop-while/break.rs
@@ -8,18 +8,18 @@ pub fn main() {
     assert_eq!(i, 20);
     let xs = [1, 2, 3, 4, 5, 6];
     for x in &xs {
-        if *x == 3 { break; } assert!((*x <= 3));
+        if *x == 3 { break; } assert!(*x <= 3);
     }
     i = 0;
-    while i < 10 { i += 1; if i % 2 == 0 { continue; } assert!((i % 2 != 0)); }
+    while i < 10 { i += 1; if i % 2 == 0 { continue; } assert!(i % 2 != 0); }
     i = 0;
     loop {
-        i += 1; if i % 2 == 0 { continue; } assert!((i % 2 != 0));
+        i += 1; if i % 2 == 0 { continue; } assert!(i % 2 != 0);
         if i >= 10 { break; }
     }
     let ys = vec![1, 2, 3, 4, 5, 6];
     for x in &ys {
         if *x % 2 == 0 { continue; }
-        assert!((*x % 2 != 0));
+        assert!(*x % 2 != 0);
     }
 }
diff --git a/tests/ui/for-loop-while/while-cont.rs b/tests/ui/for-loop-while/while-cont.rs
index 1640b7e1803..73a08c26f9a 100644
--- a/tests/ui/for-loop-while/while-cont.rs
+++ b/tests/ui/for-loop-while/while-cont.rs
@@ -3,7 +3,7 @@
 pub fn main() {
     let mut i = 1;
     while i > 0 {
-        assert!((i > 0));
+        assert!(i > 0);
         println!("{}", i);
         i -= 1;
         continue;
diff --git a/tests/ui/for-loop-while/while-loop-constraints-2.rs b/tests/ui/for-loop-while/while-loop-constraints-2.rs
index 654f6769902..1d2d9c2ecfe 100644
--- a/tests/ui/for-loop-while/while-loop-constraints-2.rs
+++ b/tests/ui/for-loop-while/while-loop-constraints-2.rs
@@ -11,5 +11,5 @@ pub fn main() {
         while false { x = y; y = z; }
         println!("{}", y);
     }
-    assert!((y == 42 && z == 50));
+    assert!(y == 42 && z == 50);
 }
diff --git a/tests/ui/generics/generic-tag-match.rs b/tests/ui/generics/generic-tag-match.rs
index dd0291e9d87..378b51df287 100644
--- a/tests/ui/generics/generic-tag-match.rs
+++ b/tests/ui/generics/generic-tag-match.rs
@@ -7,7 +7,7 @@ enum foo<T> { arm(T), }
 fn altfoo<T>(f: foo<T>) {
     let mut hit = false;
     match f { foo::arm::<T>(_x) => { println!("in arm"); hit = true; } }
-    assert!((hit));
+    assert!(hit);
 }
 
 pub fn main() { altfoo::<isize>(foo::arm::<isize>(10)); }
diff --git a/tests/ui/impl-trait/unsized_coercion5.old.stderr b/tests/ui/impl-trait/unsized_coercion5.old.stderr
index e56c026b037..72aa92ef6b9 100644
--- a/tests/ui/impl-trait/unsized_coercion5.old.stderr
+++ b/tests/ui/impl-trait/unsized_coercion5.old.stderr
@@ -1,5 +1,5 @@
 error[E0277]: the size for values of type `impl Trait + ?Sized` cannot be known at compilation time
-  --> $DIR/unsized_coercion5.rs:17:32
+  --> $DIR/unsized_coercion5.rs:15:32
    |
 LL |         let y: Box<dyn Send> = x as Box<dyn Trait + Send>;
    |                                ^ doesn't have a size known at compile-time
diff --git a/tests/ui/impl-trait/unsized_coercion5.rs b/tests/ui/impl-trait/unsized_coercion5.rs
index 81f8a6afe9a..51ae4f20671 100644
--- a/tests/ui/impl-trait/unsized_coercion5.rs
+++ b/tests/ui/impl-trait/unsized_coercion5.rs
@@ -5,8 +5,6 @@
 //@[next] compile-flags: -Znext-solver
 //@[next] check-pass
 
-#![feature(trait_upcasting)]
-
 trait Trait {}
 
 impl Trait for u32 {}
diff --git a/tests/ui/iterators/iter-range.rs b/tests/ui/iterators/iter-range.rs
index 9594729c06c..ec993317539 100644
--- a/tests/ui/iterators/iter-range.rs
+++ b/tests/ui/iterators/iter-range.rs
@@ -2,7 +2,7 @@
 
 
 fn range_<F>(a: isize, b: isize, mut it: F) where F: FnMut(isize) {
-    assert!((a < b));
+    assert!(a < b);
     let mut i: isize = a;
     while i < b { it(i); i += 1; }
 }
diff --git a/tests/ui/macros/syntax-extension-source-utils.rs b/tests/ui/macros/syntax-extension-source-utils.rs
index a16ebdc7504..2f88e508058 100644
--- a/tests/ui/macros/syntax-extension-source-utils.rs
+++ b/tests/ui/macros/syntax-extension-source-utils.rs
@@ -16,7 +16,7 @@ pub fn main() {
     assert_eq!(line!(), 16);
     assert_eq!(column!(), 16);
     assert_eq!(indirect_line!(), 18);
-    assert!((file!().ends_with("syntax-extension-source-utils.rs")));
+    assert!(file!().ends_with("syntax-extension-source-utils.rs"));
     assert_eq!(stringify!((2*3) + 5).to_string(), "(2*3) + 5".to_string());
     assert!(include!("syntax-extension-source-utils-files/includeme.\
                       fragment").to_string()
@@ -30,7 +30,7 @@ pub fn main() {
         include_bytes!("syntax-extension-source-utils-files/includeme.fragment")
         [1] == (42 as u8)); // '*'
     // The Windows tests are wrapped in an extra module for some reason
-    assert!((m1::m2::where_am_i().ends_with("m1::m2")));
+    assert!(m1::m2::where_am_i().ends_with("m1::m2"));
 
     assert_eq!((35, "(2*3) + 5"), (line!(), stringify!((2*3) + 5)));
 }
diff --git a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs
new file mode 100644
index 00000000000..9a53358464d
--- /dev/null
+++ b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.rs
@@ -0,0 +1,20 @@
+#![deny(dependency_on_unit_never_type_fallback)]
+
+fn create_ok_default<C>() -> Result<C, ()>
+where
+    C: Default,
+{
+    Ok(C::default())
+}
+
+fn main() -> Result<(), ()> {
+    //~^ ERROR this function depends on never type fallback being `()`
+    //~| WARN this was previously accepted by the compiler but is being phased out
+    let (returned_value, _) = (|| {
+        let created = create_ok_default()?;
+        Ok((created, ()))
+    })()?;
+
+    let _ = format_args!("{:?}", returned_value);
+    Ok(())
+}
diff --git a/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr
new file mode 100644
index 00000000000..3fe642a8401
--- /dev/null
+++ b/tests/ui/never_type/dont-suggest-turbofish-from-expansion.stderr
@@ -0,0 +1,26 @@
+error: this function depends on never type fallback being `()`
+  --> $DIR/dont-suggest-turbofish-from-expansion.rs:10:1
+   |
+LL | fn main() -> Result<(), ()> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = warning: this was previously accepted by the compiler but is being phased out; it will become a hard error in Rust 2024 and in a future release in all editions!
+   = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
+   = help: specify the types explicitly
+note: in edition 2024, the requirement `!: Default` will fail
+  --> $DIR/dont-suggest-turbofish-from-expansion.rs:14:23
+   |
+LL |         let created = create_ok_default()?;
+   |                       ^^^^^^^^^^^^^^^^^^^
+note: the lint level is defined here
+  --> $DIR/dont-suggest-turbofish-from-expansion.rs:1:9
+   |
+LL | #![deny(dependency_on_unit_never_type_fallback)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+help: use `()` annotations to avoid fallback changes
+   |
+LL |         let created: () = create_ok_default()?;
+   |                    ++++
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr
index 04cd2fcafd6..49b966f32ce 100644
--- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr
+++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2015.stderr
@@ -130,10 +130,6 @@ LL |         msg_send!();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
    = help: specify the type explicitly
    = note: this warning originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use `()` annotations to avoid fallback changes
-   |
-LL |             match send_message::<() /* ?0 */>() {
-   |                                  ~~
 
 warning: 10 warnings emitted
 
diff --git a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr
index 7adba2cc709..4d3692a7b04 100644
--- a/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr
+++ b/tests/ui/never_type/lint-never-type-fallback-flowing-into-unsafe.e2024.stderr
@@ -130,10 +130,6 @@ LL |         msg_send!();
    = note: for more information, see <https://doc.rust-lang.org/nightly/edition-guide/rust-2024/never-type-fallback.html>
    = help: specify the type explicitly
    = note: this error originates in the macro `msg_send` (in Nightly builds, run with -Z macro-backtrace for more info)
-help: use `()` annotations to avoid fallback changes
-   |
-LL |             match send_message::<() /* ?0 */>() {
-   |                                  ~~
 
 warning: the type `!` does not permit zero-initialization
   --> $DIR/lint-never-type-fallback-flowing-into-unsafe.rs:12:18
diff --git a/tests/ui/numbers-arithmetic/arith-unsigned.rs b/tests/ui/numbers-arithmetic/arith-unsigned.rs
index 5a285ceca32..4a1bae438ca 100644
--- a/tests/ui/numbers-arithmetic/arith-unsigned.rs
+++ b/tests/ui/numbers-arithmetic/arith-unsigned.rs
@@ -3,22 +3,22 @@
 
 // Unsigned integer operations
 pub fn main() {
-    assert!((0u8 < 255u8));
-    assert!((0u8 <= 255u8));
-    assert!((255u8 > 0u8));
-    assert!((255u8 >= 0u8));
+    assert!(0u8 < 255u8);
+    assert!(0u8 <= 255u8);
+    assert!(255u8 > 0u8);
+    assert!(255u8 >= 0u8);
     assert_eq!(250u8 / 10u8, 25u8);
     assert_eq!(255u8 % 10u8, 5u8);
-    assert!((0u16 < 60000u16));
-    assert!((0u16 <= 60000u16));
-    assert!((60000u16 > 0u16));
-    assert!((60000u16 >= 0u16));
+    assert!(0u16 < 60000u16);
+    assert!(0u16 <= 60000u16);
+    assert!(60000u16 > 0u16);
+    assert!(60000u16 >= 0u16);
     assert_eq!(60000u16 / 10u16, 6000u16);
     assert_eq!(60005u16 % 10u16, 5u16);
-    assert!((0u32 < 4000000000u32));
-    assert!((0u32 <= 4000000000u32));
-    assert!((4000000000u32 > 0u32));
-    assert!((4000000000u32 >= 0u32));
+    assert!(0u32 < 4000000000u32);
+    assert!(0u32 <= 4000000000u32);
+    assert!(4000000000u32 > 0u32);
+    assert!(4000000000u32 >= 0u32);
     assert_eq!(4000000000u32 / 10u32, 400000000u32);
     assert_eq!(4000000005u32 % 10u32, 5u32);
     // 64-bit numbers have some flakiness yet. Not tested
diff --git a/tests/ui/numbers-arithmetic/float-nan.rs b/tests/ui/numbers-arithmetic/float-nan.rs
index 7d1af0155da..ee3718f6f93 100644
--- a/tests/ui/numbers-arithmetic/float-nan.rs
+++ b/tests/ui/numbers-arithmetic/float-nan.rs
@@ -2,7 +2,7 @@
 
 pub fn main() {
   let nan: f64 = f64::NAN;
-  assert!((nan).is_nan());
+  assert!(nan.is_nan());
 
   let inf: f64 = f64::INFINITY;
   let neg_inf: f64 = -f64::INFINITY;
diff --git a/tests/ui/numbers-arithmetic/float2.rs b/tests/ui/numbers-arithmetic/float2.rs
index 1b7add01cc6..515220fee9f 100644
--- a/tests/ui/numbers-arithmetic/float2.rs
+++ b/tests/ui/numbers-arithmetic/float2.rs
@@ -15,12 +15,12 @@ pub fn main() {
     let j = 3.1e+9f64;
     let k = 3.2e-10f64;
     assert_eq!(a, b);
-    assert!((c < b));
+    assert!(c < b);
     assert_eq!(c, d);
-    assert!((e < g));
-    assert!((f < h));
+    assert!(e < g);
+    assert!(f < h);
     assert_eq!(g, 1000000.0f32);
     assert_eq!(h, i);
-    assert!((j > k));
-    assert!((k < a));
+    assert!(j > k);
+    assert!(k < a);
 }
diff --git a/tests/ui/numbers-arithmetic/floatlits.rs b/tests/ui/numbers-arithmetic/floatlits.rs
index 21f19b69c49..2dab2242011 100644
--- a/tests/ui/numbers-arithmetic/floatlits.rs
+++ b/tests/ui/numbers-arithmetic/floatlits.rs
@@ -4,9 +4,9 @@
 
 pub fn main() {
     let f = 4.999999999999f64;
-    assert!((f > 4.90f64));
-    assert!((f < 5.0f64));
+    assert!(f > 4.90f64);
+    assert!(f < 5.0f64);
     let g = 4.90000000001e-10f64;
-    assert!((g > 5e-11f64));
-    assert!((g < 5e-9f64));
+    assert!(g > 5e-11f64);
+    assert!(g < 5e-9f64);
 }
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 70cdcbd62eb..b7fb70dfd24 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:60:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:54:10
    |
 LL |     let [&mut ref x] = &[&mut 0];
    |          ^^^^^
@@ -10,55 +10,75 @@ help: replace this `&mut` pattern with `&`
 LL |     let [&ref x] = &[&mut 0];
    |          ~
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
    |
 LL |     let [ref mut x] = &[0];
-   |          ^^^^^^^ cannot override to bind by-reference when that is the implicit default
+   |          ^^^^^^^ 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
+   |
+LL |     let [ref mut x] = &[0];
+   |         ^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &[ref mut x] = &[0];
    |         +
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^^^ cannot borrow as mutable
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
    |
 LL |     let [ref x] = &[0];
-   |          ^^^ cannot override to bind by-reference when that is the implicit default
+   |          ^^^ 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
+   |
+LL |     let [ref x] = &[0];
+   |         ^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &[ref x] = &[0];
    |         +
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:88:10
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
    |
 LL |     let [ref x] = &mut [0];
-   |          ^^^ cannot override to bind by-reference when that is the implicit default
+   |          ^^^ 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
+   |
+LL |     let [ref x] = &mut [0];
+   |         ^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut [ref x] = &mut [0];
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:93:10
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
    |
 LL |     let [ref mut x] = &mut [0];
-   |          ^^^^^^^ cannot override to bind by-reference when that is the implicit default
+   |          ^^^^^^^ 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
+   |
+LL |     let [ref mut x] = &mut [0];
+   |         ^^^^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut [ref mut x] = &mut [0];
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 4c88c0c63ae..4e048570c33 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
@@ -13,26 +13,22 @@
 /// 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: this pattern relies on behavior which may change in edition 2024
-    //[structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(stable2021)] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&u32 = x;
 
     let [&ref x] = &mut [&0];
-    //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(stable2021)] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&u32 = x;
 
     let [&mut ref x] = &mut [&mut 0];
-    //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(stable2021)] let _: &u32 = x;
     #[cfg(classic2024)] let _: &&mut u32 = x;
 
     let [&mut ref mut x] = &mut [&mut 0];
-    //[structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(stable2021)] let _: &mut u32 = x;
     #[cfg(classic2024)] let _: &mut &mut u32 = x;
 }
@@ -43,15 +39,13 @@ fn errors_from_eating_the_real_reference_caught_in_hir_typeck_on_stable() {
     let [&ref x] = &[&mut 0];
     //[stable2021]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
-    //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(classic2024)] let _: &&mut u32 = x;
 
     let [&ref x] = &mut [&mut 0];
     //[stable2021]~^ ERROR: mismatched types
     //[stable2021]~| types differ in mutability
-    //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(classic2024)] let _: &&mut u32 = x;
 }
 
@@ -60,8 +54,7 @@ fn errors_dependent_on_eating_order_caught_in_hir_typeck_when_eating_outer() {
     let [&mut ref x] = &[&mut 0];
     //[classic2024]~^ ERROR: mismatched types
     //[classic2024]~| cannot match inherited `&` with `&mut` pattern
-    //[structural2024]~^^^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[structural2024]~^^^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(stable2021)] let _: &u32 = x;
 }
 
@@ -73,25 +66,21 @@ fn errors_dependent_on_eating_order_caught_in_hir_typeck_when_eating_outer() {
 fn borrowck_errors_in_old_editions() {
     let [ref mut x] = &[0];
     //~^ ERROR: cannot borrow data in a `&` reference as mutable
-    //[classic2024,structural2024]~| ERROR: this pattern relies on behavior which may change in edition 2024
-    //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[classic2024,structural2024]~| ERROR: binding modifiers may only be written when the default binding mode is `move`
 }
 
 /// The remaining tests are purely for testing `ref` bindings in the presence of an inherited
 /// reference. These should always fail on edition 2024 and succeed on edition 2021.
 pub fn main() {
     let [ref x] = &[0];
-    //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(stable2021)] let _: &u32 = x;
 
     let [ref x] = &mut [0];
-    //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(stable2021)] let _: &u32 = x;
 
     let [ref mut x] = &mut [0];
-    //[classic2024,structural2024]~^ ERROR: this pattern relies on behavior which may change in edition 2024
-    //[classic2024,structural2024]~| cannot override to bind by-reference when that is the implicit default
+    //[classic2024,structural2024]~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
     #[cfg(stable2021)] 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 a21e4bb5b8f..26095d84605 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:43:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:39: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:50:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:45: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:74:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:67: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.structural2024.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/experimental/ref-binding-on-inh-ref-errors.structural2024.stderr
index ee2c831bfcc..31930e8c033 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,136 +1,191 @@
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move`
   --> $DIR/ref-binding-on-inh-ref-errors.rs:15:11
    |
 LL |     let [&ref x] = &[&0];
-   |           ^^^ cannot override to bind by-reference when that is the implicit default
+   |           ^^^ 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
+   |
+LL |     let [&ref x] = &[&0];
+   |         ^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &[&ref x] = &[&0];
    |         +
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:21:11
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:20:11
    |
 LL |     let [&ref x] = &mut [&0];
-   |           ^^^ cannot override to bind by-reference when that is the implicit default
+   |           ^^^ 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
+   |
+LL |     let [&ref x] = &mut [&0];
+   |         ^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut [&ref x] = &mut [&0];
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:27:15
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:25:15
    |
 LL |     let [&mut ref x] = &mut [&mut 0];
-   |               ^^^ cannot override to bind by-reference when that is the implicit default
+   |               ^^^ 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
+   |
+LL |     let [&mut ref x] = &mut [&mut 0];
+   |         ^^^^^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut [&mut ref x] = &mut [&mut 0];
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:33:15
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:30:15
    |
 LL |     let [&mut ref mut x] = &mut [&mut 0];
-   |               ^^^^^^^ cannot override to bind by-reference when that is the implicit default
+   |               ^^^^^^^ 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
+   |
+LL |     let [&mut ref mut x] = &mut [&mut 0];
+   |         ^^^^^^^^^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut [&mut ref mut x] = &mut [&mut 0];
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:43:11
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:39:11
    |
 LL |     let [&ref x] = &[&mut 0];
-   |           ^^^ cannot override to bind by-reference when that is the implicit default
+   |           ^^^ 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
+   |
+LL |     let [&ref x] = &[&mut 0];
+   |         ^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &[&ref x] = &[&mut 0];
    |         +
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:50:11
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:45:11
    |
 LL |     let [&ref x] = &mut [&mut 0];
-   |           ^^^ cannot override to bind by-reference when that is the implicit default
+   |           ^^^ 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
+   |
+LL |     let [&ref x] = &mut [&mut 0];
+   |         ^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut [&ref x] = &mut [&mut 0];
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:60:15
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:54:15
    |
 LL |     let [&mut ref x] = &[&mut 0];
-   |               ^^^ cannot override to bind by-reference when that is the implicit default
+   |               ^^^ 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
+   |
+LL |     let [&mut ref x] = &[&mut 0];
+   |         ^^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &[&mut ref x] = &[&mut 0];
    |         +
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
    |
 LL |     let [ref mut x] = &[0];
-   |          ^^^^^^^ cannot override to bind by-reference when that is the implicit default
+   |          ^^^^^^^ 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
+   |
+LL |     let [ref mut x] = &[0];
+   |         ^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &[ref mut x] = &[0];
    |         +
 
 error[E0596]: cannot borrow data in a `&` reference as mutable
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:74:10
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:67:10
    |
 LL |     let [ref mut x] = &[0];
    |          ^^^^^^^^^ cannot borrow as mutable
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:75:10
    |
 LL |     let [ref x] = &[0];
-   |          ^^^ cannot override to bind by-reference when that is the implicit default
+   |          ^^^ 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
+   |
+LL |     let [ref x] = &[0];
+   |         ^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &[ref x] = &[0];
    |         +
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:88:10
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:79:10
    |
 LL |     let [ref x] = &mut [0];
-   |          ^^^ cannot override to bind by-reference when that is the implicit default
+   |          ^^^ 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
+   |
+LL |     let [ref x] = &mut [0];
+   |         ^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut [ref x] = &mut [0];
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
-  --> $DIR/ref-binding-on-inh-ref-errors.rs:93:10
+error: binding modifiers may only be written when the default binding mode is `move`
+  --> $DIR/ref-binding-on-inh-ref-errors.rs:83:10
    |
 LL |     let [ref mut x] = &mut [0];
-   |          ^^^^^^^ cannot override to bind by-reference when that is the implicit default
+   |          ^^^^^^^ 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
+   |
+LL |     let [ref mut x] = &mut [0];
+   |         ^^^^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut [ref mut x] = &mut [0];
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
index e2b2c987610..0a22e939496 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.fixed
@@ -23,22 +23,22 @@ fn main() {
     assert_type_eq(x, &mut 0u8);
 
     let &Foo(mut x) = &Foo(0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let &mut Foo(mut x) = &mut Foo(0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
-    let &Foo(ref x) = &Foo(0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    let Foo(x) = &Foo(0);
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, &0u8);
 
     let &mut Foo(ref x) = &mut Foo(0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, &0u8);
 
@@ -55,22 +55,22 @@ fn main() {
     assert_type_eq(x, &0u8);
 
     let &Foo(&x) = &Foo(&0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let &Foo(&mut x) = &Foo(&mut 0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let &mut Foo(&x) = &mut Foo(&0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let &mut Foo(&mut x) = &mut Foo(&mut 0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
@@ -79,25 +79,25 @@ fn main() {
     }
 
     if let &&&&&Some(&x) = &&&&&Some(&0u8) {
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         assert_type_eq(x, 0u8);
     }
 
     if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) {
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         assert_type_eq(x, 0u8);
     }
 
     if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) {
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         assert_type_eq(x, 0u8);
     }
 
     if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) {
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         assert_type_eq(x, &mut 0u8);
     }
@@ -109,20 +109,20 @@ fn main() {
     }
 
     let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 };
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(a, &0u32);
     assert_type_eq(b, 0u32);
 
     let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 };
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(a, 0u32);
     assert_type_eq(b, &&0u32);
     assert_type_eq(c, &&0u32);
 
     if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } =
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) })
     {
@@ -135,10 +135,108 @@ fn main() {
         // The two patterns are the same syntactically, but because they're defined in different
         // editions they don't mean the same thing.
         &(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
-            //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+            //~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
             assert_type_eq(x, 0u32);
             assert_type_eq(y, 0u32);
         }
         _ => {}
     }
+
+    let &mut [&mut &[ref a]] = &mut [&mut &[0]];
+    //~^ ERROR: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+
+    let &[&(_)] = &[&0];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+
+    // NB: Most of the following tests are for possible future improvements to migration suggestions
+
+    // Test removing multiple binding modifiers.
+    let Struct { a, b, c } = &Struct { a: 0, b: 0, c: 0 };
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(c, &0u32);
+
+    // Test that we don't change bindings' modes when removing binding modifiers.
+    let &mut Struct { ref a, ref mut b, ref mut c } = &mut Struct { a: 0, b: 0, c: 0 };
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, &mut 0u32);
+    assert_type_eq(c, &mut 0u32);
+
+    // Test removing multiple reference patterns of various mutabilities, plus a binding modifier.
+    let &mut &Struct { a: &[ref a], b: &mut [&[ref b]], ref c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 };
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &0u32);
+
+    // Test that we don't change bindings' types when removing reference patterns.
+    let &Foo(&ref a) = &Foo(&0);
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+
+    // Test that we don't change bindings' modes when adding reference paterns (caught early).
+    let &(&a, ref b, &[ref c], &mut [&mut (ref d, &[ref e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]);
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, 0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &0u32);
+    assert_type_eq(d, &0u32);
+    assert_type_eq(e, &0u32);
+
+    // Test that we don't change bindings' modes when adding reference patterns (caught late).
+    let &(ref a, &mut [ref b], &[mut c]) = &(0, &mut [0], &[0]);
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, 0u32);
+
+    // Test featuring both additions and removals.
+    let &(&a, &mut (ref b, &[ref c])) = &(&0, &mut (0, &[0]));
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, 0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &0u32);
+
+    // Test that bindings' subpatterns' modes are updated properly.
+    let &[mut a @ ref b] = &[0];
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, 0u32);
+    assert_type_eq(b, &0u32);
+
+    // Test that bindings' subpatterns' modes are checked properly.
+    let &[ref a @ mut b] = &[0];
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, 0u32);
+
+    // Test that we respect bindings' subpatterns' types when rewriting `&ref x` to `x`.
+    let [&Foo(&ref a @ ref b), &Foo(&ref c @ d)] = [&Foo(&0); 2];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &0u32);
+    assert_type_eq(d, 0u32);
+
+    // Test that we respect bindings' subpatterns' modes when rewriting `&ref x` to `x`.
+    let [&Foo(&ref a @ [ref b]), &Foo(&ref c @ [d])] = [&Foo(&[0]); 2];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &[0u32]);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &[0u32]);
+    assert_type_eq(d, 0u32);
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
index 098540adfa2..7a6f2269d44 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.rs
@@ -23,22 +23,22 @@ fn main() {
     assert_type_eq(x, &mut 0u8);
 
     let Foo(mut x) = &Foo(0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let Foo(mut x) = &mut Foo(0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let Foo(ref x) = &Foo(0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, &0u8);
 
     let Foo(ref x) = &mut Foo(0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, &0u8);
 
@@ -55,22 +55,22 @@ fn main() {
     assert_type_eq(x, &0u8);
 
     let Foo(&x) = &Foo(&0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let Foo(&mut x) = &Foo(&mut 0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let Foo(&x) = &mut Foo(&0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
     let Foo(&mut x) = &mut Foo(&mut 0);
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(x, 0u8);
 
@@ -79,25 +79,25 @@ fn main() {
     }
 
     if let Some(&x) = &&&&&Some(&0u8) {
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         assert_type_eq(x, 0u8);
     }
 
     if let Some(&mut x) = &&&&&Some(&mut 0u8) {
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         assert_type_eq(x, 0u8);
     }
 
     if let Some(&x) = &&&&&mut Some(&0u8) {
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         assert_type_eq(x, 0u8);
     }
 
     if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) {
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         assert_type_eq(x, &mut 0u8);
     }
@@ -109,20 +109,20 @@ fn main() {
     }
 
     let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 };
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(a, &0u32);
     assert_type_eq(b, 0u32);
 
     let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 };
-    //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+    //~^ ERROR: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024
     //~| WARN: this changes meaning in Rust 2024
     assert_type_eq(a, 0u32);
     assert_type_eq(b, &&0u32);
     assert_type_eq(c, &&0u32);
 
     if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } =
-        //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+        //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
         //~| WARN: this changes meaning in Rust 2024
         &(Struct { a: &Some(&0), b: &Some(&0), c: &Some(&0) })
     {
@@ -135,10 +135,108 @@ fn main() {
         // The two patterns are the same syntactically, but because they're defined in different
         // editions they don't mean the same thing.
         (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
-            //~^ ERROR: this pattern relies on behavior which may change in edition 2024
+            //~^ ERROR: binding modifiers may only be written when the default binding mode is `move`
             assert_type_eq(x, 0u32);
             assert_type_eq(y, 0u32);
         }
         _ => {}
     }
+
+    let [&mut [ref a]] = &mut [&mut &[0]];
+    //~^ ERROR: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+
+    let [&(_)] = &[&0];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+
+    // NB: Most of the following tests are for possible future improvements to migration suggestions
+
+    // Test removing multiple binding modifiers.
+    let Struct { ref a, ref b, c } = &Struct { a: 0, b: 0, c: 0 };
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(c, &0u32);
+
+    // Test that we don't change bindings' modes when removing binding modifiers.
+    let Struct { ref a, ref mut b, c } = &mut Struct { a: 0, b: 0, c: 0 };
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, &mut 0u32);
+    assert_type_eq(c, &mut 0u32);
+
+    // Test removing multiple reference patterns of various mutabilities, plus a binding modifier.
+    let Struct { a: &[ref a], b: &mut [[b]], c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 };
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &0u32);
+
+    // Test that we don't change bindings' types when removing reference patterns.
+    let Foo(&ref a) = &Foo(&0);
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+
+    // Test that we don't change bindings' modes when adding reference paterns (caught early).
+    let (&a, b, [c], [(d, [e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]);
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, 0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &0u32);
+    assert_type_eq(d, &0u32);
+    assert_type_eq(e, &0u32);
+
+    // Test that we don't change bindings' modes when adding reference patterns (caught late).
+    let (a, [b], [mut c]) = &(0, &mut [0], &[0]);
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, 0u32);
+
+    // Test featuring both additions and removals.
+    let (&a, (b, &[ref c])) = &(&0, &mut (0, &[0]));
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, 0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &0u32);
+
+    // Test that bindings' subpatterns' modes are updated properly.
+    let [mut a @ b] = &[0];
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, 0u32);
+    assert_type_eq(b, &0u32);
+
+    // Test that bindings' subpatterns' modes are checked properly.
+    let [a @ mut b] = &[0];
+    //~^ ERROR: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, 0u32);
+
+    // Test that we respect bindings' subpatterns' types when rewriting `&ref x` to `x`.
+    let [Foo(&ref a @ ref b), Foo(&ref c @ d)] = [&Foo(&0); 2];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &0u32);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &0u32);
+    assert_type_eq(d, 0u32);
+
+    // Test that we respect bindings' subpatterns' modes when rewriting `&ref x` to `x`.
+    let [Foo(&ref a @ [ref b]), Foo(&ref c @ [d])] = [&Foo(&[0]); 2];
+    //~^ ERROR: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+    //~| WARN: this changes meaning in Rust 2024
+    assert_type_eq(a, &[0u32]);
+    assert_type_eq(b, &0u32);
+    assert_type_eq(c, &[0u32]);
+    assert_type_eq(d, 0u32);
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
index 83346b9dd4a..191800df07a 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/migration_lint.stderr
@@ -1,11 +1,16 @@
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:25:13
    |
 LL |     let Foo(mut x) = &Foo(0);
-   |             ^^^ requires binding by-value, but the implicit default is by-reference
+   |             ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:25:9
+   |
+LL |     let Foo(mut x) = &Foo(0);
+   |         ^^^^^^^^^^ this matches on type `&_`
 note: the lint level is defined here
   --> $DIR/migration_lint.rs:7:9
    |
@@ -16,206 +21,546 @@ help: make the implied reference pattern explicit
 LL |     let &Foo(mut x) = &Foo(0);
    |         +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:30:13
    |
 LL |     let Foo(mut x) = &mut Foo(0);
-   |             ^^^ requires binding by-value, but the implicit default is by-reference
+   |             ^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:30:9
+   |
+LL |     let Foo(mut x) = &mut Foo(0);
+   |         ^^^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut Foo(mut x) = &mut Foo(0);
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:35:13
    |
 LL |     let Foo(ref x) = &Foo(0);
-   |             ^^^ cannot override to bind by-reference when that is the implicit default
+   |             ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/migration_lint.rs:35:9
+   |
+LL |     let Foo(ref x) = &Foo(0);
+   |         ^^^^^^^^^^ this matches on type `&_`
+help: remove the unnecessary binding modifier
+   |
+LL -     let Foo(ref x) = &Foo(0);
+LL +     let Foo(x) = &Foo(0);
    |
-LL |     let &Foo(ref x) = &Foo(0);
-   |         +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:40:13
    |
 LL |     let Foo(ref x) = &mut Foo(0);
-   |             ^^^ cannot override to bind by-reference when that is the implicit default
+   |             ^^^ binding modifier not allowed under `ref mut` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:40:9
+   |
+LL |     let Foo(ref x) = &mut Foo(0);
+   |         ^^^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut Foo(ref x) = &mut Foo(0);
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:57:13
    |
 LL |     let Foo(&x) = &Foo(&0);
-   |             ^ cannot implicitly match against multiple layers of reference
+   |             ^ reference pattern not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:57:9
+   |
+LL |     let Foo(&x) = &Foo(&0);
+   |         ^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &Foo(&x) = &Foo(&0);
    |         +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:62:13
    |
 LL |     let Foo(&mut x) = &Foo(&mut 0);
-   |             ^^^^ cannot implicitly match against multiple layers of reference
+   |             ^^^^ reference pattern not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:62:9
+   |
+LL |     let Foo(&mut x) = &Foo(&mut 0);
+   |         ^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |     let &Foo(&mut x) = &Foo(&mut 0);
    |         +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:67:13
    |
 LL |     let Foo(&x) = &mut Foo(&0);
-   |             ^ cannot implicitly match against multiple layers of reference
+   |             ^ reference pattern not allowed under `ref mut` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:67:9
+   |
+LL |     let Foo(&x) = &mut Foo(&0);
+   |         ^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut Foo(&x) = &mut Foo(&0);
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:72:13
    |
 LL |     let Foo(&mut x) = &mut Foo(&mut 0);
-   |             ^^^^ cannot implicitly match against multiple layers of reference
+   |             ^^^^ reference pattern not allowed under `ref mut` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:72:9
+   |
+LL |     let Foo(&mut x) = &mut Foo(&mut 0);
+   |         ^^^^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference pattern explicit
    |
 LL |     let &mut Foo(&mut x) = &mut Foo(&mut 0);
    |         ++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:81:17
    |
 LL |     if let Some(&x) = &&&&&Some(&0u8) {
-   |                 ^ cannot implicitly match against multiple layers of reference
+   |                 ^ reference pattern not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:81:12
+   |
+LL |     if let Some(&x) = &&&&&Some(&0u8) {
+   |            ^^^^^^^^ this matches on type `&_`
 help: make the implied reference patterns explicit
    |
 LL |     if let &&&&&Some(&x) = &&&&&Some(&0u8) {
    |            +++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:87:17
    |
 LL |     if let Some(&mut x) = &&&&&Some(&mut 0u8) {
-   |                 ^^^^ cannot implicitly match against multiple layers of reference
+   |                 ^^^^ reference pattern not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:87:12
+   |
+LL |     if let Some(&mut x) = &&&&&Some(&mut 0u8) {
+   |            ^^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference patterns explicit
    |
 LL |     if let &&&&&Some(&mut x) = &&&&&Some(&mut 0u8) {
    |            +++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:93:17
    |
 LL |     if let Some(&x) = &&&&&mut Some(&0u8) {
-   |                 ^ cannot implicitly match against multiple layers of reference
+   |                 ^ reference pattern not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:93:12
+   |
+LL |     if let Some(&x) = &&&&&mut Some(&0u8) {
+   |            ^^^^^^^^ this matches on type `&_`
 help: make the implied reference patterns explicit
    |
 LL |     if let &&&&&mut Some(&x) = &&&&&mut Some(&0u8) {
    |            ++++++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:99:17
    |
 LL |     if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) {
-   |                 ^^^^ cannot implicitly match against multiple layers of reference
+   |                 ^^^^ reference pattern not allowed under `ref mut` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:99:12
+   |
+LL |     if let Some(&mut Some(Some(x))) = &mut Some(&mut Some(&mut Some(0u8))) {
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&mut _`
 help: make the implied reference patterns and variable binding mode explicit
    |
 LL |     if let &mut Some(&mut Some(&mut Some(ref mut x))) = &mut Some(&mut Some(&mut Some(0u8))) {
    |            ++++                ++++      +++++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:111:21
    |
 LL |     let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 };
-   |                     ^^^ requires binding by-value, but the implicit default is by-reference
+   |                     ^^^ binding modifier not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:111:9
+   |
+LL |     let Struct { a, mut b, c } = &Struct { a: 0, b: 0, c: 0 };
+   |         ^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern and variable binding modes explicit
    |
 LL |     let &Struct { ref a, mut b, ref c } = &Struct { a: 0, b: 0, c: 0 };
    |         +         +++           +++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:117:21
    |
 LL |     let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 };
-   |                     ^      ^^^ cannot override to bind by-reference when that is the implicit default
+   |                     ^      ^^^ binding modifier not allowed under `ref` default binding mode
    |                     |
-   |                     cannot implicitly match against multiple layers of reference
+   |                     reference pattern not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:117:9
+   |
+LL |     let Struct { a: &a, b, ref c } = &Struct { a: &0, b: &0, c: &0 };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern and variable binding mode explicit
    |
 LL |     let &Struct { a: &a, ref b, ref c } = &Struct { a: &0, b: &0, c: &0 };
    |         +                +++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
   --> $DIR/migration_lint.rs:124:24
    |
 LL |     if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } =
-   |                        ^                 ^ cannot implicitly match against multiple layers of reference
+   |                        ^                 ^ reference pattern not allowed under `ref` default binding mode
    |                        |
-   |                        cannot implicitly match against multiple layers of reference
+   |                        reference pattern not allowed under `ref` default binding mode
    |
    = warning: this changes meaning in Rust 2024
    = 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/migration_lint.rs:124:12
+   |
+LL |     if let Struct { a: &Some(a), b: Some(&b), c: Some(c) } =
+   |            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference patterns and variable binding mode explicit
    |
 LL |     if let &Struct { a: &Some(a), b: &Some(&b), c: &Some(ref c) } =
    |            +                         +             +     +++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move`
   --> $DIR/migration_lint.rs:137:15
    |
 LL |         (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
-   |               ^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ default binding mode is reset within expansion
+   |               ^^^     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ occurs within macro expansion
    |               |
-   |               requires binding by-value, but the implicit default is by-reference
+   |               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/migration_lint.rs:137:9
+   |
+LL |         (Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
    = note: this error originates in the macro `migration_lint_macros::mixed_edition_pat` (in Nightly builds, run with -Z macro-backtrace for more info)
 help: make the implied reference pattern explicit
    |
 LL |         &(Some(mut x), migration_lint_macros::mixed_edition_pat!(y)) => {
    |         +
 
-error: aborting due to 16 previous errors
+error: binding modifiers and reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:145:10
+   |
+LL |     let [&mut [ref a]] = &mut [&mut &[0]];
+   |          ^^^^  ^^^ binding modifier not allowed under `ref` default binding mode
+   |          |
+   |          reference pattern not allowed under `ref mut` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:145:15
+   |
+LL |     let [&mut [ref a]] = &mut [&mut &[0]];
+   |               ^^^^^^^ this matches on type `&_`
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/migration_lint.rs:145:9
+   |
+LL |     let [&mut [ref a]] = &mut [&mut &[0]];
+   |         ^^^^^^^^^^^^^^ this matches on type `&mut _`
+help: make the implied reference patterns explicit
+   |
+LL |     let &mut [&mut &[ref a]] = &mut [&mut &[0]];
+   |         ++++       +
+
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:150:10
+   |
+LL |     let [&(_)] = &[&0];
+   |          ^ reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:150:9
+   |
+LL |     let [&(_)] = &[&0];
+   |         ^^^^^^ this matches on type `&_`
+help: make the implied reference pattern explicit
+   |
+LL |     let &[&(_)] = &[&0];
+   |         +
+
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:157:18
+   |
+LL |     let Struct { ref a, ref b, c } = &Struct { a: 0, b: 0, c: 0 };
+   |                  ^^^    ^^^ binding modifier not allowed under `ref` default binding mode
+   |                  |
+   |                  binding modifier not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:157:9
+   |
+LL |     let Struct { ref a, ref b, c } = &Struct { a: 0, b: 0, c: 0 };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: remove the unnecessary binding modifiers
+   |
+LL -     let Struct { ref a, ref b, c } = &Struct { a: 0, b: 0, c: 0 };
+LL +     let Struct { a, b, c } = &Struct { a: 0, b: 0, c: 0 };
+   |
+
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:164:18
+   |
+LL |     let Struct { ref a, ref mut b, c } = &mut Struct { a: 0, b: 0, c: 0 };
+   |                  ^^^    ^^^^^^^ binding modifier not allowed under `ref mut` default binding mode
+   |                  |
+   |                  binding modifier not allowed under `ref mut` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:164:9
+   |
+LL |     let Struct { ref a, ref mut b, c } = &mut Struct { a: 0, b: 0, c: 0 };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&mut _`
+help: make the implied reference pattern and variable binding mode explicit
+   |
+LL |     let &mut Struct { ref a, ref mut b, ref mut c } = &mut Struct { a: 0, b: 0, c: 0 };
+   |         ++++                            +++++++
+
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:172:21
+   |
+LL |     let Struct { a: &[ref a], b: &mut [[b]], c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 };
+   |                     ^            ^^^^ reference pattern not allowed under `ref` default binding mode
+   |                     |
+   |                     reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:172:9
+   |
+LL |     let Struct { a: &[ref a], b: &mut [[b]], c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 };
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference patterns and variable binding modes explicit
+   |
+LL |     let &mut &Struct { a: &[ref a], b: &mut [&[ref b]], ref c } = &mut &Struct { a: &[0], b: &mut [&[0]], c: 0 };
+   |         ++++++                               + +++      +++
+
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:180:13
+   |
+LL |     let Foo(&ref a) = &Foo(&0);
+   |             ^ reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:180:9
+   |
+LL |     let Foo(&ref a) = &Foo(&0);
+   |         ^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference pattern explicit
+   |
+LL |     let &Foo(&ref a) = &Foo(&0);
+   |         +
+
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:186:10
+   |
+LL |     let (&a, b, [c], [(d, [e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]);
+   |          ^ reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:186:9
+   |
+LL |     let (&a, b, [c], [(d, [e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]);
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference patterns and variable binding modes explicit
+   |
+LL |     let &(&a, ref b, &[ref c], &mut [&mut (ref d, &[ref e])]) = &(&0, 0, &[0], &mut [&mut (0, &[0])]);
+   |         +     +++    + +++     ++++  ++++  +++    + +++
+
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:196:19
+   |
+LL |     let (a, [b], [mut c]) = &(0, &mut [0], &[0]);
+   |                   ^^^ binding modifier not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:196:9
+   |
+LL |     let (a, [b], [mut c]) = &(0, &mut [0], &[0]);
+   |         ^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference patterns and variable binding modes explicit
+   |
+LL |     let &(ref a, &mut [ref b], &[mut c]) = &(0, &mut [0], &[0]);
+   |         + +++    ++++  +++     +
+
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:204:10
+   |
+LL |     let (&a, (b, &[ref c])) = &(&0, &mut (0, &[0]));
+   |          ^       ^ reference pattern not allowed under `ref` default binding mode
+   |          |
+   |          reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:204:9
+   |
+LL |     let (&a, (b, &[ref c])) = &(&0, &mut (0, &[0]));
+   |         ^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference patterns and variable binding mode explicit
+   |
+LL |     let &(&a, &mut (ref b, &[ref c])) = &(&0, &mut (0, &[0]));
+   |         +     ++++  +++
+
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:212:10
+   |
+LL |     let [mut a @ b] = &[0];
+   |          ^^^ binding modifier not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:212:9
+   |
+LL |     let [mut a @ b] = &[0];
+   |         ^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference pattern and variable binding mode explicit
+   |
+LL |     let &[mut a @ ref b] = &[0];
+   |         +         +++
+
+error: binding modifiers may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:219:14
+   |
+LL |     let [a @ mut b] = &[0];
+   |              ^^^ binding modifier not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:219:9
+   |
+LL |     let [a @ mut b] = &[0];
+   |         ^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference pattern and variable binding mode explicit
+   |
+LL |     let &[ref a @ mut b] = &[0];
+   |         + +++
+
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:226:14
+   |
+LL |     let [Foo(&ref a @ ref b), Foo(&ref c @ d)] = [&Foo(&0); 2];
+   |              ^                    ^ reference pattern not allowed under `ref` default binding mode
+   |              |
+   |              reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:226:31
+   |
+LL |     let [Foo(&ref a @ ref b), Foo(&ref c @ d)] = [&Foo(&0); 2];
+   |                               ^^^^^^^^^^^^^^^ this matches on type `&_`
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/migration_lint.rs:226:10
+   |
+LL |     let [Foo(&ref a @ ref b), Foo(&ref c @ d)] = [&Foo(&0); 2];
+   |          ^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference patterns explicit
+   |
+LL |     let [&Foo(&ref a @ ref b), &Foo(&ref c @ d)] = [&Foo(&0); 2];
+   |          +                     +
+
+error: reference patterns may only be written when the default binding mode is `move` in Rust 2024
+  --> $DIR/migration_lint.rs:235:14
+   |
+LL |     let [Foo(&ref a @ [ref b]), Foo(&ref c @ [d])] = [&Foo(&[0]); 2];
+   |              ^                      ^ reference pattern not allowed under `ref` default binding mode
+   |              |
+   |              reference pattern not allowed under `ref` default binding mode
+   |
+   = warning: this changes meaning in Rust 2024
+   = 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/migration_lint.rs:235:33
+   |
+LL |     let [Foo(&ref a @ [ref b]), Foo(&ref c @ [d])] = [&Foo(&[0]); 2];
+   |                                 ^^^^^^^^^^^^^^^^^ this matches on type `&_`
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/migration_lint.rs:235:10
+   |
+LL |     let [Foo(&ref a @ [ref b]), Foo(&ref c @ [d])] = [&Foo(&[0]); 2];
+   |          ^^^^^^^^^^^^^^^^^^^^^ this matches on type `&_`
+help: make the implied reference patterns explicit
+   |
+LL |     let [&Foo(&ref a @ [ref b]), &Foo(&ref c @ [d])] = [&Foo(&[0]); 2];
+   |          +                       +
+
+error: aborting due to 29 previous errors
 
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs
index 5ba554fc6e5..4dc04d90aaf 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.rs
@@ -21,17 +21,17 @@ macro_rules! test_pat_on_type {
 }
 
 test_pat_on_type![(&x,): &(T,)]; //~ ERROR mismatched types
-test_pat_on_type![(&x,): &(&T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024
+test_pat_on_type![(&x,): &(&T,)]; //~ ERROR reference patterns may only be written when the default binding mode is `move`
 test_pat_on_type![(&x,): &(&mut T,)]; //~ ERROR mismatched types
 test_pat_on_type![(&mut x,): &(&T,)]; //~ ERROR mismatched types
-test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024
+test_pat_on_type![(&mut x,): &(&mut T,)]; //~ ERROR reference patterns may only be written when the default binding mode is `move`
 test_pat_on_type![(&x,): &&mut &(T,)]; //~ ERROR mismatched types
 test_pat_on_type![Foo { f: (&x,) }: Foo]; //~ ERROR mismatched types
 test_pat_on_type![Foo { f: (&x,) }: &mut Foo]; //~ ERROR mismatched types
-test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR this pattern relies on behavior which may change in edition 2024
-test_pat_on_type![(mut x,): &(T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024
-test_pat_on_type![(ref x,): &(T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024
-test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR this pattern relies on behavior which may change in edition 2024
+test_pat_on_type![Foo { f: &(x,) }: &Foo]; //~ ERROR reference patterns may only be written when the default binding mode is `move`
+test_pat_on_type![(mut x,): &(T,)]; //~ ERROR binding modifiers may only be written when the default binding mode is `move`
+test_pat_on_type![(ref x,): &(T,)]; //~ ERROR binding modifiers may only be written when the default binding mode is `move`
+test_pat_on_type![(ref mut x,): &mut (T,)]; //~ ERROR binding modifiers may only be written when the default binding mode is `move`
 
 fn get<X>() -> X {
     unimplemented!()
@@ -40,6 +40,6 @@ fn get<X>() -> X {
 // Make sure this works even when the underlying type is inferred. This test passes on rust stable.
 fn infer<X: Copy>() -> X {
     match &get() {
-        (&x,) => x, //~ ERROR this pattern relies on behavior which may change in edition 2024
+        (&x,) => x, //~ ERROR reference patterns may only be written when the default binding mode is `move`
     }
 }
diff --git a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr
index affdca1d449..0c6b2ff3a2f 100644
--- a/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr
+++ b/tests/ui/pattern/rfc-3627-match-ergonomics-2024/min_match_ergonomics_fail.stderr
@@ -99,85 +99,122 @@ LL - test_pat_on_type![Foo { f: (&x,) }: &mut Foo];
 LL + test_pat_on_type![Foo { f: (x,) }: &mut Foo];
    |
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move`
   --> $DIR/min_match_ergonomics_fail.rs:24:20
    |
 LL | test_pat_on_type![(&x,): &(&T,)];
-   |                    ^ cannot implicitly match against multiple layers of reference
+   |                    ^ reference pattern 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/min_match_ergonomics_fail.rs:24:19
+   |
+LL | test_pat_on_type![(&x,): &(&T,)];
+   |                   ^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL | test_pat_on_type![&(&x,): &(&T,)];
    |                   +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move`
   --> $DIR/min_match_ergonomics_fail.rs:27:20
    |
 LL | test_pat_on_type![(&mut x,): &(&mut T,)];
-   |                    ^^^^ cannot implicitly match against multiple layers of reference
+   |                    ^^^^ reference pattern 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/min_match_ergonomics_fail.rs:27:19
+   |
+LL | test_pat_on_type![(&mut x,): &(&mut T,)];
+   |                   ^^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL | test_pat_on_type![&(&mut x,): &(&mut T,)];
    |                   +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move`
   --> $DIR/min_match_ergonomics_fail.rs:31:28
    |
 LL | test_pat_on_type![Foo { f: &(x,) }: &Foo];
-   |                            ^ cannot implicitly match against multiple layers of reference
+   |                            ^ reference pattern 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/min_match_ergonomics_fail.rs:31:19
+   |
+LL | test_pat_on_type![Foo { f: &(x,) }: &Foo];
+   |                   ^^^^^^^^^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL | test_pat_on_type![&Foo { f: &(x,) }: &Foo];
    |                   +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move`
   --> $DIR/min_match_ergonomics_fail.rs:32:20
    |
 LL | test_pat_on_type![(mut x,): &(T,)];
-   |                    ^^^ requires binding by-value, but the implicit default is by-reference
+   |                    ^^^ 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/min_match_ergonomics_fail.rs:32:19
+   |
+LL | test_pat_on_type![(mut x,): &(T,)];
+   |                   ^^^^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL | test_pat_on_type![&(mut x,): &(T,)];
    |                   +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move`
   --> $DIR/min_match_ergonomics_fail.rs:33:20
    |
 LL | test_pat_on_type![(ref x,): &(T,)];
-   |                    ^^^ cannot override to bind by-reference when that is the implicit default
+   |                    ^^^ 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
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/min_match_ergonomics_fail.rs:33:19
+   |
+LL | test_pat_on_type![(ref x,): &(T,)];
+   |                   ^^^^^^^^ this matches on type `&_`
+help: remove the unnecessary binding modifier
+   |
+LL - test_pat_on_type![(ref x,): &(T,)];
+LL + test_pat_on_type![(x,): &(T,)];
    |
-LL | test_pat_on_type![&(ref x,): &(T,)];
-   |                   +
 
-error: this pattern relies on behavior which may change in edition 2024
+error: binding modifiers may only be written when the default binding mode is `move`
   --> $DIR/min_match_ergonomics_fail.rs:34:20
    |
 LL | test_pat_on_type![(ref mut x,): &mut (T,)];
-   |                    ^^^^^^^ cannot override to bind by-reference when that is the implicit default
+   |                    ^^^^^^^ 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>
-help: make the implied reference pattern explicit
+note: matching on a reference type with a non-reference pattern changes the default binding mode
+  --> $DIR/min_match_ergonomics_fail.rs:34:19
+   |
+LL | test_pat_on_type![(ref mut x,): &mut (T,)];
+   |                   ^^^^^^^^^^^^ this matches on type `&mut _`
+help: remove the unnecessary binding modifier
+   |
+LL - test_pat_on_type![(ref mut x,): &mut (T,)];
+LL + test_pat_on_type![(x,): &mut (T,)];
    |
-LL | test_pat_on_type![&mut (ref mut x,): &mut (T,)];
-   |                   ++++
 
-error: this pattern relies on behavior which may change in edition 2024
+error: reference patterns may only be written when the default binding mode is `move`
   --> $DIR/min_match_ergonomics_fail.rs:43:10
    |
 LL |         (&x,) => x,
-   |          ^ cannot implicitly match against multiple layers of reference
+   |          ^ reference pattern 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/min_match_ergonomics_fail.rs:43:9
+   |
+LL |         (&x,) => x,
+   |         ^^^^^ this matches on type `&_`
 help: make the implied reference pattern explicit
    |
 LL |         &(&x,) => x,
diff --git a/tests/ui/sanitizer/cfi/supertraits.rs b/tests/ui/sanitizer/cfi/supertraits.rs
index 4bb6177577f..f80b3169188 100644
--- a/tests/ui/sanitizer/cfi/supertraits.rs
+++ b/tests/ui/sanitizer/cfi/supertraits.rs
@@ -1,4 +1,3 @@
-#![feature(trait_upcasting)]
 // Check that super-traits are callable.
 
 //@ revisions: cfi kcfi
diff --git a/tests/ui/structs-enums/class-impl-very-parameterized-trait.rs b/tests/ui/structs-enums/class-impl-very-parameterized-trait.rs
index 0b37192fc3b..6caec1e2034 100644
--- a/tests/ui/structs-enums/class-impl-very-parameterized-trait.rs
+++ b/tests/ui/structs-enums/class-impl-very-parameterized-trait.rs
@@ -102,6 +102,6 @@ pub fn main() {
     let mut spotty: cat<cat_type> = cat::new(2, 57, cat_type::tuxedo);
     for _ in 0_usize..6 { spotty.speak(); }
     assert_eq!(spotty.len(), 8);
-    assert!((spotty.contains_key(&2)));
+    assert!(spotty.contains_key(&2));
     assert_eq!(spotty.get(&3), &cat_type::tuxedo);
 }
diff --git a/tests/ui/structs-enums/class-implement-trait-cross-crate.rs b/tests/ui/structs-enums/class-implement-trait-cross-crate.rs
index 7a5969451cb..781ac6ad10d 100644
--- a/tests/ui/structs-enums/class-implement-trait-cross-crate.rs
+++ b/tests/ui/structs-enums/class-implement-trait-cross-crate.rs
@@ -53,7 +53,7 @@ fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
 pub fn main() {
   let mut nyan = cat(0_usize, 2, "nyan".to_string());
   nyan.eat();
-  assert!((!nyan.eat()));
+  assert!(!nyan.eat());
   for _ in 1_usize..10_usize { nyan.speak(); };
-  assert!((nyan.eat()));
+  assert!(nyan.eat());
 }
diff --git a/tests/ui/structs-enums/class-implement-traits.rs b/tests/ui/structs-enums/class-implement-traits.rs
index 04a7b706edb..3a514ff9d75 100644
--- a/tests/ui/structs-enums/class-implement-traits.rs
+++ b/tests/ui/structs-enums/class-implement-traits.rs
@@ -57,7 +57,7 @@ fn make_speak<C:noisy>(mut c: C) {
 pub fn main() {
     let mut nyan = cat(0_usize, 2, "nyan".to_string());
     nyan.eat();
-    assert!((!nyan.eat()));
+    assert!(!nyan.eat());
     for _ in 1_usize..10_usize {
         make_speak(nyan.clone());
     }
diff --git a/tests/ui/structs-enums/classes-cross-crate.rs b/tests/ui/structs-enums/classes-cross-crate.rs
index 0160d3fd85c..6fb5f2e3cc9 100644
--- a/tests/ui/structs-enums/classes-cross-crate.rs
+++ b/tests/ui/structs-enums/classes-cross-crate.rs
@@ -7,7 +7,7 @@ use cci_class_4::kitties::cat;
 pub fn main() {
     let mut nyan = cat(0_usize, 2, "nyan".to_string());
     nyan.eat();
-    assert!((!nyan.eat()));
+    assert!(!nyan.eat());
     for _ in 1_usize..10_usize { nyan.speak(); };
-    assert!((nyan.eat()));
+    assert!(nyan.eat());
 }
diff --git a/tests/ui/structs-enums/classes.rs b/tests/ui/structs-enums/classes.rs
index d1c1922f4b5..05976f6a759 100644
--- a/tests/ui/structs-enums/classes.rs
+++ b/tests/ui/structs-enums/classes.rs
@@ -45,7 +45,7 @@ fn cat(in_x : usize, in_y : isize, in_name: String) -> cat {
 pub fn main() {
   let mut nyan = cat(0_usize, 2, "nyan".to_string());
   nyan.eat();
-  assert!((!nyan.eat()));
+  assert!(!nyan.eat());
   for _ in 1_usize..10_usize { nyan.speak(); };
-  assert!((nyan.eat()));
+  assert!(nyan.eat());
 }
diff --git a/tests/ui/structs-enums/tag.rs b/tests/ui/structs-enums/tag.rs
index 16e6b2341cf..542b517e66d 100644
--- a/tests/ui/structs-enums/tag.rs
+++ b/tests/ui/structs-enums/tag.rs
@@ -25,6 +25,6 @@ impl PartialEq for colour {
     fn ne(&self, other: &colour) -> bool { !(*self).eq(other) }
 }
 
-fn f() { let x = colour::red(1, 2); let y = colour::green; assert!((x != y)); }
+fn f() { let x = colour::red(1, 2); let y = colour::green; assert!(x != y); }
 
 pub fn main() { f(); }
diff --git a/tests/ui/tail-cps.rs b/tests/ui/tail-cps.rs
index 6305e9ecdbc..fe99dadf795 100644
--- a/tests/ui/tail-cps.rs
+++ b/tests/ui/tail-cps.rs
@@ -1,6 +1,6 @@
 //@ run-pass
 
-fn checktrue(rs: bool) -> bool { assert!((rs)); return true; }
+fn checktrue(rs: bool) -> bool { assert!(rs); return true; }
 
 pub fn main() { let k = checktrue; evenk(42, k); oddk(45, k); }
 
diff --git a/tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs b/tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs
index dc5912b123a..bbf9bafde9f 100644
--- a/tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs
+++ b/tests/ui/traits/next-solver/normalize/normalize-unsize-rhs.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -Znext-solver
 //@ check-pass
-#![feature(trait_upcasting)]
 
 trait A {}
 trait B: A {}
diff --git a/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs b/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs
index ee6a7a0986d..c6094b45775 100644
--- a/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs
+++ b/tests/ui/traits/next-solver/trait-upcast-lhs-needs-normalization.rs
@@ -1,6 +1,5 @@
 //@ check-pass
 //@ compile-flags: -Znext-solver
-#![feature(trait_upcasting)]
 
 pub trait A {}
 pub trait B: A {}
diff --git a/tests/ui/traits/next-solver/upcast-right-substs.rs b/tests/ui/traits/next-solver/upcast-right-substs.rs
index bbb8a039aa7..7a566b59b83 100644
--- a/tests/ui/traits/next-solver/upcast-right-substs.rs
+++ b/tests/ui/traits/next-solver/upcast-right-substs.rs
@@ -1,6 +1,5 @@
 //@ compile-flags: -Znext-solver
 //@ check-pass
-#![feature(trait_upcasting)]
 
 trait Foo: Bar<i32> + Bar<u32> {}
 
diff --git a/tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs b/tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs
index ffc21a4a9ea..5b22fce6311 100644
--- a/tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs
+++ b/tests/ui/traits/trait-upcasting/add-supertrait-auto-traits.rs
@@ -3,8 +3,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(trait_upcasting)]
-
 trait Target {}
 trait Source: Send + Target {}
 
diff --git a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs
index 4a5e445d1ef..927a9d6b94f 100644
--- a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs
+++ b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.rs
@@ -1,4 +1,3 @@
-#![feature(trait_upcasting)]
 #![feature(trait_alias)]
 
 // Although we *elaborate* `T: Alias` to `i32: B`, we should
diff --git a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr
index 99c82b88d9c..1a410519a4e 100644
--- a/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr
+++ b/tests/ui/traits/trait-upcasting/alias-where-clause-isnt-supertrait.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/alias-where-clause-isnt-supertrait.rs:27:5
+  --> $DIR/alias-where-clause-isnt-supertrait.rs:26:5
    |
 LL | fn test(x: &dyn C) -> &dyn B {
    |                       ------ expected `&dyn B` because of return type
diff --git a/tests/ui/traits/trait-upcasting/basic.rs b/tests/ui/traits/trait-upcasting/basic.rs
index 9b9669565ba..0a8d16a42dd 100644
--- a/tests/ui/traits/trait-upcasting/basic.rs
+++ b/tests/ui/traits/trait-upcasting/basic.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(trait_upcasting)]
-
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
index 7f4343dbd2f..0a02784f29c 100644
--- a/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
+++ b/tests/ui/traits/trait-upcasting/correct-supertrait-substitution.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-#![feature(trait_upcasting)]
 
 trait Foo<T: Default + ToString>: Bar<i32> + Bar<T> {}
 trait Bar<T: Default + ToString> {
diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs
deleted file mode 100644
index e4784fa4101..00000000000
--- a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.rs
+++ /dev/null
@@ -1,35 +0,0 @@
-#![deny(deref_into_dyn_supertrait)]
-use std::ops::Deref;
-
-trait Bar<T> {}
-impl<T, U> Bar<U> for T {}
-
-trait Foo: Bar<i32> {
-    fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a);
-}
-
-impl Foo for () {
-    fn as_dyn_bar_u32<'a>(&self) -> &(dyn Bar<u32> + 'a) {
-        self
-    }
-}
-
-impl<'a> Deref for dyn Foo + 'a {
-    //~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
-    //~| WARN this will change its meaning in a future release!
-    type Target = dyn Bar<u32> + 'a;
-
-    fn deref(&self) -> &Self::Target {
-        self.as_dyn_bar_u32()
-    }
-}
-
-fn take_dyn<T>(x: &dyn Bar<T>) -> T {
-    todo!()
-}
-
-fn main() {
-    let x: &dyn Foo = &();
-    let y = take_dyn(x);
-    let z: u32 = y;
-}
diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr b/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr
deleted file mode 100644
index fa93e28c73b..00000000000
--- a/tests/ui/traits/trait-upcasting/deref-upcast-behavioral-change.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error: this `Deref` implementation is covered by an implicit supertrait coercion
-  --> $DIR/deref-upcast-behavioral-change.rs:17:1
-   |
-LL | impl<'a> Deref for dyn Foo + 'a {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
-...
-LL |     type Target = dyn Bar<u32> + 'a;
-   |     -------------------------------- target type is a supertrait of `dyn Foo`
-   |
-   = warning: this will change its meaning in a future release!
-   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
-note: the lint level is defined here
-  --> $DIR/deref-upcast-behavioral-change.rs:1:9
-   |
-LL | #![deny(deref_into_dyn_supertrait)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-shadowing-lint.rs b/tests/ui/traits/trait-upcasting/deref-upcast-shadowing-lint.rs
new file mode 100644
index 00000000000..ab84527edcf
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/deref-upcast-shadowing-lint.rs
@@ -0,0 +1,17 @@
+//@ check-pass
+#![warn(deref_into_dyn_supertrait)]
+use std::ops::Deref;
+
+trait Bar<T> {}
+trait Foo: Bar<i32> {}
+
+impl<'a> Deref for dyn Foo + 'a {
+    //~^ warn: this `Deref` implementation is covered by an implicit supertrait coercion
+    type Target = dyn Bar<u32> + 'a;
+
+    fn deref(&self) -> &Self::Target {
+        todo!()
+    }
+}
+
+fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/deref-upcast-shadowing-lint.stderr b/tests/ui/traits/trait-upcasting/deref-upcast-shadowing-lint.stderr
new file mode 100644
index 00000000000..0d7f957a50e
--- /dev/null
+++ b/tests/ui/traits/trait-upcasting/deref-upcast-shadowing-lint.stderr
@@ -0,0 +1,17 @@
+warning: this `Deref` implementation is covered by an implicit supertrait coercion
+  --> $DIR/deref-upcast-shadowing-lint.rs:8:1
+   |
+LL | impl<'a> Deref for dyn Foo + 'a {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
+LL |
+LL |     type Target = dyn Bar<u32> + 'a;
+   |     -------------------------------- target type is a supertrait of `dyn Foo`
+   |
+note: the lint level is defined here
+  --> $DIR/deref-upcast-shadowing-lint.rs:2:9
+   |
+LL | #![warn(deref_into_dyn_supertrait)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
+
+warning: 1 warning emitted
+
diff --git a/tests/ui/traits/trait-upcasting/diamond.rs b/tests/ui/traits/trait-upcasting/diamond.rs
index 303c99b67bd..c3f15a6d582 100644
--- a/tests/ui/traits/trait-upcasting/diamond.rs
+++ b/tests/ui/traits/trait-upcasting/diamond.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(trait_upcasting)]
-
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/fewer-associated.rs b/tests/ui/traits/trait-upcasting/fewer-associated.rs
index 45e8673b859..c2ea2a09d3a 100644
--- a/tests/ui/traits/trait-upcasting/fewer-associated.rs
+++ b/tests/ui/traits/trait-upcasting/fewer-associated.rs
@@ -4,8 +4,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(trait_upcasting)]
-
 trait A: B {
     type Assoc;
 }
diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs
index c4c070e49fd..9f9bf21b5a9 100644
--- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs
+++ b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ok.rs
@@ -6,8 +6,6 @@
 // Check that we are able to instantiate a binder during trait upcasting,
 // and that it doesn't cause any issues with codegen either.
 
-#![feature(trait_upcasting)]
-
 trait Supertrait<'a, 'b> {}
 trait Subtrait<'a, 'b>: Supertrait<'a, 'b> {}
 
diff --git a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs
index 2cf6fc75e77..af2594b95f3 100644
--- a/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs
+++ b/tests/ui/traits/trait-upcasting/higher-ranked-upcasting-ub.rs
@@ -5,7 +5,7 @@
 // We previously wrongly instantiated binders during trait upcasting,
 // allowing the super trait to be more generic than the sub trait.
 // This was unsound.
-#![feature(trait_upcasting)]
+
 trait Supertrait<'a, 'b> {
     fn cast(&self, x: &'a str) -> &'b str;
 }
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
index 28be189ff1e..596380b0dbb 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.current.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/illegal-upcast-from-impl.rs:17:66
+  --> $DIR/illegal-upcast-from-impl.rs:15:66
    |
 LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
    |                                        -----------------------   ^ expected trait `Super`, found trait `Sub`
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
index 28be189ff1e..596380b0dbb 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.next.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/illegal-upcast-from-impl.rs:17:66
+  --> $DIR/illegal-upcast-from-impl.rs:15:66
    |
 LL | fn illegal(x: &dyn Sub<Assoc = ()>) -> &dyn Super<Assoc = i32> { x }
    |                                        -----------------------   ^ expected trait `Super`, found trait `Sub`
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
index 0c771db4121..43ec4ece429 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-from-impl.rs
@@ -2,8 +2,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(trait_upcasting)]
-
 trait Super {
     type Assoc;
 }
diff --git a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs
index d0418e75fab..2760c1696b5 100644
--- a/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs
+++ b/tests/ui/traits/trait-upcasting/illegal-upcast-to-impl-opaque.rs
@@ -9,8 +9,6 @@
 //@[next] rustc-env:RUST_BACKTRACE=0
 //@ check-pass
 
-#![feature(trait_upcasting)]
-
 trait Super {
     type Assoc;
 }
diff --git a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs
index 79fb643eacd..0103aaa2ac9 100644
--- a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs
+++ b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.rs
@@ -1,6 +1,3 @@
-#![deny(deref_into_dyn_supertrait)]
-#![feature(trait_upcasting)] // remove this and the test compiles
-
 use std::ops::Deref;
 
 trait Bar<T> {}
@@ -32,5 +29,5 @@ fn main() {
     let x: &dyn Foo = &();
     let y = take_dyn(x);
     let z: u32 = y;
-    //~^ ERROR mismatched types
+    //~^ error: mismatched types
 }
diff --git a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr
index 6b6a26d1593..45eabbc723a 100644
--- a/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr
+++ b/tests/ui/traits/trait-upcasting/inference-behavior-change-deref.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/inference-behavior-change-deref.rs:34:18
+  --> $DIR/inference-behavior-change-deref.rs:31:18
    |
 LL |     let z: u32 = y;
    |            ---   ^ expected `u32`, found `i32`
diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.rs b/tests/ui/traits/trait-upcasting/invalid-upcast.rs
index e634bbd5ac6..9269a5e3e9f 100644
--- a/tests/ui/traits/trait-upcasting/invalid-upcast.rs
+++ b/tests/ui/traits/trait-upcasting/invalid-upcast.rs
@@ -1,5 +1,3 @@
-#![feature(trait_upcasting)]
-
 trait Foo {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
index 3aa21ee3ddd..e70b99d28c7 100644
--- a/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
+++ b/tests/ui/traits/trait-upcasting/invalid-upcast.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:53:35
+  --> $DIR/invalid-upcast.rs:51:35
    |
 LL |     let _: &dyn std::fmt::Debug = baz;
    |            --------------------   ^^^ expected trait `Debug`, found trait `Baz`
@@ -10,7 +10,7 @@ LL |     let _: &dyn std::fmt::Debug = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:55:24
+  --> $DIR/invalid-upcast.rs:53:24
    |
 LL |     let _: &dyn Send = baz;
    |            ---------   ^^^ expected trait `Send`, found trait `Baz`
@@ -21,7 +21,7 @@ LL |     let _: &dyn Send = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:57:24
+  --> $DIR/invalid-upcast.rs:55:24
    |
 LL |     let _: &dyn Sync = baz;
    |            ---------   ^^^ expected trait `Sync`, found trait `Baz`
@@ -32,7 +32,7 @@ LL |     let _: &dyn Sync = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:60:25
+  --> $DIR/invalid-upcast.rs:58:25
    |
 LL |     let bar: &dyn Bar = baz;
    |              --------   ^^^ expected trait `Bar`, found trait `Baz`
@@ -43,7 +43,7 @@ LL |     let bar: &dyn Bar = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:62:35
+  --> $DIR/invalid-upcast.rs:60:35
    |
 LL |     let _: &dyn std::fmt::Debug = bar;
    |            --------------------   ^^^ expected trait `Debug`, found trait `Bar`
@@ -54,7 +54,7 @@ LL |     let _: &dyn std::fmt::Debug = bar;
               found reference `&dyn Bar`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:64:24
+  --> $DIR/invalid-upcast.rs:62:24
    |
 LL |     let _: &dyn Send = bar;
    |            ---------   ^^^ expected trait `Send`, found trait `Bar`
@@ -65,7 +65,7 @@ LL |     let _: &dyn Send = bar;
               found reference `&dyn Bar`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:66:24
+  --> $DIR/invalid-upcast.rs:64:24
    |
 LL |     let _: &dyn Sync = bar;
    |            ---------   ^^^ expected trait `Sync`, found trait `Bar`
@@ -76,7 +76,7 @@ LL |     let _: &dyn Sync = bar;
               found reference `&dyn Bar`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:69:25
+  --> $DIR/invalid-upcast.rs:67:25
    |
 LL |     let foo: &dyn Foo = baz;
    |              --------   ^^^ expected trait `Foo`, found trait `Baz`
@@ -87,7 +87,7 @@ LL |     let foo: &dyn Foo = baz;
               found reference `&dyn Baz`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:71:35
+  --> $DIR/invalid-upcast.rs:69:35
    |
 LL |     let _: &dyn std::fmt::Debug = foo;
    |            --------------------   ^^^ expected trait `Debug`, found trait `Foo`
@@ -98,7 +98,7 @@ LL |     let _: &dyn std::fmt::Debug = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:73:24
+  --> $DIR/invalid-upcast.rs:71:24
    |
 LL |     let _: &dyn Send = foo;
    |            ---------   ^^^ expected trait `Send`, found trait `Foo`
@@ -109,7 +109,7 @@ LL |     let _: &dyn Send = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:75:24
+  --> $DIR/invalid-upcast.rs:73:24
    |
 LL |     let _: &dyn Sync = foo;
    |            ---------   ^^^ expected trait `Sync`, found trait `Foo`
@@ -120,7 +120,7 @@ LL |     let _: &dyn Sync = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:78:25
+  --> $DIR/invalid-upcast.rs:76:25
    |
 LL |     let foo: &dyn Foo = bar;
    |              --------   ^^^ expected trait `Foo`, found trait `Bar`
@@ -131,7 +131,7 @@ LL |     let foo: &dyn Foo = bar;
               found reference `&dyn Bar`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:80:35
+  --> $DIR/invalid-upcast.rs:78:35
    |
 LL |     let _: &dyn std::fmt::Debug = foo;
    |            --------------------   ^^^ expected trait `Debug`, found trait `Foo`
@@ -142,7 +142,7 @@ LL |     let _: &dyn std::fmt::Debug = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:82:24
+  --> $DIR/invalid-upcast.rs:80:24
    |
 LL |     let _: &dyn Send = foo;
    |            ---------   ^^^ expected trait `Send`, found trait `Foo`
@@ -153,7 +153,7 @@ LL |     let _: &dyn Send = foo;
               found reference `&dyn Foo`
 
 error[E0308]: mismatched types
-  --> $DIR/invalid-upcast.rs:84:24
+  --> $DIR/invalid-upcast.rs:82:24
    |
 LL |     let _: &dyn Sync = foo;
    |            ---------   ^^^ expected trait `Sync`, found trait `Foo`
diff --git a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
index ef3d366c381..8bf32efbe2e 100644
--- a/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
+++ b/tests/ui/traits/trait-upcasting/issue-11515-upcast-fn_mut-fn.rs
@@ -1,5 +1,4 @@
 //@ run-pass
-#![feature(trait_upcasting)]
 
 struct Test {
     func: Box<dyn FnMut() + 'static>,
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.current.stderr b/tests/ui/traits/trait-upcasting/issue-11515.current.stderr
deleted file mode 100644
index 8ce7d46012f..00000000000
--- a/tests/ui/traits/trait-upcasting/issue-11515.current.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
-  --> $DIR/issue-11515.rs:11:38
-   |
-LL |     let test = Box::new(Test { func: closure });
-   |                                      ^^^^^^^
-   |
-   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
-   = help: add `#![feature(trait_upcasting)]` 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: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.next.stderr b/tests/ui/traits/trait-upcasting/issue-11515.next.stderr
deleted file mode 100644
index 8ce7d46012f..00000000000
--- a/tests/ui/traits/trait-upcasting/issue-11515.next.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: cannot cast `dyn Fn()` to `dyn FnMut()`, trait upcasting coercion is experimental
-  --> $DIR/issue-11515.rs:11:38
-   |
-LL |     let test = Box::new(Test { func: closure });
-   |                                      ^^^^^^^
-   |
-   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
-   = help: add `#![feature(trait_upcasting)]` 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: required when coercing `Box<(dyn Fn() + 'static)>` into `Box<(dyn FnMut() + 'static)>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/trait-upcasting/issue-11515.rs b/tests/ui/traits/trait-upcasting/issue-11515.rs
index d251e804c3e..3b1f0a19cb9 100644
--- a/tests/ui/traits/trait-upcasting/issue-11515.rs
+++ b/tests/ui/traits/trait-upcasting/issue-11515.rs
@@ -1,3 +1,4 @@
+//@ check-pass
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
@@ -8,5 +9,5 @@ struct Test {
 
 fn main() {
     let closure: Box<dyn Fn() + 'static> = Box::new(|| ());
-    let test = Box::new(Test { func: closure }); //~ ERROR trait upcasting coercion is experimental [E0658]
+    let test = Box::new(Test { func: closure });
 }
diff --git a/tests/ui/traits/trait-upcasting/lifetime.rs b/tests/ui/traits/trait-upcasting/lifetime.rs
index ab006f8bedc..a3cbfd777a0 100644
--- a/tests/ui/traits/trait-upcasting/lifetime.rs
+++ b/tests/ui/traits/trait-upcasting/lifetime.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(trait_upcasting)]
-
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/lifetime.stderr b/tests/ui/traits/trait-upcasting/lifetime.stderr
index ca8f9cf63f3..589e9816d5a 100644
--- a/tests/ui/traits/trait-upcasting/lifetime.stderr
+++ b/tests/ui/traits/trait-upcasting/lifetime.stderr
@@ -1,5 +1,5 @@
 warning: methods `z` and `y` are never used
-  --> $DIR/lifetime.rs:10:8
+  --> $DIR/lifetime.rs:8:8
    |
 LL | trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
    |       --- methods in this trait
@@ -13,7 +13,7 @@ LL |     fn y(&self) -> i32 {
    = note: `#[warn(dead_code)]` on by default
 
 warning: method `w` is never used
-  --> $DIR/lifetime.rs:24:8
+  --> $DIR/lifetime.rs:22:8
    |
 LL | trait Bar: Foo {
    |       --- method in this trait
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs
index da1a9cc2775..d33d3bfd5dc 100644
--- a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.rs
@@ -1,4 +1,5 @@
-#![deny(deref_into_dyn_supertrait)]
+//@ check-pass
+#![warn(deref_into_dyn_supertrait)]
 
 use std::ops::Deref;
 
@@ -6,8 +7,7 @@ trait Bar<'a> {}
 trait Foo<'a>: Bar<'a> {}
 
 impl<'a> Deref for dyn Foo<'a> {
-    //~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
-    //~| WARN this will change its meaning in a future release!
+    //~^ warn: this `Deref` implementation is covered by an implicit supertrait coercion
     type Target = dyn Bar<'a>;
 
     fn deref(&self) -> &Self::Target {
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr
index a5f3660d4bc..806c57e44a2 100644
--- a/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-deny-regions.stderr
@@ -1,19 +1,17 @@
-error: this `Deref` implementation is covered by an implicit supertrait coercion
-  --> $DIR/migrate-lint-deny-regions.rs:8:1
+warning: this `Deref` implementation is covered by an implicit supertrait coercion
+  --> $DIR/migrate-lint-deny-regions.rs:9:1
    |
 LL | impl<'a> Deref for dyn Foo<'a> {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo<'_>` implements `Deref<Target = dyn Bar<'_>>` which conflicts with supertrait `Bar<'_>`
-...
+LL |
 LL |     type Target = dyn Bar<'a>;
    |     -------------------------- target type is a supertrait of `dyn Foo<'_>`
    |
-   = warning: this will change its meaning in a future release!
-   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
 note: the lint level is defined here
-  --> $DIR/migrate-lint-deny-regions.rs:1:9
+  --> $DIR/migrate-lint-deny-regions.rs:2:9
    |
-LL | #![deny(deref_into_dyn_supertrait)]
+LL | #![warn(deref_into_dyn_supertrait)]
    |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
-error: aborting due to 1 previous error
+warning: 1 warning emitted
 
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs b/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs
deleted file mode 100644
index 926b3649e01..00000000000
--- a/tests/ui/traits/trait-upcasting/migrate-lint-deny.rs
+++ /dev/null
@@ -1,25 +0,0 @@
-#![deny(deref_into_dyn_supertrait)]
-
-use std::ops::Deref;
-
-// issue 89190
-trait A {}
-trait B: A {}
-
-impl<'a> Deref for dyn 'a + B {
-    //~^ ERROR this `Deref` implementation is covered by an implicit supertrait coercion
-    //~| WARN this will change its meaning in a future release!
-
-    type Target = dyn A;
-    fn deref(&self) -> &Self::Target {
-        todo!()
-    }
-}
-
-fn take_a(_: &dyn A) {}
-
-fn whoops(b: &dyn B) {
-    take_a(b)
-}
-
-fn main() {}
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
deleted file mode 100644
index 29997a9b3d9..00000000000
--- a/tests/ui/traits/trait-upcasting/migrate-lint-deny.stderr
+++ /dev/null
@@ -1,19 +0,0 @@
-error: this `Deref` implementation is covered by an implicit supertrait coercion
-  --> $DIR/migrate-lint-deny.rs:9:1
-   |
-LL | impl<'a> Deref for dyn 'a + B {
-   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn B` implements `Deref<Target = dyn A>` which conflicts with supertrait `A`
-...
-LL |     type Target = dyn A;
-   |     -------------------- target type is a supertrait of `dyn B`
-   |
-   = warning: this will change its meaning in a future release!
-   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
-note: the lint level is defined here
-  --> $DIR/migrate-lint-deny.rs:1:9
-   |
-LL | #![deny(deref_into_dyn_supertrait)]
-   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
-
-error: aborting due to 1 previous error
-
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs
index 8e62c4b95b0..20806f22886 100644
--- a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.rs
@@ -1,4 +1,5 @@
 //@ check-pass
+#![warn(deref_into_dyn_supertrait)]
 
 use std::ops::Deref;
 
@@ -9,8 +10,7 @@ trait Foo: Bar<i32> {
 }
 
 impl<'a> Deref for dyn Foo + 'a {
-    //~^ WARN this `Deref` implementation is covered by an implicit supertrait coercion
-    //~| WARN this will change its meaning in a future release!
+    //~^ warn: this `Deref` implementation is covered by an implicit supertrait coercion
     type Target = dyn Bar<u32> + 'a;
 
     fn deref(&self) -> &Self::Target {
diff --git a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr
index 6245da5a176..86cff5233ff 100644
--- a/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr
+++ b/tests/ui/traits/trait-upcasting/migrate-lint-different-substs.stderr
@@ -1,15 +1,17 @@
 warning: this `Deref` implementation is covered by an implicit supertrait coercion
-  --> $DIR/migrate-lint-different-substs.rs:11:1
+  --> $DIR/migrate-lint-different-substs.rs:12:1
    |
 LL | impl<'a> Deref for dyn Foo + 'a {
    | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ `dyn Foo` implements `Deref<Target = dyn Bar<u32>>` which conflicts with supertrait `Bar<i32>`
-...
+LL |
 LL |     type Target = dyn Bar<u32> + 'a;
    |     -------------------------------- target type is a supertrait of `dyn Foo`
    |
-   = warning: this will change its meaning in a future release!
-   = note: for more information, see issue #89460 <https://github.com/rust-lang/rust/issues/89460>
-   = note: `#[warn(deref_into_dyn_supertrait)]` on by default
+note: the lint level is defined here
+  --> $DIR/migrate-lint-different-substs.rs:2:9
+   |
+LL | #![warn(deref_into_dyn_supertrait)]
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^
 
 warning: 1 warning emitted
 
diff --git a/tests/ui/traits/trait-upcasting/mono-impossible.rs b/tests/ui/traits/trait-upcasting/mono-impossible.rs
index 88f19e1c95f..f19f0538efa 100644
--- a/tests/ui/traits/trait-upcasting/mono-impossible.rs
+++ b/tests/ui/traits/trait-upcasting/mono-impossible.rs
@@ -1,7 +1,5 @@
 //@ build-pass
 
-#![feature(trait_upcasting)]
-
 trait Supertrait<T> {
     fn method(&self) {}
 }
diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
index 754437a3bec..0bf0d14c259 100644
--- a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
+++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.rs
@@ -1,5 +1,4 @@
 //@ check-fail
-#![feature(trait_upcasting)]
 
 trait Bar<T> {
     fn bar(&self, _: T) {}
diff --git a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
index 70ba1fcaf38..c888ccc1ebb 100644
--- a/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
+++ b/tests/ui/traits/trait-upcasting/multiple-occurrence-ambiguousity.stderr
@@ -1,5 +1,5 @@
 error[E0308]: mismatched types
-  --> $DIR/multiple-occurrence-ambiguousity.rs:20:26
+  --> $DIR/multiple-occurrence-ambiguousity.rs:19:26
    |
 LL |     let t: &dyn Bar<_> = s;
    |            -----------   ^ expected trait `Bar`, found trait `Foo`
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs
index 510a1471af2..a0bb1c57adb 100644
--- a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-binder.rs
@@ -1,10 +1,8 @@
+// Test for <https://github.com/rust-lang/rust/issues/135316>.
+//
 //@ run-pass
 //@ check-run-results
 
-// Test for <https://github.com/rust-lang/rust/issues/135316>.
-
-#![feature(trait_upcasting)]
-
 trait Supertrait<T> {
     fn _print_numbers(&self, mem: &[usize; 100]) {
         println!("{mem:?}");
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs
index 69a71859a5c..6b9ddf9bedc 100644
--- a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.rs
@@ -1,5 +1,4 @@
 #![feature(rustc_attrs)]
-#![feature(trait_upcasting)]
 
 // Test for <https://github.com/rust-lang/rust/issues/135315>.
 
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr
index 757e2dc6939..04b1afae7be 100644
--- a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization-vtable.stderr
@@ -5,7 +5,7 @@ error: vtable entries: [
            Method(<() as Supertrait<()>>::_print_numbers),
            Method(<() as Middle<()>>::say_hello),
        ]
-  --> $DIR/multiple-supertraits-modulo-normalization-vtable.rs:30:1
+  --> $DIR/multiple-supertraits-modulo-normalization-vtable.rs:29:1
    |
 LL | impl Trait for () {}
    | ^^^^^^^^^^^^^^^^^
@@ -17,7 +17,7 @@ error: vtable entries: [
            Method(<dyn Middle<()> as Supertrait<()>>::_print_numbers - shim(reify)),
            Method(<dyn Middle<()> as Middle<()>>::say_hello - shim(reify)),
        ]
-  --> $DIR/multiple-supertraits-modulo-normalization-vtable.rs:34:1
+  --> $DIR/multiple-supertraits-modulo-normalization-vtable.rs:33:1
    |
 LL | type Virtual = dyn Middle<()>;
    | ^^^^^^^^^^^^
diff --git a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs
index c744e6e64f5..08ec49971ac 100644
--- a/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs
+++ b/tests/ui/traits/trait-upcasting/multiple-supertraits-modulo-normalization.rs
@@ -1,10 +1,8 @@
+// Test for <https://github.com/rust-lang/rust/issues/135315>.
+//
 //@ run-pass
 //@ check-run-results
 
-#![feature(trait_upcasting)]
-
-// Test for <https://github.com/rust-lang/rust/issues/135315>.
-
 trait Supertrait<T> {
     fn _print_numbers(&self, mem: &[usize; 100]) {
         println!("{mem:?}");
diff --git a/tests/ui/traits/trait-upcasting/normalization.rs b/tests/ui/traits/trait-upcasting/normalization.rs
index ae5a6a5243c..b714479961f 100644
--- a/tests/ui/traits/trait-upcasting/normalization.rs
+++ b/tests/ui/traits/trait-upcasting/normalization.rs
@@ -4,8 +4,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(trait_upcasting)]
-
 trait Mirror {
     type Assoc;
 }
diff --git a/tests/ui/traits/trait-upcasting/prefer-lower-candidates.rs b/tests/ui/traits/trait-upcasting/prefer-lower-candidates.rs
index 4bc59b09fb5..09557ba0260 100644
--- a/tests/ui/traits/trait-upcasting/prefer-lower-candidates.rs
+++ b/tests/ui/traits/trait-upcasting/prefer-lower-candidates.rs
@@ -6,8 +6,6 @@
 // Ensure we don't have ambiguity when upcasting to two supertraits
 // that are identical modulo normalization.
 
-#![feature(trait_upcasting)]
-
 trait Supertrait<T> {
     fn method(&self) {}
 }
diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.rs b/tests/ui/traits/trait-upcasting/replace-vptr.rs
index 4829e3c5c12..6ca5864669b 100644
--- a/tests/ui/traits/trait-upcasting/replace-vptr.rs
+++ b/tests/ui/traits/trait-upcasting/replace-vptr.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(trait_upcasting)]
-
 trait A {
     fn foo_a(&self); //~ WARN method `foo_a` is never used
 }
diff --git a/tests/ui/traits/trait-upcasting/replace-vptr.stderr b/tests/ui/traits/trait-upcasting/replace-vptr.stderr
index 823094761b3..1a8bfd1bfa6 100644
--- a/tests/ui/traits/trait-upcasting/replace-vptr.stderr
+++ b/tests/ui/traits/trait-upcasting/replace-vptr.stderr
@@ -1,5 +1,5 @@
 warning: method `foo_a` is never used
-  --> $DIR/replace-vptr.rs:6:8
+  --> $DIR/replace-vptr.rs:4:8
    |
 LL | trait A {
    |       - method in this trait
@@ -9,7 +9,7 @@ LL |     fn foo_a(&self);
    = note: `#[warn(dead_code)]` on by default
 
 warning: method `foo_c` is never used
-  --> $DIR/replace-vptr.rs:14:8
+  --> $DIR/replace-vptr.rs:12:8
    |
 LL | trait C: A + B {
    |       - method in this trait
diff --git a/tests/ui/traits/trait-upcasting/struct.rs b/tests/ui/traits/trait-upcasting/struct.rs
index 39da20259a0..51e6f006fbf 100644
--- a/tests/ui/traits/trait-upcasting/struct.rs
+++ b/tests/ui/traits/trait-upcasting/struct.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(trait_upcasting)]
-
 use std::rc::Rc;
 use std::sync::Arc;
 
diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.rs b/tests/ui/traits/trait-upcasting/subtrait-method.rs
index 136d15af0e8..20277280440 100644
--- a/tests/ui/traits/trait-upcasting/subtrait-method.rs
+++ b/tests/ui/traits/trait-upcasting/subtrait-method.rs
@@ -1,5 +1,3 @@
-#![feature(trait_upcasting)]
-
 trait Foo: PartialEq<i32> + std::fmt::Debug + Send + Sync {
     fn a(&self) -> i32 {
         10
diff --git a/tests/ui/traits/trait-upcasting/subtrait-method.stderr b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
index 0408be6986b..a7658a7bcd3 100644
--- a/tests/ui/traits/trait-upcasting/subtrait-method.stderr
+++ b/tests/ui/traits/trait-upcasting/subtrait-method.stderr
@@ -1,12 +1,12 @@
 error[E0599]: no method named `c` found for reference `&dyn Bar` in the current scope
-  --> $DIR/subtrait-method.rs:55:9
+  --> $DIR/subtrait-method.rs:53:9
    |
 LL |     bar.c();
    |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:27:1
+  --> $DIR/subtrait-method.rs:25:1
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
@@ -16,14 +16,14 @@ LL |     bar.a();
    |         ~
 
 error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
-  --> $DIR/subtrait-method.rs:59:9
+  --> $DIR/subtrait-method.rs:57:9
    |
 LL |     foo.b();
    |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `b`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:17:1
+  --> $DIR/subtrait-method.rs:15:1
    |
 LL | trait Bar: Foo {
    | ^^^^^^^^^^^^^^
@@ -33,14 +33,14 @@ LL |     foo.a();
    |         ~
 
 error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
-  --> $DIR/subtrait-method.rs:61:9
+  --> $DIR/subtrait-method.rs:59:9
    |
 LL |     foo.c();
    |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:27:1
+  --> $DIR/subtrait-method.rs:25:1
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
@@ -50,14 +50,14 @@ LL |     foo.a();
    |         ~
 
 error[E0599]: no method named `b` found for reference `&dyn Foo` in the current scope
-  --> $DIR/subtrait-method.rs:65:9
+  --> $DIR/subtrait-method.rs:63:9
    |
 LL |     foo.b();
    |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Bar` defines an item `b`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:17:1
+  --> $DIR/subtrait-method.rs:15:1
    |
 LL | trait Bar: Foo {
    | ^^^^^^^^^^^^^^
@@ -67,14 +67,14 @@ LL |     foo.a();
    |         ~
 
 error[E0599]: no method named `c` found for reference `&dyn Foo` in the current scope
-  --> $DIR/subtrait-method.rs:67:9
+  --> $DIR/subtrait-method.rs:65:9
    |
 LL |     foo.c();
    |         ^
    |
    = help: items from traits can only be used if the trait is implemented and in scope
 note: `Baz` defines an item `c`, perhaps you need to implement it
-  --> $DIR/subtrait-method.rs:27:1
+  --> $DIR/subtrait-method.rs:25:1
    |
 LL | trait Baz: Bar {
    | ^^^^^^^^^^^^^^
diff --git a/tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs b/tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs
index 6cd74b6c7f7..e65cb60d993 100644
--- a/tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs
+++ b/tests/ui/traits/trait-upcasting/supertraits-modulo-inner-binder.rs
@@ -1,7 +1,5 @@
 //@ run-pass
 
-#![feature(trait_upcasting)]
-
 trait Super<U> {
     fn call(&self)
     where
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
index 9a9ad9bbf77..2f27d1522a6 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.current.stderr
@@ -1,5 +1,5 @@
 error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-1.rs:20:13
+  --> $DIR/type-checking-test-1.rs:18:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
    |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
index 9a9ad9bbf77..2f27d1522a6 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.next.stderr
@@ -1,5 +1,5 @@
 error[E0605]: non-primitive cast: `&dyn Foo` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-1.rs:20:13
+  --> $DIR/type-checking-test-1.rs:18:13
    |
 LL |     let _ = x as &dyn Bar<_>; // Ambiguous
    |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
index fd902fd87e0..b06f5e04528 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-1.rs
@@ -2,8 +2,6 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
 
-#![feature(trait_upcasting)]
-
 trait Foo: Bar<i32> + Bar<u32> {}
 trait Bar<T> {
     fn bar(&self) -> Option<T> {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
index b024b27750b..b4df0f5a902 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.rs
@@ -1,5 +1,3 @@
-#![feature(trait_upcasting)]
-
 trait Foo<T>: Bar<i32> + Bar<T> {}
 trait Bar<T> {
     fn bar(&self) -> Option<T> {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
index 3e59b9d3363..f84ea93dc67 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-2.stderr
@@ -1,11 +1,11 @@
 error[E0605]: non-primitive cast: `&dyn Foo<i32>` as `&dyn Bar<u32>`
-  --> $DIR/type-checking-test-2.rs:19:13
+  --> $DIR/type-checking-test-2.rs:17:13
    |
 LL |     let _ = x as &dyn Bar<u32>; // Error
    |             ^^^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
 
 error[E0605]: non-primitive cast: `&dyn Foo<u32>` as `&dyn Bar<_>`
-  --> $DIR/type-checking-test-2.rs:24:13
+  --> $DIR/type-checking-test-2.rs:22:13
    |
 LL |     let a = x as &dyn Bar<_>; // Ambiguous
    |             ^^^^^^^^^^^^^^^^ an `as` expression can only be used to convert between primitive types or to coerce to a specific trait object
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
index b2db3a12797..3685569d98d 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.rs
@@ -1,5 +1,3 @@
-#![feature(trait_upcasting)]
-
 trait Foo<'a>: Bar<'a> {}
 trait Bar<'a> {}
 
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
index 01b8da645f3..d80649638ae 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-3.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-3.rs:11:13
+  --> $DIR/type-checking-test-3.rs:9:13
    |
 LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
@@ -7,7 +7,7 @@ LL |     let _ = x as &dyn Bar<'a>; // Error
    |             ^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-3.rs:16:18
+  --> $DIR/type-checking-test-3.rs:14:18
    |
 LL | fn test_wrong2<'a>(x: &dyn Foo<'a>) {
    |                -- lifetime `'a` defined here
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
index 01759ec7a93..20de722ee9b 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.rs
@@ -1,5 +1,3 @@
-#![feature(trait_upcasting)]
-
 trait Foo<'a>: Bar<'a, 'a> {}
 trait Bar<'a, 'b> {
     fn get_b(&self) -> Option<&'a u32> {
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
index e91ea193a01..55a5e4cd497 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-4.stderr
@@ -1,5 +1,5 @@
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:19:13
+  --> $DIR/type-checking-test-4.rs:17:13
    |
 LL | fn test_wrong1<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
@@ -7,7 +7,7 @@ LL |     let _ = x as &dyn Bar<'static, 'a>; // Error
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^ cast requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:24:18
+  --> $DIR/type-checking-test-4.rs:22:18
    |
 LL | fn test_wrong2<'a>(x: &dyn Foo<'static>, y: &'a u32) {
    |                -- lifetime `'a` defined here
@@ -15,7 +15,7 @@ LL |     let _ = x as &dyn Bar<'a, 'static>; // Error
    |                  ^^^^^^^^^^^^^^^^^^^^^ type annotation requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:30:5
+  --> $DIR/type-checking-test-4.rs:28:5
    |
 LL | fn test_wrong3<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -24,7 +24,7 @@ LL |     y.get_b() // ERROR
    |     ^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:35:5
+  --> $DIR/type-checking-test-4.rs:33:5
    |
 LL | fn test_wrong4<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -32,7 +32,7 @@ LL |     <_ as Bar>::get_b(x) // ERROR
    |     ^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:40:5
+  --> $DIR/type-checking-test-4.rs:38:5
    |
 LL | fn test_wrong5<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
@@ -40,7 +40,7 @@ LL |     <_ as Bar<'_, '_>>::get_b(x) // ERROR
    |     ^^^^^^^^^^^^^^^^^^^^^^^^^^^^ returning this value requires that `'a` must outlive `'static`
 
 error: lifetime may not live long enough
-  --> $DIR/type-checking-test-4.rs:48:5
+  --> $DIR/type-checking-test-4.rs:46:5
    |
 LL | fn test_wrong6<'a>(x: &dyn Foo<'a>) -> Option<&'static u32> {
    |                -- lifetime `'a` defined here
diff --git a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs
index a3a1ce29465..ab3817da28b 100644
--- a/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs
+++ b/tests/ui/traits/trait-upcasting/type-checking-test-opaques.rs
@@ -1,4 +1,4 @@
-#![feature(trait_upcasting, type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
 
 //@ check-pass
 
diff --git a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
index 07f1549e177..0548eda0468 100644
--- a/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
+++ b/tests/ui/traits/trait-upcasting/upcast-defining-opaque.rs
@@ -3,7 +3,7 @@
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@check-pass
 
-#![feature(trait_upcasting, type_alias_impl_trait)]
+#![feature(type_alias_impl_trait)]
 
 trait Super {
     type Assoc;
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr
deleted file mode 100644
index 239f8279194..00000000000
--- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.current.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
-  --> $DIR/upcast-through-struct-tail.rs:11:5
-   |
-LL |     x
-   |     ^
-   |
-   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
-   = help: add `#![feature(trait_upcasting)]` 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: required when coercing `Box<Wrapper<(dyn A + 'a)>>` into `Box<Wrapper<(dyn B + 'a)>>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr
deleted file mode 100644
index 239f8279194..00000000000
--- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.next.stderr
+++ /dev/null
@@ -1,14 +0,0 @@
-error[E0658]: cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
-  --> $DIR/upcast-through-struct-tail.rs:11:5
-   |
-LL |     x
-   |     ^
-   |
-   = note: see issue #65991 <https://github.com/rust-lang/rust/issues/65991> for more information
-   = help: add `#![feature(trait_upcasting)]` 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: required when coercing `Box<Wrapper<(dyn A + 'a)>>` into `Box<Wrapper<(dyn B + 'a)>>`
-
-error: aborting due to 1 previous error
-
-For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
index e40cca4e0a8..dd4d91f8d4f 100644
--- a/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
+++ b/tests/ui/traits/trait-upcasting/upcast-through-struct-tail.rs
@@ -1,3 +1,4 @@
+//@ check-pass
 //@ revisions: current next
 //@ ignore-compare-mode-next-solver (explicit revisions)
 //@[next] compile-flags: -Znext-solver
@@ -9,7 +10,6 @@ trait B {}
 
 fn test<'a>(x: Box<Wrapper<dyn A + 'a>>) -> Box<Wrapper<dyn B + 'a>> {
     x
-    //~^ ERROR cannot cast `dyn A` to `dyn B`, trait upcasting coercion is experimental
 }
 
 fn main() {}
diff --git a/tests/ui/traits/upcast_reorder.rs b/tests/ui/traits/upcast_reorder.rs
index 55e6ad4c368..43fc1517a3b 100644
--- a/tests/ui/traits/upcast_reorder.rs
+++ b/tests/ui/traits/upcast_reorder.rs
@@ -2,8 +2,6 @@
 //
 // issue: <https://github.com/rust-lang/rust/issues/131813>
 
-#![feature(trait_upcasting)]
-
 trait Pollable {
     #[allow(unused)]
     fn poll(&self) {}
diff --git a/tests/ui/traits/upcast_soundness_bug.rs b/tests/ui/traits/upcast_soundness_bug.rs
index 0ddae1d1417..4c89fa135e7 100644
--- a/tests/ui/traits/upcast_soundness_bug.rs
+++ b/tests/ui/traits/upcast_soundness_bug.rs
@@ -1,4 +1,3 @@
-#![feature(trait_upcasting)]
 //@ check-fail
 //
 // issue: <https://github.com/rust-lang/rust/pull/120222>
diff --git a/tests/ui/traits/upcast_soundness_bug.stderr b/tests/ui/traits/upcast_soundness_bug.stderr
index 19d1a5e5926..f5fa6bdc999 100644
--- a/tests/ui/traits/upcast_soundness_bug.stderr
+++ b/tests/ui/traits/upcast_soundness_bug.stderr
@@ -1,5 +1,5 @@
 error[E0606]: casting `*const dyn Trait<u8, u8>` as `*const dyn Trait<u8, u16>` is invalid
-  --> $DIR/upcast_soundness_bug.rs:59:13
+  --> $DIR/upcast_soundness_bug.rs:58:13
    |
 LL |     let p = p as *const dyn Trait<u8, u16>; // <- this is bad!
    |             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/wrong-adt-assume.rs b/tests/ui/transmutability/malformed-program-gracefulness/wrong-adt-assume.rs
new file mode 100644
index 00000000000..2340df25025
--- /dev/null
+++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-adt-assume.rs
@@ -0,0 +1,20 @@
+//! Test that we don't ICE when passing the wrong ADT to ASSUME.
+
+#![feature(adt_const_params)]
+#![feature(transmutability)]
+
+use std::marker::ConstParamTy;
+use std::mem::TransmuteFrom;
+
+#[derive(ConstParamTy, PartialEq, Eq)]
+struct NotAssume;
+
+fn foo<const ASSUME: NotAssume>()
+where
+    u8: TransmuteFrom<u8, ASSUME>, //~ ERROR the constant `ASSUME` is not of type `Assume`
+{
+}
+
+fn main() {
+    foo::<{ NotAssume }>();
+}
diff --git a/tests/ui/transmutability/malformed-program-gracefulness/wrong-adt-assume.stderr b/tests/ui/transmutability/malformed-program-gracefulness/wrong-adt-assume.stderr
new file mode 100644
index 00000000000..cae700ecfdc
--- /dev/null
+++ b/tests/ui/transmutability/malformed-program-gracefulness/wrong-adt-assume.stderr
@@ -0,0 +1,11 @@
+error: the constant `ASSUME` is not of type `Assume`
+  --> $DIR/wrong-adt-assume.rs:14:9
+   |
+LL |     u8: TransmuteFrom<u8, ASSUME>,
+   |         ^^^^^^^^^^^^^^^^^^^^^^^^^ expected `Assume`, found `NotAssume`
+   |
+note: required by a const generic parameter in `TransmuteFrom`
+  --> $SRC_DIR/core/src/mem/transmutability.rs:LL:COL
+
+error: aborting due to 1 previous error
+
diff --git a/tests/ui/weird-exprs.rs b/tests/ui/weird-exprs.rs
index 08b5517aae2..55a8d580a8b 100644
--- a/tests/ui/weird-exprs.rs
+++ b/tests/ui/weird-exprs.rs
@@ -34,7 +34,7 @@ fn what() {
     let i = &Cell::new(false);
     let dont = {||the(i)};
     dont();
-    assert!((i.get()));
+    assert!(i.get());
 }
 
 fn zombiejesus() {
@@ -69,8 +69,8 @@ fn notsure() {
 
 fn canttouchthis() -> usize {
     fn p() -> bool { true }
-    let _a = (assert!((true)) == (assert!(p())));
-    let _c = (assert!((p())) == ());
+    let _a = (assert!(true) == (assert!(p())));
+    let _c = (assert!(p()) == ());
     let _b: bool = (println!("{}", 0) == (return 0));
 }
 
diff --git a/triagebot.toml b/triagebot.toml
index 49cf1213987..3caf4e9fb1e 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -236,6 +236,15 @@ trigger_files = [
     "src/tools/jsondoclint",
 ]
 
+[autolabel."A-attributes"]
+trigger_files = [
+    "compiler/rustc_codegen_ssa/src/codegen_attrs.rs",
+    "compiler/rustc_passes/src/check_attr.rs",
+    "compiler/rustc_attr_parsing",
+    "compiler/rustc_attr_data_structures",
+    "compiler/rustc_attr_validation",
+]
+
 [autolabel."T-compiler"]
 trigger_files = [
     # Source code
@@ -1017,6 +1026,17 @@ cc = ["@ehuss"]
 message = "The rustc-dev-guide subtree was changed. If this PR *only* touches the dev guide consider submitting a PR directly to [rust-lang/rustc-dev-guide](https://github.com/rust-lang/rustc-dev-guide/pulls) otherwise thank you for updating the dev guide with your changes."
 cc = ["@BoxyUwU", "@jieyouxu", "@kobzol"]
 
+[mentions."compiler/rustc_codegen_ssa/src/codegen_attrs.rs"]
+cc = ["@jdonszelmann"]
+[mentions."compiler/rustc_passes/src/check_attr.rs"]
+cc = ["@jdonszelmann"]
+[mentions."compiler/rustc_attr_parsing"]
+cc = ["@jdonszelmann"]
+[mentions."compiler/rustc_attr_data_structures"]
+cc = ["@jdonszelmann"]
+[mentions."compiler/rustc_attr_validation"]
+cc = ["@jdonszelmann"]
+
 [assign]
 warn_non_default_branch.enable = true
 contributing_url = "https://rustc-dev-guide.rust-lang.org/getting-started.html"