diff --git a/Cargo.lock b/Cargo.lock
index 2ee2c52b32ade..f08a95380c469 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -3317,7 +3317,6 @@ dependencies = [
  "rand 0.8.5",
  "rand_xoshiro",
  "rustc_data_structures",
- "rustc_feature",
  "rustc_index",
  "rustc_macros",
  "rustc_serialize",
@@ -3379,6 +3378,7 @@ dependencies = [
  "rustc_ast_pretty",
  "rustc_data_structures",
  "rustc_errors",
+ "rustc_feature",
  "rustc_fluent_macro",
  "rustc_hir",
  "rustc_index",
@@ -3683,6 +3683,7 @@ version = "0.0.0"
 dependencies = [
  "ctrlc",
  "libc",
+ "rustc_abi",
  "rustc_ast",
  "rustc_ast_lowering",
  "rustc_ast_passes",
@@ -4337,6 +4338,7 @@ version = "0.0.0"
 dependencies = [
  "rustc_abi",
  "rustc_ast",
+ "rustc_ast_lowering",
  "rustc_ast_pretty",
  "rustc_attr_parsing",
  "rustc_data_structures",
diff --git a/compiler/rustc_abi/Cargo.toml b/compiler/rustc_abi/Cargo.toml
index 3acd25e546114..1013f1d3958d8 100644
--- a/compiler/rustc_abi/Cargo.toml
+++ b/compiler/rustc_abi/Cargo.toml
@@ -9,7 +9,6 @@ bitflags = "2.4.1"
 rand = { version = "0.8.4", default-features = false, optional = true }
 rand_xoshiro = { version = "0.6.0", optional = true }
 rustc_data_structures = { path = "../rustc_data_structures", optional = true  }
-rustc_feature = { path = "../rustc_feature", optional = true }
 rustc_index = { path = "../rustc_index", default-features = false }
 rustc_macros = { path = "../rustc_macros", optional = true }
 rustc_serialize = { path = "../rustc_serialize", optional = true  }
@@ -24,7 +23,6 @@ default = ["nightly", "randomize"]
 # without depending on rustc_data_structures, rustc_macros and rustc_serialize
 nightly = [
     "dep:rustc_data_structures",
-    "dep:rustc_feature",
     "dep:rustc_macros",
     "dep:rustc_serialize",
     "dep:rustc_span",
diff --git a/compiler/rustc_abi/src/callconv.rs b/compiler/rustc_abi/src/callconv.rs
index daa365bf6e1d7..9fb70b80c9efb 100644
--- a/compiler/rustc_abi/src/callconv.rs
+++ b/compiler/rustc_abi/src/callconv.rs
@@ -1,6 +1,5 @@
 #[cfg(feature = "nightly")]
-use crate::{BackendRepr, FieldsShape, TyAbiInterface, TyAndLayout};
-use crate::{Primitive, Size, Variants};
+use crate::{BackendRepr, FieldsShape, Primitive, Size, TyAbiInterface, TyAndLayout, Variants};
 
 mod reg;
 
diff --git a/compiler/rustc_abi/src/extern_abi.rs b/compiler/rustc_abi/src/extern_abi.rs
index 130834d560f72..f3cf7f583cebd 100644
--- a/compiler/rustc_abi/src/extern_abi.rs
+++ b/compiler/rustc_abi/src/extern_abi.rs
@@ -1,7 +1,6 @@
 use std::fmt;
 
 use rustc_macros::{Decodable, Encodable, HashStable_Generic};
-use rustc_span::{Span, Symbol, sym};
 
 #[cfg(test)]
 mod tests;
@@ -95,14 +94,14 @@ impl Abi {
 
 #[derive(Copy, Clone)]
 pub struct AbiData {
-    abi: Abi,
+    pub abi: Abi,
 
     /// Name of this ABI as we like it called.
-    name: &'static str,
+    pub name: &'static str,
 }
 
 #[allow(non_upper_case_globals)]
-const AbiDatas: &[AbiData] = &[
+pub const AbiDatas: &[AbiData] = &[
     AbiData { abi: Abi::Rust, name: "Rust" },
     AbiData { abi: Abi::C { unwind: false }, name: "C" },
     AbiData { abi: Abi::C { unwind: true }, name: "C-unwind" },
@@ -142,129 +141,18 @@ const AbiDatas: &[AbiData] = &[
 ];
 
 #[derive(Copy, Clone, Debug)]
-pub enum AbiUnsupported {
-    Unrecognized,
-    Reason { explain: &'static str },
-}
-
+pub struct AbiUnsupported {}
 /// Returns the ABI with the given name (if any).
 pub fn lookup(name: &str) -> Result<Abi, AbiUnsupported> {
-    AbiDatas.iter().find(|abi_data| name == abi_data.name).map(|&x| x.abi).ok_or_else(|| match name {
-        "riscv-interrupt" => AbiUnsupported::Reason {
-            explain: "please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively",
-        },
-        "riscv-interrupt-u" => AbiUnsupported::Reason {
-            explain: "user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314",
-        },
-        "wasm" => AbiUnsupported::Reason {
-            explain: "non-standard wasm ABI is no longer supported",
-        },
-
-        _ => AbiUnsupported::Unrecognized,
-
-    })
-}
-
-pub fn all_names() -> Vec<&'static str> {
-    AbiDatas.iter().map(|d| d.name).collect()
-}
-
-pub fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> {
     AbiDatas
         .iter()
-        .map(|d| d.name)
-        .filter(|name| is_enabled(features, span, name).is_ok())
-        .collect()
+        .find(|abi_data| name == abi_data.name)
+        .map(|&x| x.abi)
+        .ok_or_else(|| AbiUnsupported {})
 }
 
-pub enum AbiDisabled {
-    Unstable { feature: Symbol, explain: &'static str },
-    Unrecognized,
-}
-
-pub fn is_enabled(
-    features: &rustc_feature::Features,
-    span: Span,
-    name: &str,
-) -> Result<(), AbiDisabled> {
-    let s = is_stable(name);
-    if let Err(AbiDisabled::Unstable { feature, .. }) = s {
-        if features.enabled(feature) || span.allows_unstable(feature) {
-            return Ok(());
-        }
-    }
-    s
-}
-
-/// Returns whether the ABI is stable to use.
-///
-/// Note that there is a separate check determining whether the ABI is even supported
-/// on the current target; see `fn is_abi_supported` in `rustc_target::spec`.
-pub fn is_stable(name: &str) -> Result<(), AbiDisabled> {
-    match name {
-        // Stable
-        "Rust" | "C" | "C-unwind" | "cdecl" | "cdecl-unwind" | "stdcall" | "stdcall-unwind"
-        | "fastcall" | "fastcall-unwind" | "aapcs" | "aapcs-unwind" | "win64" | "win64-unwind"
-        | "sysv64" | "sysv64-unwind" | "system" | "system-unwind" | "efiapi" | "thiscall"
-        | "thiscall-unwind" => Ok(()),
-        "rust-intrinsic" => Err(AbiDisabled::Unstable {
-            feature: sym::intrinsics,
-            explain: "intrinsics are subject to change",
-        }),
-        "vectorcall" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_vectorcall,
-            explain: "vectorcall is experimental and subject to change",
-        }),
-        "vectorcall-unwind" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_vectorcall,
-            explain: "vectorcall-unwind ABI is experimental and subject to change",
-        }),
-        "rust-call" => Err(AbiDisabled::Unstable {
-            feature: sym::unboxed_closures,
-            explain: "rust-call ABI is subject to change",
-        }),
-        "rust-cold" => Err(AbiDisabled::Unstable {
-            feature: sym::rust_cold_cc,
-            explain: "rust-cold is experimental and subject to change",
-        }),
-        "ptx-kernel" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_ptx,
-            explain: "PTX ABIs are experimental and subject to change",
-        }),
-        "unadjusted" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_unadjusted,
-            explain: "unadjusted ABI is an implementation detail and perma-unstable",
-        }),
-        "msp430-interrupt" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_msp430_interrupt,
-            explain: "msp430-interrupt ABI is experimental and subject to change",
-        }),
-        "x86-interrupt" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_x86_interrupt,
-            explain: "x86-interrupt ABI is experimental and subject to change",
-        }),
-        "gpu-kernel" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_gpu_kernel,
-            explain: "gpu-kernel ABI is experimental and subject to change",
-        }),
-        "avr-interrupt" | "avr-non-blocking-interrupt" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_avr_interrupt,
-            explain: "avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change",
-        }),
-        "riscv-interrupt-m" | "riscv-interrupt-s" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_riscv_interrupt,
-            explain: "riscv-interrupt ABIs are experimental and subject to change",
-        }),
-        "C-cmse-nonsecure-call" => Err(AbiDisabled::Unstable {
-            feature: sym::abi_c_cmse_nonsecure_call,
-            explain: "C-cmse-nonsecure-call ABI is experimental and subject to change",
-        }),
-        "C-cmse-nonsecure-entry" => Err(AbiDisabled::Unstable {
-            feature: sym::cmse_nonsecure_entry,
-            explain: "C-cmse-nonsecure-entry ABI is experimental and subject to change",
-        }),
-        _ => Err(AbiDisabled::Unrecognized),
-    }
+pub fn all_names() -> Vec<&'static str> {
+    AbiDatas.iter().map(|d| d.name).collect()
 }
 
 impl Abi {
diff --git a/compiler/rustc_abi/src/extern_abi/tests.rs b/compiler/rustc_abi/src/extern_abi/tests.rs
index 4823058dd6970..72c0f183d50c1 100644
--- a/compiler/rustc_abi/src/extern_abi/tests.rs
+++ b/compiler/rustc_abi/src/extern_abi/tests.rs
@@ -18,7 +18,7 @@ fn lookup_cdecl() {
 #[test]
 fn lookup_baz() {
     let abi = lookup("baz");
-    assert_matches!(abi, Err(AbiUnsupported::Unrecognized));
+    assert_matches!(abi, Err(AbiUnsupported {}));
 }
 
 #[test]
diff --git a/compiler/rustc_abi/src/lib.rs b/compiler/rustc_abi/src/lib.rs
index fc34b28893309..259f1c18ea8e9 100644
--- a/compiler/rustc_abi/src/lib.rs
+++ b/compiler/rustc_abi/src/lib.rs
@@ -66,9 +66,7 @@ mod extern_abi;
 
 pub use callconv::{Heterogeneous, HomogeneousAggregate, Reg, RegKind};
 #[cfg(feature = "nightly")]
-pub use extern_abi::{
-    AbiDisabled, AbiUnsupported, ExternAbi, all_names, enabled_names, is_enabled, is_stable, lookup,
-};
+pub use extern_abi::{AbiDatas, AbiUnsupported, ExternAbi, all_names, lookup};
 #[cfg(feature = "nightly")]
 pub use layout::{FIRST_VARIANT, FieldIdx, Layout, TyAbiInterface, TyAndLayout, VariantIdx};
 pub use layout::{LayoutCalculator, LayoutCalculatorError};
diff --git a/compiler/rustc_ast_lowering/Cargo.toml b/compiler/rustc_ast_lowering/Cargo.toml
index 754f3c1a6e9ae..ce95f4dfa1b82 100644
--- a/compiler/rustc_ast_lowering/Cargo.toml
+++ b/compiler/rustc_ast_lowering/Cargo.toml
@@ -13,6 +13,7 @@ rustc_ast = { path = "../rustc_ast" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_data_structures = { path = "../rustc_data_structures" }
 rustc_errors = { path = "../rustc_errors" }
+rustc_feature = { path = "../rustc_feature" }
 rustc_fluent_macro = { path = "../rustc_fluent_macro" }
 rustc_hir = { path = "../rustc_hir" }
 rustc_index = { path = "../rustc_index" }
diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs
index f9fe4938ca8bc..d8b7cb0c3225b 100644
--- a/compiler/rustc_ast_lowering/src/delegation.rs
+++ b/compiler/rustc_ast_lowering/src/delegation.rs
@@ -41,13 +41,13 @@ use std::iter;
 use ast::visit::Visitor;
 use hir::def::{DefKind, PartialRes, Res};
 use hir::{BodyId, HirId};
+use rustc_abi::ExternAbi;
 use rustc_ast::*;
 use rustc_errors::ErrorGuaranteed;
 use rustc_hir::def_id::DefId;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{Asyncness, ResolverAstLowering};
 use rustc_span::{Ident, Span};
-use rustc_target::spec::abi;
 use {rustc_ast as ast, rustc_hir as hir};
 
 use super::{GenericArgsMode, ImplTraitContext, LoweringContext, ParamMode};
@@ -398,7 +398,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
             safety: hir::Safety::Safe.into(),
             constness: hir::Constness::NotConst,
             asyncness: hir::IsAsync::NotAsync,
-            abi: abi::Abi::Rust,
+            abi: ExternAbi::Rust,
         }
     }
 
diff --git a/compiler/rustc_ast_lowering/src/errors.rs b/compiler/rustc_ast_lowering/src/errors.rs
index f727691bf479c..9f69387b7b715 100644
--- a/compiler/rustc_ast_lowering/src/errors.rs
+++ b/compiler/rustc_ast_lowering/src/errors.rs
@@ -1,5 +1,5 @@
+use rustc_errors::DiagArgFromDisplay;
 use rustc_errors::codes::*;
-use rustc_errors::{Diag, DiagArgFromDisplay, EmissionGuarantee, SubdiagMessageOp, Subdiagnostic};
 use rustc_macros::{Diagnostic, Subdiagnostic};
 use rustc_span::{Ident, Span, Symbol};
 
@@ -32,8 +32,6 @@ pub(crate) struct InvalidAbi {
     pub abi: Symbol,
     pub command: String,
     #[subdiagnostic]
-    pub explain: Option<InvalidAbiReason>,
-    #[subdiagnostic]
     pub suggestion: Option<InvalidAbiSuggestion>,
 }
 
@@ -45,19 +43,6 @@ pub(crate) struct TupleStructWithDefault {
     pub span: Span,
 }
 
-pub(crate) struct InvalidAbiReason(pub &'static str);
-
-impl Subdiagnostic for InvalidAbiReason {
-    fn add_to_diag_with<G: EmissionGuarantee, F: SubdiagMessageOp<G>>(
-        self,
-        diag: &mut Diag<'_, G>,
-        _: &F,
-    ) {
-        #[allow(rustc::untranslatable_diagnostic)]
-        diag.note(self.0);
-    }
-}
-
 #[derive(Subdiagnostic)]
 #[suggestion(
     ast_lowering_invalid_abi_suggestion,
diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs
index 7379a3d2cde66..75b08e16cdbd9 100644
--- a/compiler/rustc_ast_lowering/src/item.rs
+++ b/compiler/rustc_ast_lowering/src/item.rs
@@ -17,9 +17,9 @@ use thin_vec::ThinVec;
 use tracing::instrument;
 
 use super::errors::{
-    InvalidAbi, InvalidAbiReason, InvalidAbiSuggestion, MisplacedRelaxTraitBound,
-    TupleStructWithDefault,
+    InvalidAbi, InvalidAbiSuggestion, MisplacedRelaxTraitBound, TupleStructWithDefault,
 };
+use super::stability::{enabled_names, gate_unstable_abi};
 use super::{
     AstOwner, FnDeclKind, ImplTraitContext, ImplTraitPosition, LoweringContext, ParamMode,
     ResolverAstLoweringExt,
@@ -1479,11 +1479,16 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    pub(super) fn lower_abi(&mut self, abi: StrLit) -> ExternAbi {
-        rustc_abi::lookup(abi.symbol_unescaped.as_str()).unwrap_or_else(|err| {
-            self.error_on_invalid_abi(abi, err);
+    pub(super) fn lower_abi(&mut self, abi_str: StrLit) -> ExternAbi {
+        let ast::StrLit { symbol_unescaped, span, .. } = abi_str;
+        let extern_abi = rustc_abi::lookup(symbol_unescaped.as_str()).unwrap_or_else(|_| {
+            self.error_on_invalid_abi(abi_str);
             ExternAbi::Rust
-        })
+        });
+        let sess = self.tcx.sess;
+        let features = self.tcx.features();
+        gate_unstable_abi(sess, features, span, extern_abi);
+        extern_abi
     }
 
     pub(super) fn lower_extern(&mut self, ext: Extern) -> ExternAbi {
@@ -1494,8 +1499,8 @@ impl<'hir> LoweringContext<'_, 'hir> {
         }
     }
 
-    fn error_on_invalid_abi(&self, abi: StrLit, err: rustc_abi::AbiUnsupported) {
-        let abi_names = rustc_abi::enabled_names(self.tcx.features(), abi.span)
+    fn error_on_invalid_abi(&self, abi: StrLit) {
+        let abi_names = enabled_names(self.tcx.features(), abi.span)
             .iter()
             .map(|s| Symbol::intern(s))
             .collect::<Vec<_>>();
@@ -1503,10 +1508,6 @@ impl<'hir> LoweringContext<'_, 'hir> {
         self.dcx().emit_err(InvalidAbi {
             abi: abi.symbol_unescaped,
             span: abi.span,
-            explain: match err {
-                rustc_abi::AbiUnsupported::Reason { explain } => Some(InvalidAbiReason(explain)),
-                _ => None,
-            },
             suggestion: suggested_name.map(|suggested_name| InvalidAbiSuggestion {
                 span: abi.span,
                 suggestion: format!("\"{suggested_name}\""),
diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs
index 127b7e3684e90..3fecb9e9c7ea9 100644
--- a/compiler/rustc_ast_lowering/src/lib.rs
+++ b/compiler/rustc_ast_lowering/src/lib.rs
@@ -84,6 +84,7 @@ mod index;
 mod item;
 mod pat;
 mod path;
+pub mod stability;
 
 rustc_fluent_macro::fluent_messages! { "../messages.ftl" }
 
diff --git a/compiler/rustc_ast_lowering/src/stability.rs b/compiler/rustc_ast_lowering/src/stability.rs
new file mode 100644
index 0000000000000..e7c166850a46b
--- /dev/null
+++ b/compiler/rustc_ast_lowering/src/stability.rs
@@ -0,0 +1,147 @@
+use std::fmt;
+
+use rustc_abi::ExternAbi;
+use rustc_feature::Features;
+use rustc_session::Session;
+use rustc_session::parse::feature_err;
+use rustc_span::symbol::sym;
+use rustc_span::{Span, Symbol};
+
+pub(crate) fn enabled_names(features: &rustc_feature::Features, span: Span) -> Vec<&'static str> {
+    rustc_abi::AbiDatas
+        .iter()
+        .filter(|data| extern_abi_enabled(features, span, data.abi).is_ok())
+        .map(|d| d.name)
+        .collect()
+}
+
+pub(crate) fn extern_abi_enabled(
+    features: &rustc_feature::Features,
+    span: Span,
+    abi: ExternAbi,
+) -> Result<(), UnstableAbi> {
+    extern_abi_stability(abi).or_else(|unstable @ UnstableAbi { feature, .. }| {
+        if features.enabled(feature) || span.allows_unstable(feature) {
+            Ok(())
+        } else {
+            Err(unstable)
+        }
+    })
+}
+
+#[allow(rustc::untranslatable_diagnostic)]
+pub(crate) fn gate_unstable_abi(sess: &Session, features: &Features, span: Span, abi: ExternAbi) {
+    match extern_abi_enabled(features, span, abi) {
+        Ok(_) => (),
+        Err(unstable_abi) => {
+            let explain = unstable_abi.to_string();
+            feature_err(sess, unstable_abi.feature, span, explain).emit();
+        }
+    }
+}
+
+pub struct UnstableAbi {
+    abi: ExternAbi,
+    feature: Symbol,
+    explain: GateReason,
+}
+
+enum GateReason {
+    Experimental,
+    ImplDetail,
+}
+
+impl fmt::Display for UnstableAbi {
+    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
+        let Self { abi, .. } = self;
+        let name = abi.to_string();
+        let name = name.trim_matches('"');
+        match self.explain {
+            GateReason::Experimental => {
+                write!(f, r#"the extern "{name}" ABI is experimental and subject to change"#)
+            }
+            GateReason::ImplDetail => {
+                write!(
+                    f,
+                    r#"the extern "{name}" ABI is an implementation detail and perma-unstable"#
+                )
+            }
+        }
+    }
+}
+
+pub fn extern_abi_stability(abi: ExternAbi) -> Result<(), UnstableAbi> {
+    match abi {
+        // stable ABIs
+        ExternAbi::Rust
+        | ExternAbi::C { .. }
+        | ExternAbi::Cdecl { .. }
+        | ExternAbi::Stdcall { .. }
+        | ExternAbi::Fastcall { .. }
+        | ExternAbi::Thiscall { .. }
+        | ExternAbi::Aapcs { .. }
+        | ExternAbi::Win64 { .. }
+        | ExternAbi::SysV64 { .. }
+        | ExternAbi::System { .. }
+        | ExternAbi::EfiApi => Ok(()),
+        // implementation details
+        ExternAbi::RustIntrinsic => {
+            Err(UnstableAbi { abi, feature: sym::intrinsics, explain: GateReason::ImplDetail })
+        }
+        ExternAbi::Unadjusted => {
+            Err(UnstableAbi { abi, feature: sym::abi_unadjusted, explain: GateReason::ImplDetail })
+        }
+        // experimental
+        ExternAbi::Vectorcall { .. } => Err(UnstableAbi {
+            abi,
+            feature: sym::abi_vectorcall,
+            explain: GateReason::Experimental,
+        }),
+        ExternAbi::RustCall => Err(UnstableAbi {
+            abi,
+            feature: sym::unboxed_closures,
+            explain: GateReason::Experimental,
+        }),
+        ExternAbi::RustCold => {
+            Err(UnstableAbi { abi, feature: sym::rust_cold_cc, explain: GateReason::Experimental })
+        }
+        ExternAbi::GpuKernel => Err(UnstableAbi {
+            abi,
+            feature: sym::abi_gpu_kernel,
+            explain: GateReason::Experimental,
+        }),
+        ExternAbi::PtxKernel => {
+            Err(UnstableAbi { abi, feature: sym::abi_ptx, explain: GateReason::Experimental })
+        }
+        ExternAbi::Msp430Interrupt => Err(UnstableAbi {
+            abi,
+            feature: sym::abi_msp430_interrupt,
+            explain: GateReason::Experimental,
+        }),
+        ExternAbi::X86Interrupt => Err(UnstableAbi {
+            abi,
+            feature: sym::abi_x86_interrupt,
+            explain: GateReason::Experimental,
+        }),
+        ExternAbi::AvrInterrupt | ExternAbi::AvrNonBlockingInterrupt => Err(UnstableAbi {
+            abi,
+            feature: sym::abi_avr_interrupt,
+            explain: GateReason::Experimental,
+        }),
+        ExternAbi::RiscvInterruptM | ExternAbi::RiscvInterruptS => Err(UnstableAbi {
+            abi,
+            feature: sym::abi_riscv_interrupt,
+            explain: GateReason::Experimental,
+        }),
+        ExternAbi::CCmseNonSecureCall => Err(UnstableAbi {
+            abi,
+            feature: sym::abi_c_cmse_nonsecure_call,
+            explain: GateReason::Experimental,
+        }),
+        ExternAbi::CCmseNonSecureEntry => Err(UnstableAbi {
+            abi,
+            feature: sym::cmse_nonsecure_entry,
+            explain: GateReason::Experimental,
+        }),
+    }
+}
diff --git a/compiler/rustc_ast_passes/src/ast_validation.rs b/compiler/rustc_ast_passes/src/ast_validation.rs
index 0049c5b4823cb..f9f4035cb22f0 100644
--- a/compiler/rustc_ast_passes/src/ast_validation.rs
+++ b/compiler/rustc_ast_passes/src/ast_validation.rs
@@ -20,6 +20,7 @@ use std::mem;
 use std::ops::{Deref, DerefMut};
 
 use itertools::{Either, Itertools};
+use rustc_abi::ExternAbi;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, walk_list};
 use rustc_ast::*;
@@ -35,7 +36,6 @@ use rustc_session::lint::builtin::{
 };
 use rustc_session::lint::{BuiltinLintDiag, LintBuffer};
 use rustc_span::{Ident, Span, kw, sym};
-use rustc_target::spec::abi;
 use thin_vec::thin_vec;
 
 use crate::errors::{self, TildeConstReason};
@@ -723,7 +723,7 @@ impl<'a> AstValidator<'a> {
                 MISSING_ABI,
                 id,
                 span,
-                BuiltinLintDiag::MissingAbi(span, abi::Abi::FALLBACK),
+                BuiltinLintDiag::MissingAbi(span, ExternAbi::FALLBACK),
             )
         }
     }
diff --git a/compiler/rustc_ast_passes/src/feature_gate.rs b/compiler/rustc_ast_passes/src/feature_gate.rs
index 13294efdaf6f9..e5d8013058f65 100644
--- a/compiler/rustc_ast_passes/src/feature_gate.rs
+++ b/compiler/rustc_ast_passes/src/feature_gate.rs
@@ -1,9 +1,9 @@
 use rustc_ast as ast;
 use rustc_ast::visit::{self, AssocCtxt, FnCtxt, FnKind, Visitor};
 use rustc_ast::{NodeId, PatKind, attr, token};
-use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features, GateIssue};
+use rustc_feature::{AttributeGate, BUILTIN_ATTRIBUTE_MAP, BuiltinAttribute, Features};
 use rustc_session::Session;
-use rustc_session::parse::{feature_err, feature_err_issue, feature_warn};
+use rustc_session::parse::{feature_err, feature_warn};
 use rustc_span::source_map::Spanned;
 use rustc_span::{Span, Symbol, sym};
 use thin_vec::ThinVec;
@@ -72,35 +72,6 @@ struct PostExpansionVisitor<'a> {
 }
 
 impl<'a> PostExpansionVisitor<'a> {
-    #[allow(rustc::untranslatable_diagnostic)] // FIXME: make this translatable
-    fn check_abi(&self, abi: ast::StrLit) {
-        let ast::StrLit { symbol_unescaped, span, .. } = abi;
-
-        match rustc_abi::is_enabled(self.features, span, symbol_unescaped.as_str()) {
-            Ok(()) => (),
-            Err(rustc_abi::AbiDisabled::Unstable { feature, explain }) => {
-                feature_err_issue(&self.sess, feature, span, GateIssue::Language, explain).emit();
-            }
-            Err(rustc_abi::AbiDisabled::Unrecognized) => {
-                if self.sess.opts.pretty.is_none_or(|ppm| ppm.needs_hir()) {
-                    self.sess.dcx().span_delayed_bug(
-                        span,
-                        format!(
-                            "unrecognized ABI not caught in lowering: {}",
-                            symbol_unescaped.as_str()
-                        ),
-                    );
-                }
-            }
-        }
-    }
-
-    fn check_extern(&self, ext: ast::Extern) {
-        if let ast::Extern::Explicit(abi, _) = ext {
-            self.check_abi(abi);
-        }
-    }
-
     /// Feature gate `impl Trait` inside `type Alias = $type_expr;`.
     fn check_impl_trait(&self, ty: &ast::Ty, in_associated_ty: bool) {
         struct ImplTraitVisitor<'a> {
@@ -223,12 +194,9 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
 
     fn visit_item(&mut self, i: &'a ast::Item) {
         match &i.kind {
-            ast::ItemKind::ForeignMod(foreign_module) => {
-                if let Some(abi) = foreign_module.abi {
-                    self.check_abi(abi);
-                }
+            ast::ItemKind::ForeignMod(_foreign_module) => {
+                // handled during lowering
             }
-
             ast::ItemKind::Struct(..) | ast::ItemKind::Enum(..) | ast::ItemKind::Union(..) => {
                 for attr in attr::filter_by_name(&i.attrs, sym::repr) {
                     for item in attr.meta_item_list().unwrap_or_else(ThinVec::new) {
@@ -315,7 +283,6 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
         match &ty.kind {
             ast::TyKind::BareFn(bare_fn_ty) => {
                 // Function pointers cannot be `const`
-                self.check_extern(bare_fn_ty.ext);
                 self.check_late_bound_lifetime_defs(&bare_fn_ty.generic_params);
             }
             ast::TyKind::Never => {
@@ -418,9 +385,8 @@ impl<'a> Visitor<'a> for PostExpansionVisitor<'a> {
     }
 
     fn visit_fn(&mut self, fn_kind: FnKind<'a>, span: Span, _: NodeId) {
-        if let Some(header) = fn_kind.header() {
+        if let Some(_header) = fn_kind.header() {
             // Stability of const fn methods are covered in `visit_assoc_item` below.
-            self.check_extern(header.ext);
         }
 
         if let FnKind::Closure(ast::ClosureBinder::For { generic_params, .. }, ..) = fn_kind {
diff --git a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
index 82417a86dd9ee..5aed9f76f144f 100644
--- a/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
+++ b/compiler/rustc_builtin_macros/src/deriving/coerce_pointee.rs
@@ -3,11 +3,11 @@ use ast::ptr::P;
 use rustc_ast::mut_visit::MutVisitor;
 use rustc_ast::visit::BoundKind;
 use rustc_ast::{
-    self as ast, GenericArg, GenericBound, GenericParamKind, ItemKind, MetaItem,
+    self as ast, GenericArg, GenericBound, GenericParamKind, Generics, ItemKind, MetaItem,
     TraitBoundModifiers, VariantData, WherePredicate,
 };
-use rustc_attr_parsing as attr;
 use rustc_data_structures::flat_map_in_place::FlatMapInPlace;
+use rustc_errors::E0802;
 use rustc_expand::base::{Annotatable, ExtCtxt};
 use rustc_macros::Diagnostic;
 use rustc_span::{Ident, Span, Symbol, sym};
@@ -32,15 +32,6 @@ pub(crate) fn expand_deriving_coerce_pointee(
     let (name_ident, generics) = if let Annotatable::Item(aitem) = item
         && let ItemKind::Struct(struct_data, g) = &aitem.kind
     {
-        let is_transparent = aitem.attrs.iter().any(|attr| {
-            attr::find_repr_attrs(cx.sess, attr)
-                .into_iter()
-                .any(|r| matches!(r, attr::ReprTransparent))
-        });
-        if !is_transparent {
-            cx.dcx().emit_err(RequireTransparent { span });
-            return;
-        }
         if !matches!(
             struct_data,
             VariantData::Struct { fields, recovered: _ } | VariantData::Tuple(fields, _)
@@ -88,8 +79,7 @@ pub(crate) fn expand_deriving_coerce_pointee(
     } else {
         let mut pointees = type_params
             .iter()
-            .filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span)))
-            .fuse();
+            .filter_map(|&(idx, span, is_pointee)| is_pointee.then_some((idx, span)));
         match (pointees.next(), pointees.next()) {
             (Some((idx, _span)), None) => idx,
             (None, _) => {
@@ -110,6 +100,52 @@ pub(crate) fn expand_deriving_coerce_pointee(
     // Declare helper function that adds implementation blocks.
     // FIXME(dingxiangfei2009): Investigate the set of attributes on target struct to be propagated to impls
     let attrs = thin_vec![cx.attr_word(sym::automatically_derived, span),];
+    // # Validity assertion which will be checked later in `rustc_hir_analysis::coherence::builtins`.
+    {
+        let trait_path =
+            cx.path_all(span, true, path!(span, core::marker::CoercePointeeValidated), vec![]);
+        let trait_ref = cx.trait_ref(trait_path);
+        push(Annotatable::Item(
+            cx.item(
+                span,
+                Ident::empty(),
+                attrs.clone(),
+                ast::ItemKind::Impl(Box::new(ast::Impl {
+                    safety: ast::Safety::Default,
+                    polarity: ast::ImplPolarity::Positive,
+                    defaultness: ast::Defaultness::Final,
+                    constness: ast::Const::No,
+                    generics: Generics {
+                        params: generics
+                            .params
+                            .iter()
+                            .map(|p| match &p.kind {
+                                GenericParamKind::Lifetime => {
+                                    cx.lifetime_param(p.span(), p.ident, p.bounds.clone())
+                                }
+                                GenericParamKind::Type { default: _ } => {
+                                    cx.typaram(p.span(), p.ident, p.bounds.clone(), None)
+                                }
+                                GenericParamKind::Const { ty, kw_span: _, default: _ } => cx
+                                    .const_param(
+                                        p.span(),
+                                        p.ident,
+                                        p.bounds.clone(),
+                                        ty.clone(),
+                                        None,
+                                    ),
+                            })
+                            .collect(),
+                        where_clause: generics.where_clause.clone(),
+                        span: generics.span,
+                    },
+                    of_trait: Some(trait_ref),
+                    self_ty: self_type.clone(),
+                    items: ThinVec::new(),
+                })),
+            ),
+        ));
+    }
     let mut add_impl_block = |generics, trait_symbol, trait_args| {
         let mut parts = path!(span, core::ops);
         parts.push(Ident::new(trait_symbol, span));
@@ -430,35 +466,35 @@ impl<'a, 'b> rustc_ast::visit::Visitor<'a> for AlwaysErrorOnGenericParam<'a, 'b>
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_coerce_pointee_requires_transparent)]
+#[diag(builtin_macros_coerce_pointee_requires_transparent, code = E0802)]
 struct RequireTransparent {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_coerce_pointee_requires_one_field)]
+#[diag(builtin_macros_coerce_pointee_requires_one_field, code = E0802)]
 struct RequireOneField {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_coerce_pointee_requires_one_generic)]
+#[diag(builtin_macros_coerce_pointee_requires_one_generic, code = E0802)]
 struct RequireOneGeneric {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_coerce_pointee_requires_one_pointee)]
+#[diag(builtin_macros_coerce_pointee_requires_one_pointee, code = E0802)]
 struct RequireOnePointee {
     #[primary_span]
     span: Span,
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_coerce_pointee_too_many_pointees)]
+#[diag(builtin_macros_coerce_pointee_too_many_pointees, code = E0802)]
 struct TooManyPointees {
     #[primary_span]
     one: Span,
@@ -467,7 +503,7 @@ struct TooManyPointees {
 }
 
 #[derive(Diagnostic)]
-#[diag(builtin_macros_coerce_pointee_requires_maybe_sized)]
+#[diag(builtin_macros_coerce_pointee_requires_maybe_sized, code = E0802)]
 struct RequiresMaybeSized {
     #[primary_span]
     span: Span,
diff --git a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
index 2c38fb5658f22..1d8f61806f56e 100644
--- a/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
+++ b/compiler/rustc_codegen_ssa/src/codegen_attrs.rs
@@ -1,5 +1,6 @@
 use std::str::FromStr;
 
+use rustc_abi::ExternAbi;
 use rustc_ast::attr::list_contains_name;
 use rustc_ast::expand::autodiff_attrs::{
     AutoDiffAttrs, DiffActivity, DiffMode, valid_input_activity, valid_ret_activity,
@@ -23,7 +24,7 @@ use rustc_middle::ty::{self as ty, TyCtxt};
 use rustc_session::parse::feature_err;
 use rustc_session::{Session, lint};
 use rustc_span::{Ident, Span, sym};
-use rustc_target::spec::{SanitizerSet, abi};
+use rustc_target::spec::SanitizerSet;
 use tracing::debug;
 
 use crate::errors;
@@ -219,7 +220,7 @@ fn codegen_fn_attrs(tcx: TyCtxt<'_>, did: LocalDefId) -> CodegenFnAttrs {
 
                 if !is_closure
                     && let Some(fn_sig) = fn_sig()
-                    && fn_sig.skip_binder().abi() != abi::Abi::Rust
+                    && fn_sig.skip_binder().abi() != ExternAbi::Rust
                 {
                     struct_span_code_err!(
                         tcx.dcx(),
diff --git a/compiler/rustc_driver_impl/Cargo.toml b/compiler/rustc_driver_impl/Cargo.toml
index 07b88e59723d9..0b45e5786e83d 100644
--- a/compiler/rustc_driver_impl/Cargo.toml
+++ b/compiler/rustc_driver_impl/Cargo.toml
@@ -5,6 +5,7 @@ edition = "2021"
 
 [dependencies]
 # tidy-alphabetical-start
+rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
 rustc_ast_lowering = { path = "../rustc_ast_lowering" }
 rustc_ast_passes = { path = "../rustc_ast_passes" }
diff --git a/compiler/rustc_driver_impl/src/lib.rs b/compiler/rustc_driver_impl/src/lib.rs
index 4c47ce93dd56f..6efd11a8c3c07 100644
--- a/compiler/rustc_driver_impl/src/lib.rs
+++ b/compiler/rustc_driver_impl/src/lib.rs
@@ -747,7 +747,7 @@ fn print_crate_info(
                 }
             }
             CallingConventions => {
-                let mut calling_conventions = rustc_target::spec::abi::all_names();
+                let mut calling_conventions = rustc_abi::all_names();
                 calling_conventions.sort_unstable();
                 println_info!("{}", calling_conventions.join("\n"));
             }
diff --git a/compiler/rustc_error_codes/src/error_codes/E0802.md b/compiler/rustc_error_codes/src/error_codes/E0802.md
new file mode 100644
index 0000000000000..59061ff04359d
--- /dev/null
+++ b/compiler/rustc_error_codes/src/error_codes/E0802.md
@@ -0,0 +1,94 @@
+The target of `derive(CoercePointee)` macro has inadmissible specification for
+a meaningful use.
+
+Erroneous code examples:
+
+The target data is not a `struct`.
+
+```compile_fail,E0802
+#![feature(coerce_pointee)]
+use std::marker::CoercePointee;
+#[derive(CoercePointee)]
+enum NotStruct<'a, T: ?Sized> {
+    Variant(&'a T),
+}
+```
+
+The target data has a layout that is not transparent, or `repr(transparent)`
+in other words.
+
+```compile_fail,E0802
+#![feature(coerce_pointee)]
+use std::marker::CoercePointee;
+#[derive(CoercePointee)]
+struct NotTransparent<'a, #[pointee] T: ?Sized> {
+    ptr: &'a T,
+}
+```
+
+The target data has no data field.
+
+```compile_fail,E0802
+#![feature(coerce_pointee)]
+use std::marker::CoercePointee;
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct NoField<'a, #[pointee] T: ?Sized> {}
+```
+
+The target data is not generic over any data, or has no generic type parameter.
+
+```compile_fail,E0802
+#![feature(coerce_pointee)]
+use std::marker::CoercePointee;
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct NoGeneric<'a>(&'a u8);
+```
+
+The target data has multiple generic type parameters, but none is designated as
+a pointee for coercion.
+
+```compile_fail,E0802
+#![feature(coerce_pointee)]
+use std::marker::CoercePointee;
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct AmbiguousPointee<'a, T1: ?Sized, T2: ?Sized> {
+    a: (&'a T1, &'a T2),
+}
+```
+
+The target data has multiple generic type parameters that are designated as
+pointees for coercion.
+
+```compile_fail,E0802
+#![feature(coerce_pointee)]
+use std::marker::CoercePointee;
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct TooManyPointees<
+    'a,
+    #[pointee] A: ?Sized,
+    #[pointee] B: ?Sized>
+((&'a A, &'a B));
+```
+
+The type parameter that is designated as a pointee is not marked `?Sized`.
+
+```compile_fail,E0802
+#![feature(coerce_pointee)]
+use std::marker::CoercePointee;
+#[derive(CoercePointee)]
+#[repr(transparent)]
+struct NoMaybeSized<'a, #[pointee] T> {
+    ptr: &'a T,
+}
+```
+
+In summary, the `CoercePointee` macro demands the type to be a `struct` that is
+generic over at least one type or over more types, one of which is marked with
+`#[pointee]`, and has at least one data field and adopts a `repr(transparent)`
+layout.
+The only generic type or the type marked with `#[pointee]` has to be also
+marked as `?Sized`.
diff --git a/compiler/rustc_error_codes/src/lib.rs b/compiler/rustc_error_codes/src/lib.rs
index 0a30bdb48a09c..e970b16f61064 100644
--- a/compiler/rustc_error_codes/src/lib.rs
+++ b/compiler/rustc_error_codes/src/lib.rs
@@ -545,6 +545,7 @@ E0798: 0798,
 E0799: 0799,
 E0800: 0800,
 E0801: 0801,
+E0802: 0802,
         );
     )
 }
diff --git a/compiler/rustc_expand/src/build.rs b/compiler/rustc_expand/src/build.rs
index 046213b5a6a6d..ee7f68cc2f01c 100644
--- a/compiler/rustc_expand/src/build.rs
+++ b/compiler/rustc_expand/src/build.rs
@@ -1,7 +1,8 @@
 use rustc_ast::ptr::P;
 use rustc_ast::util::literal;
 use rustc_ast::{
-    self as ast, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp, attr, token,
+    self as ast, AnonConst, AttrVec, BlockCheckMode, Expr, LocalKind, MatchKind, PatKind, UnOp,
+    attr, token,
 };
 use rustc_span::source_map::Spanned;
 use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
@@ -138,6 +139,42 @@ impl<'a> ExtCtxt<'a> {
         }
     }
 
+    pub fn lifetime_param(
+        &self,
+        span: Span,
+        ident: Ident,
+        bounds: ast::GenericBounds,
+    ) -> ast::GenericParam {
+        ast::GenericParam {
+            id: ast::DUMMY_NODE_ID,
+            ident: ident.with_span_pos(span),
+            attrs: AttrVec::new(),
+            bounds,
+            is_placeholder: false,
+            kind: ast::GenericParamKind::Lifetime,
+            colon_span: None,
+        }
+    }
+
+    pub fn const_param(
+        &self,
+        span: Span,
+        ident: Ident,
+        bounds: ast::GenericBounds,
+        ty: P<ast::Ty>,
+        default: Option<AnonConst>,
+    ) -> ast::GenericParam {
+        ast::GenericParam {
+            id: ast::DUMMY_NODE_ID,
+            ident: ident.with_span_pos(span),
+            attrs: AttrVec::new(),
+            bounds,
+            is_placeholder: false,
+            kind: ast::GenericParamKind::Const { ty, kw_span: DUMMY_SP, default },
+            colon_span: None,
+        }
+    }
+
     pub fn trait_ref(&self, path: ast::Path) -> ast::TraitRef {
         ast::TraitRef { path, ref_id: ast::DUMMY_NODE_ID }
     }
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 3a2e810dc6af7..a4c5e4800eb4a 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -513,6 +513,8 @@ declare_features! (
     (incomplete, generic_const_exprs, "1.56.0", Some(76560)),
     /// Allows generic parameters and where-clauses on free & associated const items.
     (incomplete, generic_const_items, "1.73.0", Some(113521)),
+    /// Allows any generic constants being used as pattern type range ends
+    (incomplete, generic_pattern_types, "CURRENT_RUSTC_VERSION", Some(136574)),
     /// Allows registering static items globally, possibly across crates, to iterate over at runtime.
     (unstable, global_registration, "1.80.0", Some(125119)),
     /// Allows using guards in patterns.
diff --git a/compiler/rustc_hir/src/lang_items.rs b/compiler/rustc_hir/src/lang_items.rs
index b6689c95c4bb2..1852987b1677f 100644
--- a/compiler/rustc_hir/src/lang_items.rs
+++ b/compiler/rustc_hir/src/lang_items.rs
@@ -370,6 +370,8 @@ language_item_table! {
 
     PointerLike,             sym::pointer_like,        pointer_like,               Target::Trait,          GenericRequirement::Exact(0);
 
+    CoercePointeeValidated, sym::coerce_pointee_validated, coerce_pointee_validated_trait, Target::Trait,     GenericRequirement::Exact(0);
+
     ConstParamTy,            sym::const_param_ty,      const_param_ty_trait,       Target::Trait,          GenericRequirement::Exact(0);
     UnsizedConstParamTy,     sym::unsized_const_param_ty, unsized_const_param_ty_trait, Target::Trait, GenericRequirement::Exact(0);
 
@@ -429,9 +431,13 @@ language_item_table! {
     ContractCheckRequires,     sym::contract_check_requires,      contract_check_requires_fn,      Target::Fn, GenericRequirement::None;
 }
 
+/// The requirement imposed on the generics of a lang item
 pub enum GenericRequirement {
+    /// No restriction on the generics
     None,
+    /// A minimum number of generics that is demanded on a lang item
     Minimum(usize),
+    /// The number of generics must match precisely as stipulated
     Exact(usize),
 }
 
diff --git a/compiler/rustc_hir_analysis/messages.ftl b/compiler/rustc_hir_analysis/messages.ftl
index c28c1afcfe66c..258267c5ca929 100644
--- a/compiler/rustc_hir_analysis/messages.ftl
+++ b/compiler/rustc_hir_analysis/messages.ftl
@@ -85,6 +85,16 @@ hir_analysis_cmse_output_stack_spill =
     .note1 = functions with the `"{$abi_name}"` ABI must pass their result via the available return registers
     .note2 = the result must either be a (transparently wrapped) i64, u64 or f64, or be at most 4 bytes in size
 
+hir_analysis_coerce_pointee_no_field = `CoercePointee` can only be derived on `struct`s with at least one field
+
+hir_analysis_coerce_pointee_no_user_validity_assertion = asserting applicability of `derive(CoercePointee)` on a target data is forbidden
+
+hir_analysis_coerce_pointee_not_concrete_ty = `derive(CoercePointee)` is only applicable to `struct`
+
+hir_analysis_coerce_pointee_not_struct = `derive(CoercePointee)` is only applicable to `struct`, instead of `{$kind}`
+
+hir_analysis_coerce_pointee_not_transparent = `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
+
 hir_analysis_coerce_unsized_may = the trait `{$trait_name}` may only be implemented for a coercion between structures
 
 hir_analysis_coerce_unsized_multi = implementing the trait `CoerceUnsized` requires multiple coercions
diff --git a/compiler/rustc_hir_analysis/src/coherence/builtin.rs b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
index 66082f4c282b3..9da57c330c5ef 100644
--- a/compiler/rustc_hir_analysis/src/coherence/builtin.rs
+++ b/compiler/rustc_hir_analysis/src/coherence/builtin.rs
@@ -48,6 +48,10 @@ pub(super) fn check_trait<'tcx>(
     checker
         .check(lang_items.dispatch_from_dyn_trait(), visit_implementation_of_dispatch_from_dyn)?;
     checker.check(lang_items.pointer_like(), visit_implementation_of_pointer_like)?;
+    checker.check(
+        lang_items.coerce_pointee_validated_trait(),
+        visit_implementation_of_coerce_pointee_validity,
+    )?;
     Ok(())
 }
 
@@ -783,3 +787,32 @@ fn visit_implementation_of_pointer_like(checker: &Checker<'_>) -> Result<(), Err
         .with_note(why_disqualified)
         .emit())
 }
+
+fn visit_implementation_of_coerce_pointee_validity(
+    checker: &Checker<'_>,
+) -> Result<(), ErrorGuaranteed> {
+    let tcx = checker.tcx;
+    let self_ty = tcx.impl_trait_ref(checker.impl_def_id).unwrap().instantiate_identity().self_ty();
+    let span = tcx.def_span(checker.impl_def_id);
+    if !tcx.is_builtin_derived(checker.impl_def_id.into()) {
+        return Err(tcx.dcx().emit_err(errors::CoercePointeeNoUserValidityAssertion { span }));
+    }
+    let ty::Adt(def, _args) = self_ty.kind() else {
+        return Err(tcx.dcx().emit_err(errors::CoercePointeeNotConcreteType { span }));
+    };
+    let did = def.did();
+    // Now get a more precise span of the `struct`.
+    let span = tcx.def_span(did);
+    if !def.is_struct() {
+        return Err(tcx
+            .dcx()
+            .emit_err(errors::CoercePointeeNotStruct { span, kind: def.descr().into() }));
+    }
+    if !def.repr().transparent() {
+        return Err(tcx.dcx().emit_err(errors::CoercePointeeNotTransparent { span }));
+    }
+    if def.all_fields().next().is_none() {
+        return Err(tcx.dcx().emit_err(errors::CoercePointeeNoField { span }));
+    }
+    Ok(())
+}
diff --git a/compiler/rustc_hir_analysis/src/errors.rs b/compiler/rustc_hir_analysis/src/errors.rs
index 9769be302264d..12750543f4bf7 100644
--- a/compiler/rustc_hir_analysis/src/errors.rs
+++ b/compiler/rustc_hir_analysis/src/errors.rs
@@ -1180,6 +1180,42 @@ pub(crate) struct DispatchFromDynRepr {
     pub span: Span,
 }
 
+#[derive(Diagnostic)]
+#[diag(hir_analysis_coerce_pointee_not_struct, code = E0802)]
+pub(crate) struct CoercePointeeNotStruct {
+    #[primary_span]
+    pub span: Span,
+    pub kind: String,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_coerce_pointee_not_concrete_ty, code = E0802)]
+pub(crate) struct CoercePointeeNotConcreteType {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_coerce_pointee_no_user_validity_assertion, code = E0802)]
+pub(crate) struct CoercePointeeNoUserValidityAssertion {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_coerce_pointee_not_transparent, code = E0802)]
+pub(crate) struct CoercePointeeNotTransparent {
+    #[primary_span]
+    pub span: Span,
+}
+
+#[derive(Diagnostic)]
+#[diag(hir_analysis_coerce_pointee_no_field, code = E0802)]
+pub(crate) struct CoercePointeeNoField {
+    #[primary_span]
+    pub span: Span,
+}
+
 #[derive(Diagnostic)]
 #[diag(hir_analysis_inherent_ty_outside_relevant, code = E0390)]
 #[help]
diff --git a/compiler/rustc_hir_typeck/src/method/confirm.rs b/compiler/rustc_hir_typeck/src/method/confirm.rs
index 3e48e8d15c3cd..36cc9b40d0081 100644
--- a/compiler/rustc_hir_typeck/src/method/confirm.rs
+++ b/compiler/rustc_hir_typeck/src/method/confirm.rs
@@ -681,17 +681,23 @@ impl<'a, 'tcx> ConfirmContext<'a, 'tcx> {
             traits::upcast_choices(self.tcx, source_trait_ref, target_trait_def_id);
 
         // must be exactly one trait ref or we'd get an ambig error etc
-        let [upcast_trait_ref] = upcast_trait_refs.as_slice() else {
-            span_bug!(
+        if let &[upcast_trait_ref] = upcast_trait_refs.as_slice() {
+            upcast_trait_ref
+        } else {
+            self.dcx().span_delayed_bug(
                 self.span,
-                "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
-                source_trait_ref,
-                target_trait_def_id,
-                upcast_trait_refs
-            )
-        };
+                format!(
+                    "cannot uniquely upcast `{:?}` to `{:?}`: `{:?}`",
+                    source_trait_ref, target_trait_def_id, upcast_trait_refs
+                ),
+            );
 
-        *upcast_trait_ref
+            ty::Binder::dummy(ty::TraitRef::new_from_args(
+                self.tcx,
+                target_trait_def_id,
+                ty::GenericArgs::extend_with_error(self.tcx, target_trait_def_id, &[]),
+            ))
+        }
     }
 
     fn instantiate_binder_with_fresh_vars<T>(&self, value: ty::Binder<'tcx, T>) -> T
diff --git a/compiler/rustc_passes/Cargo.toml b/compiler/rustc_passes/Cargo.toml
index 2b8a3b9ce235c..f592a12ab75c1 100644
--- a/compiler/rustc_passes/Cargo.toml
+++ b/compiler/rustc_passes/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
 # tidy-alphabetical-start
 rustc_abi = { path = "../rustc_abi" }
 rustc_ast = { path = "../rustc_ast" }
+rustc_ast_lowering = { path = "../rustc_ast_lowering" }
 rustc_ast_pretty = { path = "../rustc_ast_pretty" }
 rustc_attr_parsing = { path = "../rustc_attr_parsing" }
 rustc_data_structures = { path = "../rustc_data_structures" }
diff --git a/compiler/rustc_passes/src/naked_functions.rs b/compiler/rustc_passes/src/naked_functions.rs
index 1e165b22e51c2..875b6edb58cbc 100644
--- a/compiler/rustc_passes/src/naked_functions.rs
+++ b/compiler/rustc_passes/src/naked_functions.rs
@@ -1,5 +1,6 @@
 //! Checks validity of naked functions.
 
+use rustc_abi::ExternAbi;
 use rustc_hir as hir;
 use rustc_hir::def::DefKind;
 use rustc_hir::def_id::{LocalDefId, LocalModDefId};
@@ -11,7 +12,6 @@ use rustc_middle::span_bug;
 use rustc_middle::ty::TyCtxt;
 use rustc_session::lint::builtin::UNDEFINED_NAKED_FUNCTION_ABI;
 use rustc_span::{Span, sym};
-use rustc_target::spec::abi::Abi;
 
 use crate::errors::{
     NakedAsmOutsideNakedFn, NakedFunctionsAsmBlock, NakedFunctionsMustNakedAsm, NoPatterns,
@@ -61,8 +61,8 @@ fn check_mod_naked_functions(tcx: TyCtxt<'_>, module_def_id: LocalModDefId) {
 }
 
 /// Checks that function uses non-Rust ABI.
-fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: Abi) {
-    if abi == Abi::Rust {
+fn check_abi(tcx: TyCtxt<'_>, def_id: LocalDefId, abi: ExternAbi) {
+    if abi == ExternAbi::Rust {
         let hir_id = tcx.local_def_id_to_hir_id(def_id);
         let span = tcx.def_span(def_id);
         tcx.emit_node_span_lint(
diff --git a/compiler/rustc_passes/src/stability.rs b/compiler/rustc_passes/src/stability.rs
index 34f1ca55c7875..fd30d0d4867fe 100644
--- a/compiler/rustc_passes/src/stability.rs
+++ b/compiler/rustc_passes/src/stability.rs
@@ -4,6 +4,7 @@
 use std::mem::replace;
 use std::num::NonZero;
 
+use rustc_ast_lowering::stability::extern_abi_stability;
 use rustc_attr_parsing::{
     self as attr, ConstStability, DeprecatedSince, Stability, StabilityLevel, StableSince,
     UnstableReason, VERSION_PLACEHOLDER,
@@ -1027,8 +1028,8 @@ impl<'tcx> Visitor<'tcx> for CheckTraitImplStable<'tcx> {
         if let TyKind::Never = t.kind {
             self.fully_stable = false;
         }
-        if let TyKind::BareFn(f) = t.kind {
-            if rustc_target::spec::abi::is_stable(f.abi.name()).is_err() {
+        if let TyKind::BareFn(function) = t.kind {
+            if extern_abi_stability(function.abi).is_err() {
                 self.fully_stable = false;
             }
         }
diff --git a/compiler/rustc_span/src/symbol.rs b/compiler/rustc_span/src/symbol.rs
index c819d43323583..bb59b4c40bd7f 100644
--- a/compiler/rustc_span/src/symbol.rs
+++ b/compiler/rustc_span/src/symbol.rs
@@ -193,6 +193,7 @@ symbols! {
         Cleanup,
         Clone,
         CoercePointee,
+        CoercePointeeValidated,
         CoerceUnsized,
         Command,
         ConstParamTy,
@@ -619,6 +620,7 @@ symbols! {
         cmp_partialord_lt,
         cmpxchg16b_target_feature,
         cmse_nonsecure_entry,
+        coerce_pointee_validated,
         coerce_unsized,
         cold,
         cold_path,
@@ -1024,6 +1026,7 @@ symbols! {
         generic_const_exprs,
         generic_const_items,
         generic_param_attrs,
+        generic_pattern_types,
         get_context,
         global_alloc_ty,
         global_allocator,
diff --git a/compiler/rustc_target/src/spec/mod.rs b/compiler/rustc_target/src/spec/mod.rs
index df1862ec27eee..810d8aa820043 100644
--- a/compiler/rustc_target/src/spec/mod.rs
+++ b/compiler/rustc_target/src/spec/mod.rs
@@ -57,13 +57,6 @@ use crate::spec::crt_objects::CrtObjects;
 
 pub mod crt_objects;
 
-pub mod abi {
-    pub use rustc_abi::{
-        AbiDisabled, AbiUnsupported, ExternAbi as Abi, all_names, enabled_names, is_enabled,
-        is_stable, lookup,
-    };
-}
-
 mod base;
 mod json;
 
diff --git a/compiler/rustc_trait_selection/src/traits/wf.rs b/compiler/rustc_trait_selection/src/traits/wf.rs
index 96051ad0aa54f..c27bd269b0d9f 100644
--- a/compiler/rustc_trait_selection/src/traits/wf.rs
+++ b/compiler/rustc_trait_selection/src/traits/wf.rs
@@ -8,8 +8,9 @@ use rustc_middle::ty::{
     self, GenericArg, GenericArgKind, GenericArgsRef, Ty, TyCtxt, TypeSuperVisitable,
     TypeVisitable, TypeVisitableExt, TypeVisitor,
 };
-use rustc_span::Span;
+use rustc_session::parse::feature_err;
 use rustc_span::def_id::{DefId, LocalDefId};
+use rustc_span::{Span, sym};
 use tracing::{debug, instrument, trace};
 
 use crate::infer::InferCtxt;
@@ -704,8 +705,47 @@ impl<'a, 'tcx> TypeVisitor<TyCtxt<'tcx>> for WfPredicates<'a, 'tcx> {
                 ));
             }
 
-            ty::Pat(subty, _) => {
+            ty::Pat(subty, pat) => {
                 self.require_sized(subty, ObligationCauseCode::Misc);
+                match *pat {
+                    ty::PatternKind::Range { start, end, include_end: _ } => {
+                        let mut check = |c| {
+                            let cause = self.cause(ObligationCauseCode::Misc);
+                            self.out.push(traits::Obligation::with_depth(
+                                tcx,
+                                cause.clone(),
+                                self.recursion_depth,
+                                self.param_env,
+                                ty::Binder::dummy(ty::PredicateKind::Clause(
+                                    ty::ClauseKind::ConstArgHasType(c, subty),
+                                )),
+                            ));
+                            if !tcx.features().generic_pattern_types() {
+                                if c.has_param() {
+                                    if self.span.is_dummy() {
+                                        self.tcx().dcx().delayed_bug(
+                                            "feature error should be reported elsewhere, too",
+                                        );
+                                    } else {
+                                        feature_err(
+                                            &self.tcx().sess,
+                                            sym::generic_pattern_types,
+                                            self.span,
+                                            "wraparound pattern type ranges cause monomorphization time errors",
+                                        )
+                                        .emit();
+                                    }
+                                }
+                            }
+                        };
+                        if let Some(start) = start {
+                            check(start)
+                        }
+                        if let Some(end) = end {
+                            check(end)
+                        }
+                    }
+                }
             }
 
             ty::Tuple(tys) => {
diff --git a/library/core/src/marker.rs b/library/core/src/marker.rs
index 1a8ef20dd7b9d..029c8b356d074 100644
--- a/library/core/src/marker.rs
+++ b/library/core/src/marker.rs
@@ -1284,8 +1284,22 @@ pub trait FnPtr: Copy + Clone {
 /// }
 /// ```
 #[rustc_builtin_macro(CoercePointee, attributes(pointee))]
-#[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize)]
+#[allow_internal_unstable(dispatch_from_dyn, coerce_unsized, unsize, coerce_pointee_validated)]
 #[unstable(feature = "derive_coerce_pointee", issue = "123430")]
 pub macro CoercePointee($item:item) {
     /* compiler built-in */
 }
+
+/// A trait that is implemented for ADTs with `derive(CoercePointee)` so that
+/// the compiler can enforce the derive impls are valid post-expansion, since
+/// the derive has stricter requirements than if the impls were written by hand.
+///
+/// This trait is not intended to be implemented by users or used other than
+/// validation, so it should never be stabilized.
+#[cfg(not(bootstrap))]
+#[lang = "coerce_pointee_validated"]
+#[unstable(feature = "coerce_pointee_validated", issue = "none")]
+#[doc(hidden)]
+pub trait CoercePointeeValidated {
+    /* compiler built-in */
+}
diff --git a/src/ci/github-actions/jobs.yml b/src/ci/github-actions/jobs.yml
index 8ae6d543bc598..738c8aaaed8d8 100644
--- a/src/ci/github-actions/jobs.yml
+++ b/src/ci/github-actions/jobs.yml
@@ -460,26 +460,26 @@ auto:
 
   - name: x86_64-msvc-1
     env:
-      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-sanitizers --enable-profiler
       SCRIPT: make ci-msvc-py
     <<: *job-windows-25
 
   - name: x86_64-msvc-2
     env:
-      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-profiler
+      RUST_CONFIGURE_ARGS: --build=x86_64-pc-windows-msvc --enable-sanitizers --enable-profiler
       SCRIPT: make ci-msvc-ps1
     <<: *job-windows-25
 
   # i686-msvc is split into two jobs to run tests in parallel.
   - name: i686-msvc-1
     env:
-      RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
+      RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc  --enable-sanitizers
       SCRIPT: make ci-msvc-py
     <<: *job-windows
 
   - name: i686-msvc-2
     env:
-      RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc
+      RUST_CONFIGURE_ARGS: --build=i686-pc-windows-msvc --enable-sanitizers
       SCRIPT: make ci-msvc-ps1
     <<: *job-windows
 
diff --git a/src/doc/edition-guide b/src/doc/edition-guide
index f56aecc3b036d..8dbdda7cae4fa 160000
--- a/src/doc/edition-guide
+++ b/src/doc/edition-guide
@@ -1 +1 @@
-Subproject commit f56aecc3b036dff16404b525a83b00f911b9bbea
+Subproject commit 8dbdda7cae4fa030f09f8f5b63994d4d1dde74b9
diff --git a/src/doc/embedded-book b/src/doc/embedded-book
index ddbf1b4e2858f..0b8219ac23a3e 160000
--- a/src/doc/embedded-book
+++ b/src/doc/embedded-book
@@ -1 +1 @@
-Subproject commit ddbf1b4e2858fedb71b7c42eb15c4576517dc125
+Subproject commit 0b8219ac23a3e09464e4e0166c768cf1c4bba0d5
diff --git a/src/doc/reference b/src/doc/reference
index 4249fb411dd27..de2d5289e4550 160000
--- a/src/doc/reference
+++ b/src/doc/reference
@@ -1 +1 @@
-Subproject commit 4249fb411dd27f945e2881eb0378044b94cee06f
+Subproject commit de2d5289e45506b11dd652bef4f99de64be70e1c
diff --git a/src/doc/rust-by-example b/src/doc/rust-by-example
index 743766929f1e5..66543bbc5b7db 160000
--- a/src/doc/rust-by-example
+++ b/src/doc/rust-by-example
@@ -1 +1 @@
-Subproject commit 743766929f1e53e72fab74394ae259bbfb4a7619
+Subproject commit 66543bbc5b7dbd4e679092c07ae06ba6c73fd912
diff --git a/tests/incremental/feature_gate.rs b/tests/incremental/feature_gate.rs
index 54c2dbb352e14..332cf944b5d65 100644
--- a/tests/incremental/feature_gate.rs
+++ b/tests/incremental/feature_gate.rs
@@ -10,4 +10,4 @@ fn main() {
 }
 
 extern "unadjusted" fn foo() {}
-//[cfail2]~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable
+//[cfail2]~^ ERROR: "unadjusted" ABI is an implementation detail and perma-unstable
diff --git a/tests/ui/abi/removed-wasm-abi.rs b/tests/ui/abi/removed-wasm-abi.rs
deleted file mode 100644
index a45e42bfe020e..0000000000000
--- a/tests/ui/abi/removed-wasm-abi.rs
+++ /dev/null
@@ -1,4 +0,0 @@
-extern "wasm" fn test() {}
-//~^ ERROR invalid ABI: found `wasm`
-
-fn main() {}
diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr
index e80411fda344e..e1f433479857a 100644
--- a/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr
+++ b/tests/ui/abi/riscv-discoverability-guidance.riscv32.stderr
@@ -8,10 +8,9 @@ LL | extern "riscv-interrupt" fn isr() {}
    |        help: did you mean: `"riscv-interrupt-m"`
    |
    = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
-   = note: please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively
 
 error[E0703]: invalid ABI: found `riscv-interrupt-u`
-  --> $DIR/riscv-discoverability-guidance.rs:23:8
+  --> $DIR/riscv-discoverability-guidance.rs:22:8
    |
 LL | extern "riscv-interrupt-u" fn isr_U() {}
    |        ^^^^^^^^^^^^^^^^^^^
@@ -20,7 +19,6 @@ LL | extern "riscv-interrupt-u" fn isr_U() {}
    |        help: did you mean: `"riscv-interrupt-m"`
    |
    = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
-   = note: user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr
index e80411fda344e..e1f433479857a 100644
--- a/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr
+++ b/tests/ui/abi/riscv-discoverability-guidance.riscv64.stderr
@@ -8,10 +8,9 @@ LL | extern "riscv-interrupt" fn isr() {}
    |        help: did you mean: `"riscv-interrupt-m"`
    |
    = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
-   = note: please use one of riscv-interrupt-m or riscv-interrupt-s for machine- or supervisor-level interrupts, respectively
 
 error[E0703]: invalid ABI: found `riscv-interrupt-u`
-  --> $DIR/riscv-discoverability-guidance.rs:23:8
+  --> $DIR/riscv-discoverability-guidance.rs:22:8
    |
 LL | extern "riscv-interrupt-u" fn isr_U() {}
    |        ^^^^^^^^^^^^^^^^^^^
@@ -20,7 +19,6 @@ LL | extern "riscv-interrupt-u" fn isr_U() {}
    |        help: did you mean: `"riscv-interrupt-m"`
    |
    = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
-   = note: user-mode interrupt handlers have been removed from LLVM pending standardization, see: https://reviews.llvm.org/D149314
 
 error: aborting due to 2 previous errors
 
diff --git a/tests/ui/abi/riscv-discoverability-guidance.rs b/tests/ui/abi/riscv-discoverability-guidance.rs
index 1b189d907baf6..dec5059b0a7f0 100644
--- a/tests/ui/abi/riscv-discoverability-guidance.rs
+++ b/tests/ui/abi/riscv-discoverability-guidance.rs
@@ -18,10 +18,8 @@ extern "riscv-interrupt" fn isr() {}
 //~^ ERROR invalid ABI
 //~^^ NOTE invalid ABI
 //~^^^ NOTE invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
-//~^^^^ NOTE please use one of riscv-interrupt-m or riscv-interrupt-s
 
 extern "riscv-interrupt-u" fn isr_U() {}
 //~^ ERROR invalid ABI
 //~^^ NOTE invalid ABI
 //~^^^ NOTE invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
-//~^^^^ NOTE user-mode interrupt handlers have been removed from LLVM pending standardization
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr
index 120d5cc5293b4..63260b5c78fdc 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-call/gate_test.stderr
@@ -1,4 +1,4 @@
-error[E0658]: C-cmse-nonsecure-call ABI is experimental and subject to change
+error[E0658]: the extern "C-cmse-nonsecure-call" ABI is experimental and subject to change
   --> $DIR/gate_test.rs:5:46
    |
 LL |         core::mem::transmute::<usize, extern "C-cmse-nonsecure-call" fn(i32, i32, i32, i32) -> i32>(
diff --git a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
index dabf16cab3098..0afbbe647af0c 100644
--- a/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
+++ b/tests/ui/cmse-nonsecure/cmse-nonsecure-entry/gate_test.stderr
@@ -1,4 +1,4 @@
-error[E0658]: C-cmse-nonsecure-entry ABI is experimental and subject to change
+error[E0658]: the extern "C-cmse-nonsecure-entry" ABI is experimental and subject to change
   --> $DIR/gate_test.rs:4:12
    |
 LL | pub extern "C-cmse-nonsecure-entry" fn entry_function(input: u32) -> u32 {
diff --git a/tests/ui/deriving/auxiliary/malicious-macro.rs b/tests/ui/deriving/auxiliary/malicious-macro.rs
new file mode 100644
index 0000000000000..6665b40a14f2b
--- /dev/null
+++ b/tests/ui/deriving/auxiliary/malicious-macro.rs
@@ -0,0 +1,31 @@
+#![feature(let_chains)]
+
+extern crate proc_macro;
+
+use proc_macro::{Delimiter, TokenStream, TokenTree};
+
+#[proc_macro_attribute]
+pub fn norepr(_: TokenStream, input: TokenStream) -> TokenStream {
+    let mut tokens = vec![];
+    let mut tts = input.into_iter().fuse().peekable();
+    loop {
+        let Some(token) = tts.next() else { break };
+        if let TokenTree::Punct(punct) = &token
+            && punct.as_char() == '#'
+        {
+            if let Some(TokenTree::Group(group)) = tts.peek()
+                && let Delimiter::Bracket = group.delimiter()
+                && let Some(TokenTree::Ident(ident)) = group.stream().into_iter().next()
+                && ident.to_string() == "repr"
+            {
+                let _ = tts.next();
+                // skip '#' and '[repr(..)]
+            } else {
+                tokens.push(token);
+            }
+        } else {
+            tokens.push(token);
+        }
+    }
+    tokens.into_iter().collect()
+}
diff --git a/tests/ui/deriving/built-in-proc-macro-scope.stdout b/tests/ui/deriving/built-in-proc-macro-scope.stdout
index db97c7145ea09..fa4e50968f4de 100644
--- a/tests/ui/deriving/built-in-proc-macro-scope.stdout
+++ b/tests/ui/deriving/built-in-proc-macro-scope.stdout
@@ -20,6 +20,8 @@ pub struct Ptr<'a, #[pointee] T: ?Sized> {
     data: &'a mut T,
 }
 #[automatically_derived]
+impl<'a, T: ?Sized> ::core::marker::CoercePointeeValidated for Ptr<'a, T> { }
+#[automatically_derived]
 impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
     ::core::ops::DispatchFromDyn<Ptr<'a, __S>> for Ptr<'a, T> {
 }
diff --git a/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout b/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout
index d6eaca5cba188..a774efbbe354b 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout
+++ b/tests/ui/deriving/deriving-coerce-pointee-expanded.stdout
@@ -16,6 +16,10 @@ struct MyPointer<'a, #[pointee] T: ?Sized> {
     ptr: &'a T,
 }
 #[automatically_derived]
+impl<'a, T: ?Sized> ::core::marker::CoercePointeeValidated for
+    MyPointer<'a, T> {
+}
+#[automatically_derived]
 impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
     ::core::ops::DispatchFromDyn<MyPointer<'a, __S>> for MyPointer<'a, T> {
 }
@@ -31,6 +35,11 @@ pub struct MyPointer2<'a, Y, Z: MyTrait<T>, #[pointee] T: ?Sized + MyTrait<T>,
     x: core::marker::PhantomData<X>,
 }
 #[automatically_derived]
+impl<'a, Y, Z: MyTrait<T>, T: ?Sized + MyTrait<T>, X: MyTrait<T>>
+    ::core::marker::CoercePointeeValidated for MyPointer2<'a, Y, Z, T, X>
+    where Y: MyTrait<T> {
+}
+#[automatically_derived]
 impl<'a, Y, Z: MyTrait<T> + MyTrait<__S>, T: ?Sized + MyTrait<T> +
     ::core::marker::Unsize<__S>, __S: ?Sized + MyTrait<__S>, X: MyTrait<T> +
     MyTrait<__S>> ::core::ops::DispatchFromDyn<MyPointer2<'a, Y, Z, __S, X>>
@@ -48,6 +57,10 @@ struct MyPointerWithoutPointee<'a, T: ?Sized> {
     ptr: &'a T,
 }
 #[automatically_derived]
+impl<'a, T: ?Sized> ::core::marker::CoercePointeeValidated for
+    MyPointerWithoutPointee<'a, T> {
+}
+#[automatically_derived]
 impl<'a, T: ?Sized + ::core::marker::Unsize<__S>, __S: ?Sized>
     ::core::ops::DispatchFromDyn<MyPointerWithoutPointee<'a, __S>> for
     MyPointerWithoutPointee<'a, T> {
diff --git a/tests/ui/deriving/deriving-coerce-pointee-neg.rs b/tests/ui/deriving/deriving-coerce-pointee-neg.rs
index da25c854c546a..6577500d8eb0f 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-neg.rs
+++ b/tests/ui/deriving/deriving-coerce-pointee-neg.rs
@@ -1,6 +1,9 @@
+//@ proc-macro: malicious-macro.rs
 #![feature(derive_coerce_pointee, arbitrary_self_types)]
 
 extern crate core;
+extern crate malicious_macro;
+
 use std::marker::CoercePointee;
 
 #[derive(CoercePointee)]
@@ -41,8 +44,8 @@ struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &
 //~^ ERROR: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
 
 #[derive(CoercePointee)]
-//~^ ERROR: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
 struct NotTransparent<'a, #[pointee] T: ?Sized> {
+    //~^ ERROR: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
     ptr: &'a T,
 }
 
@@ -131,4 +134,12 @@ struct GlobalCoreSized<'a, #[pointee] T: ?::core::marker::Sized> {
     ptr: &'a T,
 }
 
+#[derive(CoercePointee)]
+#[malicious_macro::norepr]
+#[repr(transparent)]
+struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
+    //~^ ERROR: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout [E0802]
+    ptr: &'a T,
+}
+
 fn main() {}
diff --git a/tests/ui/deriving/deriving-coerce-pointee-neg.stderr b/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
index c1e8be49d37d3..999214bfa9fe3 100644
--- a/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
+++ b/tests/ui/deriving/deriving-coerce-pointee-neg.stderr
@@ -1,89 +1,81 @@
-error: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
-  --> $DIR/deriving-coerce-pointee-neg.rs:6:10
+error[E0802]: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
+  --> $DIR/deriving-coerce-pointee-neg.rs:9:10
    |
 LL | #[derive(CoercePointee)]
    |          ^^^^^^^^^^^^^
    |
    = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `CoercePointee` can only be derived on `struct`s with at least one field
-  --> $DIR/deriving-coerce-pointee-neg.rs:12:10
+error[E0802]: `CoercePointee` can only be derived on `struct`s with at least one field
+  --> $DIR/deriving-coerce-pointee-neg.rs:15:10
    |
 LL | #[derive(CoercePointee)]
    |          ^^^^^^^^^^^^^
    |
    = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `CoercePointee` can only be derived on `struct`s with at least one field
-  --> $DIR/deriving-coerce-pointee-neg.rs:19:10
+error[E0802]: `CoercePointee` can only be derived on `struct`s with at least one field
+  --> $DIR/deriving-coerce-pointee-neg.rs:22:10
    |
 LL | #[derive(CoercePointee)]
    |          ^^^^^^^^^^^^^
    |
    = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: `CoercePointee` can only be derived on `struct`s that are generic over at least one type
-  --> $DIR/deriving-coerce-pointee-neg.rs:26:10
+error[E0802]: `CoercePointee` can only be derived on `struct`s that are generic over at least one type
+  --> $DIR/deriving-coerce-pointee-neg.rs:29:10
    |
 LL | #[derive(CoercePointee)]
    |          ^^^^^^^^^^^^^
    |
    = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
-  --> $DIR/deriving-coerce-pointee-neg.rs:31:10
+error[E0802]: exactly one generic type parameter must be marked as `#[pointee]` to derive `CoercePointee` traits
+  --> $DIR/deriving-coerce-pointee-neg.rs:34:10
    |
 LL | #[derive(CoercePointee)]
    |          ^^^^^^^^^^^^^
    |
    = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
 
-error: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
-  --> $DIR/deriving-coerce-pointee-neg.rs:40:39
+error[E0802]: only one type parameter can be marked as `#[pointee]` when deriving `CoercePointee` traits
+  --> $DIR/deriving-coerce-pointee-neg.rs:43:39
    |
 LL | struct TooManyPointees<'a, #[pointee] A: ?Sized, #[pointee] B: ?Sized>((&'a A, &'a B));
    |                                       ^                     - here another type parameter is marked as `#[pointee]`
 
-error: `CoercePointee` can only be derived on `struct`s with `#[repr(transparent)]`
-  --> $DIR/deriving-coerce-pointee-neg.rs:43:10
-   |
-LL | #[derive(CoercePointee)]
-   |          ^^^^^^^^^^^^^
-   |
-   = note: this error originates in the derive macro `CoercePointee` (in Nightly builds, run with -Z macro-backtrace for more info)
-
-error: `derive(CoercePointee)` requires `T` to be marked `?Sized`
-  --> $DIR/deriving-coerce-pointee-neg.rs:51:36
+error[E0802]: `derive(CoercePointee)` requires `T` to be marked `?Sized`
+  --> $DIR/deriving-coerce-pointee-neg.rs:54:36
    |
 LL | struct NoMaybeSized<'a, #[pointee] T> {
    |                                    ^
 
 error: the `#[pointee]` attribute may only be used on generic parameters
-  --> $DIR/deriving-coerce-pointee-neg.rs:59:5
+  --> $DIR/deriving-coerce-pointee-neg.rs:62:5
    |
 LL |     #[pointee]
    |     ^^^^^^^^^^
 
 error: the `#[pointee]` attribute may only be used on generic parameters
-  --> $DIR/deriving-coerce-pointee-neg.rs:69:33
+  --> $DIR/deriving-coerce-pointee-neg.rs:72:33
    |
 LL |                     struct UhOh<#[pointee] T>(T);
    |                                 ^^^^^^^^^^
 
 error: the `#[pointee]` attribute may only be used on generic parameters
-  --> $DIR/deriving-coerce-pointee-neg.rs:83:21
+  --> $DIR/deriving-coerce-pointee-neg.rs:86:21
    |
 LL |         struct UhOh<#[pointee] T>(T);
    |                     ^^^^^^^^^^
 
 error: the `#[pointee]` attribute may only be used on generic parameters
-  --> $DIR/deriving-coerce-pointee-neg.rs:98:25
+  --> $DIR/deriving-coerce-pointee-neg.rs:101:25
    |
 LL |             struct UhOh<#[pointee] T>(T);
    |                         ^^^^^^^^^^
 
 error[E0392]: lifetime parameter `'a` is never used
-  --> $DIR/deriving-coerce-pointee-neg.rs:15:16
+  --> $DIR/deriving-coerce-pointee-neg.rs:18:16
    |
 LL | struct NoField<'a, #[pointee] T: ?Sized> {}
    |                ^^ unused lifetime parameter
@@ -91,7 +83,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {}
    = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
 
 error[E0392]: type parameter `T` is never used
-  --> $DIR/deriving-coerce-pointee-neg.rs:15:31
+  --> $DIR/deriving-coerce-pointee-neg.rs:18:31
    |
 LL | struct NoField<'a, #[pointee] T: ?Sized> {}
    |                               ^ unused type parameter
@@ -99,7 +91,7 @@ LL | struct NoField<'a, #[pointee] T: ?Sized> {}
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
 
 error[E0392]: lifetime parameter `'a` is never used
-  --> $DIR/deriving-coerce-pointee-neg.rs:22:20
+  --> $DIR/deriving-coerce-pointee-neg.rs:25:20
    |
 LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
    |                    ^^ unused lifetime parameter
@@ -107,13 +99,26 @@ LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
    = help: consider removing `'a`, referring to it in a field, or using a marker such as `PhantomData`
 
 error[E0392]: type parameter `T` is never used
-  --> $DIR/deriving-coerce-pointee-neg.rs:22:35
+  --> $DIR/deriving-coerce-pointee-neg.rs:25:35
    |
 LL | struct NoFieldUnit<'a, #[pointee] T: ?Sized>();
    |                                   ^ unused type parameter
    |
    = help: consider removing `T`, referring to it in a field, or using a marker such as `PhantomData`
 
-error: aborting due to 16 previous errors
+error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
+  --> $DIR/deriving-coerce-pointee-neg.rs:47:1
+   |
+LL | struct NotTransparent<'a, #[pointee] T: ?Sized> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error[E0802]: `derive(CoercePointee)` is only applicable to `struct` with `repr(transparent)` layout
+  --> $DIR/deriving-coerce-pointee-neg.rs:140:1
+   |
+LL | struct TryToWipeRepr<'a, #[pointee] T: ?Sized> {
+   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+
+error: aborting due to 17 previous errors
 
-For more information about this error, try `rustc --explain E0392`.
+Some errors have detailed explanations: E0392, E0802.
+For more information about an error, try `rustc --explain E0392`.
diff --git a/tests/ui/extern/fictional-abi.rs b/tests/ui/extern/fictional-abi.rs
new file mode 100644
index 0000000000000..60b24f8856efc
--- /dev/null
+++ b/tests/ui/extern/fictional-abi.rs
@@ -0,0 +1,3 @@
+#![crate_type = "lib"]
+
+pub extern "fictional" fn lol() {} //~ ERROR: invalid ABI
diff --git a/tests/ui/abi/removed-wasm-abi.stderr b/tests/ui/extern/fictional-abi.stderr
similarity index 53%
rename from tests/ui/abi/removed-wasm-abi.stderr
rename to tests/ui/extern/fictional-abi.stderr
index 6007c4e258014..9784a57776fc0 100644
--- a/tests/ui/abi/removed-wasm-abi.stderr
+++ b/tests/ui/extern/fictional-abi.stderr
@@ -1,11 +1,10 @@
-error[E0703]: invalid ABI: found `wasm`
-  --> $DIR/removed-wasm-abi.rs:1:8
+error[E0703]: invalid ABI: found `fictional`
+  --> $DIR/fictional-abi.rs:3:12
    |
-LL | extern "wasm" fn test() {}
-   |        ^^^^^^ invalid ABI
+LL | pub extern "fictional" fn lol() {}
+   |            ^^^^^^^^^^^ invalid ABI
    |
    = note: invoke `rustc --print=calling-conventions` for a full list of supported calling conventions
-   = note: non-standard wasm ABI is no longer supported
 
 error: aborting due to 1 previous error
 
diff --git a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
index f37c5335deb04..5386628a8e069 100644
--- a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
+++ b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.rs
@@ -9,43 +9,43 @@ trait Sized { }
 // feature gate is not used.
 
 extern "avr-non-blocking-interrupt" fn fu() {}
-//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+//~^ ERROR extern "avr-non-blocking-interrupt" ABI is experimental
 extern "avr-interrupt" fn f() {}
-//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+//~^ ERROR extern "avr-interrupt" ABI is experimental
 
 trait T {
     extern "avr-interrupt" fn m();
-    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    //~^ ERROR extern "avr-interrupt" ABI is experimental
     extern "avr-non-blocking-interrupt" fn mu();
-    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    //~^ ERROR extern "avr-non-blocking-interrupt" ABI is experimental
 
     extern "avr-interrupt" fn dm() {}
-    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    //~^ ERROR extern "avr-interrupt" ABI is experimental
     extern "avr-non-blocking-interrupt" fn dmu() {}
-    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    //~^ ERROR extern "avr-non-blocking-interrupt" ABI is experimental
 }
 
 struct S;
 impl T for S {
     extern "avr-interrupt" fn m() {}
-    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    //~^ ERROR extern "avr-interrupt" ABI is experimental
     extern "avr-non-blocking-interrupt" fn mu() {}
-    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    //~^ ERROR extern "avr-non-blocking-interrupt" ABI is experimental
 }
 
 impl S {
     extern "avr-interrupt" fn im() {}
-    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    //~^ ERROR extern "avr-interrupt" ABI is experimental
     extern "avr-non-blocking-interrupt" fn imu() {}
-    //~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+    //~^ ERROR extern "avr-non-blocking-interrupt" ABI is experimental
 }
 
 type TA = extern "avr-interrupt" fn();
-//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+//~^ ERROR extern "avr-interrupt" ABI is experimental
 type TAU = extern "avr-non-blocking-interrupt" fn();
-//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+//~^ ERROR extern "avr-non-blocking-interrupt" ABI is experimental
 
 extern "avr-interrupt" {}
-//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+//~^ ERROR extern "avr-interrupt" ABI is experimental
 extern "avr-non-blocking-interrupt" {}
-//~^ ERROR avr-interrupt and avr-non-blocking-interrupt ABIs are experimental
+//~^ ERROR extern "avr-non-blocking-interrupt" ABI is experimental
diff --git a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
index c6786699de1b8..d9f3c3adc7f04 100644
--- a/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi-avr-interrupt.stderr
@@ -1,4 +1,4 @@
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-non-blocking-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:11:8
    |
 LL | extern "avr-non-blocking-interrupt" fn fu() {}
@@ -8,7 +8,7 @@ LL | extern "avr-non-blocking-interrupt" fn fu() {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:13:8
    |
 LL | extern "avr-interrupt" fn f() {}
@@ -18,7 +18,7 @@ LL | extern "avr-interrupt" fn f() {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:17:12
    |
 LL |     extern "avr-interrupt" fn m();
@@ -28,7 +28,7 @@ LL |     extern "avr-interrupt" fn m();
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-non-blocking-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:19:12
    |
 LL |     extern "avr-non-blocking-interrupt" fn mu();
@@ -38,7 +38,7 @@ LL |     extern "avr-non-blocking-interrupt" fn mu();
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:22:12
    |
 LL |     extern "avr-interrupt" fn dm() {}
@@ -48,7 +48,7 @@ LL |     extern "avr-interrupt" fn dm() {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-non-blocking-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:24:12
    |
 LL |     extern "avr-non-blocking-interrupt" fn dmu() {}
@@ -58,7 +58,7 @@ LL |     extern "avr-non-blocking-interrupt" fn dmu() {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:30:12
    |
 LL |     extern "avr-interrupt" fn m() {}
@@ -68,7 +68,7 @@ LL |     extern "avr-interrupt" fn m() {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-non-blocking-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:32:12
    |
 LL |     extern "avr-non-blocking-interrupt" fn mu() {}
@@ -78,7 +78,7 @@ LL |     extern "avr-non-blocking-interrupt" fn mu() {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:37:12
    |
 LL |     extern "avr-interrupt" fn im() {}
@@ -88,7 +88,7 @@ LL |     extern "avr-interrupt" fn im() {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-non-blocking-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:39:12
    |
 LL |     extern "avr-non-blocking-interrupt" fn imu() {}
@@ -98,7 +98,7 @@ LL |     extern "avr-non-blocking-interrupt" fn imu() {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:43:18
    |
 LL | type TA = extern "avr-interrupt" fn();
@@ -108,7 +108,7 @@ LL | type TA = extern "avr-interrupt" fn();
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-non-blocking-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:45:19
    |
 LL | type TAU = extern "avr-non-blocking-interrupt" fn();
@@ -118,7 +118,7 @@ LL | type TAU = extern "avr-non-blocking-interrupt" fn();
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:48:8
    |
 LL | extern "avr-interrupt" {}
@@ -128,7 +128,7 @@ LL | extern "avr-interrupt" {}
    = help: add `#![feature(abi_avr_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: avr-interrupt and avr-non-blocking-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "avr-non-blocking-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-avr-interrupt.rs:50:8
    |
 LL | extern "avr-non-blocking-interrupt" {}
diff --git a/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs
index b0fb4c414d40f..bb69a638ceeab 100644
--- a/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs
+++ b/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.rs
@@ -6,29 +6,29 @@
 trait Sized { }
 
 extern "msp430-interrupt" fn f() {}
-//~^ ERROR msp430-interrupt ABI is experimental
+//~^ ERROR "msp430-interrupt" ABI is experimental
 
 trait T {
     extern "msp430-interrupt" fn m();
-    //~^ ERROR msp430-interrupt ABI is experimental
+    //~^ ERROR "msp430-interrupt" ABI is experimental
 
     extern "msp430-interrupt" fn dm() {}
-    //~^ ERROR msp430-interrupt ABI is experimental
+    //~^ ERROR "msp430-interrupt" ABI is experimental
 }
 
 struct S;
 impl T for S {
     extern "msp430-interrupt" fn m() {}
-    //~^ ERROR msp430-interrupt ABI is experimental
+    //~^ ERROR "msp430-interrupt" ABI is experimental
 }
 
 impl S {
     extern "msp430-interrupt" fn im() {}
-    //~^ ERROR msp430-interrupt ABI is experimental
+    //~^ ERROR "msp430-interrupt" ABI is experimental
 }
 
 type TA = extern "msp430-interrupt" fn();
-//~^ ERROR msp430-interrupt ABI is experimental
+//~^ ERROR "msp430-interrupt" ABI is experimental
 
 extern "msp430-interrupt" {}
-//~^ ERROR msp430-interrupt ABI is experimental
+//~^ ERROR "msp430-interrupt" ABI is experimental
diff --git a/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
index 5dacc86dcc59c..21ddbf7a86df8 100644
--- a/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi-msp430-interrupt.stderr
@@ -1,4 +1,4 @@
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "msp430-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:8:8
    |
 LL | extern "msp430-interrupt" fn f() {}
@@ -8,7 +8,7 @@ LL | extern "msp430-interrupt" fn f() {}
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "msp430-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:12:12
    |
 LL |     extern "msp430-interrupt" fn m();
@@ -18,7 +18,7 @@ LL |     extern "msp430-interrupt" fn m();
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "msp430-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:15:12
    |
 LL |     extern "msp430-interrupt" fn dm() {}
@@ -28,7 +28,7 @@ LL |     extern "msp430-interrupt" fn dm() {}
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "msp430-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:21:12
    |
 LL |     extern "msp430-interrupt" fn m() {}
@@ -38,7 +38,7 @@ LL |     extern "msp430-interrupt" fn m() {}
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "msp430-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:26:12
    |
 LL |     extern "msp430-interrupt" fn im() {}
@@ -48,7 +48,7 @@ LL |     extern "msp430-interrupt" fn im() {}
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "msp430-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:30:18
    |
 LL | type TA = extern "msp430-interrupt" fn();
@@ -58,7 +58,7 @@ LL | type TA = extern "msp430-interrupt" fn();
    = help: add `#![feature(abi_msp430_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: msp430-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "msp430-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-msp430-interrupt.rs:33:8
    |
 LL | extern "msp430-interrupt" {}
diff --git a/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.rs
index 29820f8877d33..6f4989fbd9fe9 100644
--- a/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.rs
+++ b/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.rs
@@ -9,25 +9,25 @@ trait Sized {}
 // feature gate is not used.
 
 extern "riscv-interrupt-m" fn f() {}
-//~^ ERROR riscv-interrupt ABIs are experimental
+//~^ ERROR "riscv-interrupt-m" ABI is experimental
 extern "riscv-interrupt-s" fn f_s() {}
-//~^ ERROR riscv-interrupt ABIs are experimental
+//~^ ERROR "riscv-interrupt-s" ABI is experimental
 
 trait T {
     extern "riscv-interrupt-m" fn m();
-    //~^ ERROR riscv-interrupt ABIs are experimental
+    //~^ ERROR "riscv-interrupt-m" ABI is experimental
 }
 
 struct S;
 impl T for S {
     extern "riscv-interrupt-m" fn m() {}
-    //~^ ERROR riscv-interrupt ABIs are experimental
+    //~^ ERROR "riscv-interrupt-m" ABI is experimental
 }
 
 impl S {
     extern "riscv-interrupt-m" fn im() {}
-    //~^ ERROR riscv-interrupt ABIs are experimental
+    //~^ ERROR "riscv-interrupt-m" ABI is experimental
 }
 
 type TA = extern "riscv-interrupt-m" fn();
-//~^ ERROR riscv-interrupt ABIs are experimental
+//~^ ERROR "riscv-interrupt-m" ABI is experimental
diff --git a/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.stderr
index 6b7853a320b0d..3c9e99aa1b9b3 100644
--- a/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi-riscv-interrupt.stderr
@@ -1,4 +1,4 @@
-error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "riscv-interrupt-m" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-riscv-interrupt.rs:11:8
    |
 LL | extern "riscv-interrupt-m" fn f() {}
@@ -8,7 +8,7 @@ LL | extern "riscv-interrupt-m" fn f() {}
    = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "riscv-interrupt-s" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-riscv-interrupt.rs:13:8
    |
 LL | extern "riscv-interrupt-s" fn f_s() {}
@@ -18,7 +18,7 @@ LL | extern "riscv-interrupt-s" fn f_s() {}
    = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "riscv-interrupt-m" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-riscv-interrupt.rs:17:12
    |
 LL |     extern "riscv-interrupt-m" fn m();
@@ -28,7 +28,7 @@ LL |     extern "riscv-interrupt-m" fn m();
    = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "riscv-interrupt-m" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-riscv-interrupt.rs:23:12
    |
 LL |     extern "riscv-interrupt-m" fn m() {}
@@ -38,7 +38,7 @@ LL |     extern "riscv-interrupt-m" fn m() {}
    = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "riscv-interrupt-m" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-riscv-interrupt.rs:28:12
    |
 LL |     extern "riscv-interrupt-m" fn im() {}
@@ -48,7 +48,7 @@ LL |     extern "riscv-interrupt-m" fn im() {}
    = help: add `#![feature(abi_riscv_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: riscv-interrupt ABIs are experimental and subject to change
+error[E0658]: the extern "riscv-interrupt-m" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-riscv-interrupt.rs:32:18
    |
 LL | type TA = extern "riscv-interrupt-m" fn();
diff --git a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs
index 812ca12c7c37d..93c59364f10ba 100644
--- a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs
+++ b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.rs
@@ -5,24 +5,24 @@
 #[lang="sized"]
 trait Sized { }
 
-extern "x86-interrupt" fn f7() {} //~ ERROR x86-interrupt ABI is experimental
+extern "x86-interrupt" fn f7() {} //~ ERROR "x86-interrupt" ABI is experimental
 trait Tr {
-    extern "x86-interrupt" fn m7(); //~ ERROR x86-interrupt ABI is experimental
-    extern "x86-interrupt" fn dm7() {} //~ ERROR x86-interrupt ABI is experimental
+    extern "x86-interrupt" fn m7(); //~ ERROR "x86-interrupt" ABI is experimental
+    extern "x86-interrupt" fn dm7() {} //~ ERROR "x86-interrupt" ABI is experimental
 }
 
 struct S;
 
 // Methods in trait impl
 impl Tr for S {
-    extern "x86-interrupt" fn m7() {} //~ ERROR x86-interrupt ABI is experimental
+    extern "x86-interrupt" fn m7() {} //~ ERROR "x86-interrupt" ABI is experimental
 }
 
 // Methods in inherent impl
 impl S {
-    extern "x86-interrupt" fn im7() {} //~ ERROR x86-interrupt ABI is experimental
+    extern "x86-interrupt" fn im7() {} //~ ERROR "x86-interrupt" ABI is experimental
 }
 
-type A7 = extern "x86-interrupt" fn(); //~ ERROR x86-interrupt ABI is experimental
+type A7 = extern "x86-interrupt" fn(); //~ ERROR "x86-interrupt" ABI is experimental
 
-extern "x86-interrupt" {} //~ ERROR x86-interrupt ABI is experimental
+extern "x86-interrupt" {} //~ ERROR "x86-interrupt" ABI is experimental
diff --git a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr
index 860005cac3416..231cf207c862d 100644
--- a/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi-x86-interrupt.stderr
@@ -1,4 +1,4 @@
-error[E0658]: x86-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:8:8
    |
 LL | extern "x86-interrupt" fn f7() {}
@@ -8,7 +8,7 @@ LL | extern "x86-interrupt" fn f7() {}
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:10:12
    |
 LL |     extern "x86-interrupt" fn m7();
@@ -18,7 +18,7 @@ LL |     extern "x86-interrupt" fn m7();
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:11:12
    |
 LL |     extern "x86-interrupt" fn dm7() {}
@@ -28,7 +28,7 @@ LL |     extern "x86-interrupt" fn dm7() {}
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:18:12
    |
 LL |     extern "x86-interrupt" fn m7() {}
@@ -38,7 +38,7 @@ LL |     extern "x86-interrupt" fn m7() {}
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:23:12
    |
 LL |     extern "x86-interrupt" fn im7() {}
@@ -48,7 +48,7 @@ LL |     extern "x86-interrupt" fn im7() {}
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:26:18
    |
 LL | type A7 = extern "x86-interrupt" fn();
@@ -58,7 +58,7 @@ LL | type A7 = extern "x86-interrupt" fn();
    = help: add `#![feature(abi_x86_interrupt)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: x86-interrupt ABI is experimental and subject to change
+error[E0658]: the extern "x86-interrupt" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi-x86-interrupt.rs:28:8
    |
 LL | extern "x86-interrupt" {}
diff --git a/tests/ui/feature-gates/feature-gate-abi.rs b/tests/ui/feature-gates/feature-gate-abi.rs
index 3aa430e736f09..7ab05889c20a7 100644
--- a/tests/ui/feature-gates/feature-gate-abi.rs
+++ b/tests/ui/feature-gates/feature-gate-abi.rs
@@ -11,49 +11,49 @@ trait Sized { }
 trait Tuple { }
 
 // Functions
-extern "rust-intrinsic" fn f1() {} //~ ERROR intrinsics are subject to change
+extern "rust-intrinsic" fn f1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
                                    //~^ ERROR intrinsic must be in
-extern "rust-intrinsic" fn f2() {} //~ ERROR intrinsics are subject to change
+extern "rust-intrinsic" fn f2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
                                        //~^ ERROR intrinsic must be in
-extern "rust-call" fn f4(_: ()) {} //~ ERROR rust-call ABI is subject to change
+extern "rust-call" fn f4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change
 
 // Methods in trait definition
 trait Tr {
-    extern "rust-intrinsic" fn m1(); //~ ERROR intrinsics are subject to change
+    extern "rust-intrinsic" fn m1(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
                                      //~^ ERROR intrinsic must be in
-    extern "rust-intrinsic" fn m2(); //~ ERROR intrinsics are subject to change
+    extern "rust-intrinsic" fn m2(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
                                          //~^ ERROR intrinsic must be in
-    extern "rust-call" fn m4(_: ()); //~ ERROR rust-call ABI is subject to change
+    extern "rust-call" fn m4(_: ()); //~ ERROR extern "rust-call" ABI is experimental and subject to change
 
-    extern "rust-call" fn dm4(_: ()) {} //~ ERROR rust-call ABI is subject to change
+    extern "rust-call" fn dm4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change
 }
 
 struct S;
 
 // Methods in trait impl
 impl Tr for S {
-    extern "rust-intrinsic" fn m1() {} //~ ERROR intrinsics are subject to change
+    extern "rust-intrinsic" fn m1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
                                        //~^ ERROR intrinsic must be in
-    extern "rust-intrinsic" fn m2() {} //~ ERROR intrinsics are subject to change
+    extern "rust-intrinsic" fn m2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
                                            //~^ ERROR intrinsic must be in
-    extern "rust-call" fn m4(_: ()) {} //~ ERROR rust-call ABI is subject to change
+    extern "rust-call" fn m4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change
 }
 
 // Methods in inherent impl
 impl S {
-    extern "rust-intrinsic" fn im1() {} //~ ERROR intrinsics are subject to change
+    extern "rust-intrinsic" fn im1() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
                                         //~^ ERROR intrinsic must be in
-    extern "rust-intrinsic" fn im2() {} //~ ERROR intrinsics are subject to change
+    extern "rust-intrinsic" fn im2() {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
                                             //~^ ERROR intrinsic must be in
-    extern "rust-call" fn im4(_: ()) {} //~ ERROR rust-call ABI is subject to change
+    extern "rust-call" fn im4(_: ()) {} //~ ERROR extern "rust-call" ABI is experimental and subject to change
 }
 
 // Function pointer types
-type A1 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
-type A2 = extern "rust-intrinsic" fn(); //~ ERROR intrinsics are subject to change
-type A4 = extern "rust-call" fn(_: ()); //~ ERROR rust-call ABI is subject to change
+type A1 = extern "rust-intrinsic" fn(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
+type A2 = extern "rust-intrinsic" fn(); //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
+type A4 = extern "rust-call" fn(_: ()); //~ ERROR extern "rust-call" ABI is experimental and subject to change
 
 // Foreign modules
-extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
-extern "rust-intrinsic" {} //~ ERROR intrinsics are subject to change
-extern "rust-call" {} //~ ERROR rust-call ABI is subject to change
+extern "rust-intrinsic" {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
+extern "rust-intrinsic" {} //~ ERROR extern "rust-intrinsic" ABI is an implementation detail
+extern "rust-call" {} //~ ERROR extern "rust-call" ABI is experimental and subject to change
diff --git a/tests/ui/feature-gates/feature-gate-abi.stderr b/tests/ui/feature-gates/feature-gate-abi.stderr
index dbdfa7b275d49..70ec64e5135e5 100644
--- a/tests/ui/feature-gates/feature-gate-abi.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi.stderr
@@ -1,4 +1,4 @@
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:14:8
    |
 LL | extern "rust-intrinsic" fn f1() {}
@@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" fn f1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:16:8
    |
 LL | extern "rust-intrinsic" fn f2() {}
@@ -16,7 +16,7 @@ LL | extern "rust-intrinsic" fn f2() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:18:8
    |
 LL | extern "rust-call" fn f4(_: ()) {}
@@ -26,7 +26,7 @@ LL | extern "rust-call" fn f4(_: ()) {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:22:12
    |
 LL |     extern "rust-intrinsic" fn m1();
@@ -35,7 +35,7 @@ LL |     extern "rust-intrinsic" fn m1();
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:24:12
    |
 LL |     extern "rust-intrinsic" fn m2();
@@ -44,7 +44,7 @@ LL |     extern "rust-intrinsic" fn m2();
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:26:12
    |
 LL |     extern "rust-call" fn m4(_: ());
@@ -54,7 +54,7 @@ LL |     extern "rust-call" fn m4(_: ());
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:28:12
    |
 LL |     extern "rust-call" fn dm4(_: ()) {}
@@ -64,7 +64,7 @@ LL |     extern "rust-call" fn dm4(_: ()) {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:35:12
    |
 LL |     extern "rust-intrinsic" fn m1() {}
@@ -73,7 +73,7 @@ LL |     extern "rust-intrinsic" fn m1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:37:12
    |
 LL |     extern "rust-intrinsic" fn m2() {}
@@ -82,7 +82,7 @@ LL |     extern "rust-intrinsic" fn m2() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:39:12
    |
 LL |     extern "rust-call" fn m4(_: ()) {}
@@ -92,7 +92,7 @@ LL |     extern "rust-call" fn m4(_: ()) {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:44:12
    |
 LL |     extern "rust-intrinsic" fn im1() {}
@@ -101,7 +101,7 @@ LL |     extern "rust-intrinsic" fn im1() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:46:12
    |
 LL |     extern "rust-intrinsic" fn im2() {}
@@ -110,7 +110,7 @@ LL |     extern "rust-intrinsic" fn im2() {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:48:12
    |
 LL |     extern "rust-call" fn im4(_: ()) {}
@@ -120,7 +120,7 @@ LL |     extern "rust-call" fn im4(_: ()) {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:52:18
    |
 LL | type A1 = extern "rust-intrinsic" fn();
@@ -129,7 +129,7 @@ LL | type A1 = extern "rust-intrinsic" fn();
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:53:18
    |
 LL | type A2 = extern "rust-intrinsic" fn();
@@ -138,7 +138,7 @@ LL | type A2 = extern "rust-intrinsic" fn();
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:54:18
    |
 LL | type A4 = extern "rust-call" fn(_: ());
@@ -148,7 +148,7 @@ LL | type A4 = extern "rust-call" fn(_: ());
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:57:8
    |
 LL | extern "rust-intrinsic" {}
@@ -157,7 +157,7 @@ LL | extern "rust-intrinsic" {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi.rs:58:8
    |
 LL | extern "rust-intrinsic" {}
@@ -166,7 +166,7 @@ LL | extern "rust-intrinsic" {}
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi.rs:59:8
    |
 LL | extern "rust-call" {}
diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs
index 7d39820f086e9..fb04906dafe96 100644
--- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs
+++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.rs
@@ -10,14 +10,14 @@ trait Sized { }
 trait Tuple { }
 
 // Functions
-extern "gpu-kernel" fn f1(_: ()) {} //~ ERROR gpu-kernel ABI is experimental and subject to change
+extern "gpu-kernel" fn f1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change
 //~^ ERROR is not a supported ABI
 
 // Methods in trait definition
 trait Tr {
-    extern "gpu-kernel" fn m1(_: ()); //~ ERROR gpu-kernel ABI is experimental and subject to change
+    extern "gpu-kernel" fn m1(_: ()); //~ ERROR "gpu-kernel" ABI is experimental and subject to change
 
-    extern "gpu-kernel" fn dm1(_: ()) {} //~ ERROR gpu-kernel ABI is experimental and subject to change
+    extern "gpu-kernel" fn dm1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change
     //~^ ERROR is not a supported ABI
 }
 
@@ -25,21 +25,21 @@ struct S;
 
 // Methods in trait impl
 impl Tr for S {
-    extern "gpu-kernel" fn m1(_: ()) {} //~ ERROR gpu-kernel ABI is experimental and subject to change
+    extern "gpu-kernel" fn m1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change
     //~^ ERROR is not a supported ABI
 }
 
 // Methods in inherent impl
 impl S {
-    extern "gpu-kernel" fn im1(_: ()) {} //~ ERROR gpu-kernel ABI is experimental and subject to change
+    extern "gpu-kernel" fn im1(_: ()) {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change
     //~^ ERROR is not a supported ABI
 }
 
 // Function pointer types
-type A1 = extern "gpu-kernel" fn(_: ()); //~ ERROR gpu-kernel ABI is experimental and subject to change
+type A1 = extern "gpu-kernel" fn(_: ()); //~ ERROR "gpu-kernel" ABI is experimental and subject to change
 //~^ WARN the calling convention "gpu-kernel" is not supported on this target
 //~^^ WARN this was previously accepted by the compiler but is being phased out
 
 // Foreign modules
-extern "gpu-kernel" {} //~ ERROR gpu-kernel ABI is experimental and subject to change
+extern "gpu-kernel" {} //~ ERROR "gpu-kernel" ABI is experimental and subject to change
 //~^ ERROR is not a supported ABI
diff --git a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr
index 771c49acb97a5..b05c16e3d9ee2 100644
--- a/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi_gpu_kernel.stderr
@@ -1,4 +1,4 @@
-error[E0658]: gpu-kernel ABI is experimental and subject to change
+error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_gpu_kernel.rs:13:8
    |
 LL | extern "gpu-kernel" fn f1(_: ()) {}
@@ -8,7 +8,7 @@ LL | extern "gpu-kernel" fn f1(_: ()) {}
    = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: gpu-kernel ABI is experimental and subject to change
+error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_gpu_kernel.rs:18:12
    |
 LL |     extern "gpu-kernel" fn m1(_: ());
@@ -18,7 +18,7 @@ LL |     extern "gpu-kernel" fn m1(_: ());
    = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: gpu-kernel ABI is experimental and subject to change
+error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_gpu_kernel.rs:20:12
    |
 LL |     extern "gpu-kernel" fn dm1(_: ()) {}
@@ -28,7 +28,7 @@ LL |     extern "gpu-kernel" fn dm1(_: ()) {}
    = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: gpu-kernel ABI is experimental and subject to change
+error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_gpu_kernel.rs:28:12
    |
 LL |     extern "gpu-kernel" fn m1(_: ()) {}
@@ -38,7 +38,7 @@ LL |     extern "gpu-kernel" fn m1(_: ()) {}
    = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: gpu-kernel ABI is experimental and subject to change
+error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_gpu_kernel.rs:34:12
    |
 LL |     extern "gpu-kernel" fn im1(_: ()) {}
@@ -48,7 +48,7 @@ LL |     extern "gpu-kernel" fn im1(_: ()) {}
    = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: gpu-kernel ABI is experimental and subject to change
+error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_gpu_kernel.rs:39:18
    |
 LL | type A1 = extern "gpu-kernel" fn(_: ());
@@ -58,7 +58,7 @@ LL | type A1 = extern "gpu-kernel" fn(_: ());
    = help: add `#![feature(abi_gpu_kernel)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: gpu-kernel ABI is experimental and subject to change
+error[E0658]: the extern "gpu-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_gpu_kernel.rs:44:8
    |
 LL | extern "gpu-kernel" {}
diff --git a/tests/ui/feature-gates/feature-gate-abi_ptx.rs b/tests/ui/feature-gates/feature-gate-abi_ptx.rs
index 83f48430281a3..e742492303ade 100644
--- a/tests/ui/feature-gates/feature-gate-abi_ptx.rs
+++ b/tests/ui/feature-gates/feature-gate-abi_ptx.rs
@@ -5,22 +5,22 @@
 #[lang="sized"]
 trait Sized { }
 
-extern "ptx-kernel" fn fu() {} //~ ERROR PTX ABIs are experimental
+extern "ptx-kernel" fn fu() {} //~ ERROR extern "ptx-kernel" ABI is experimental
 
 trait T {
-    extern "ptx-kernel" fn mu(); //~ ERROR PTX ABIs are experimental
-    extern "ptx-kernel" fn dmu() {} //~ ERROR PTX ABIs are experimental
+    extern "ptx-kernel" fn mu(); //~ ERROR extern "ptx-kernel" ABI is experimental
+    extern "ptx-kernel" fn dmu() {} //~ ERROR extern "ptx-kernel" ABI is experimental
 }
 
 struct S;
 impl T for S {
-    extern "ptx-kernel" fn mu() {} //~ ERROR PTX ABIs are experimental
+    extern "ptx-kernel" fn mu() {} //~ ERROR extern "ptx-kernel" ABI is experimental
 }
 
 impl S {
-    extern "ptx-kernel" fn imu() {} //~ ERROR PTX ABIs are experimental
+    extern "ptx-kernel" fn imu() {} //~ ERROR extern "ptx-kernel" ABI is experimental
 }
 
-type TAU = extern "ptx-kernel" fn(); //~ ERROR PTX ABIs are experimental
+type TAU = extern "ptx-kernel" fn(); //~ ERROR extern "ptx-kernel" ABI is experimental
 
-extern "ptx-kernel" {} //~ ERROR PTX ABIs are experimental
+extern "ptx-kernel" {} //~ ERROR extern "ptx-kernel" ABI is experimental
diff --git a/tests/ui/feature-gates/feature-gate-abi_ptx.stderr b/tests/ui/feature-gates/feature-gate-abi_ptx.stderr
index 22b493e577dd5..d128075919b09 100644
--- a/tests/ui/feature-gates/feature-gate-abi_ptx.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi_ptx.stderr
@@ -1,4 +1,4 @@
-error[E0658]: PTX ABIs are experimental and subject to change
+error[E0658]: the extern "ptx-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_ptx.rs:8:8
    |
 LL | extern "ptx-kernel" fn fu() {}
@@ -8,7 +8,7 @@ LL | extern "ptx-kernel" fn fu() {}
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: PTX ABIs are experimental and subject to change
+error[E0658]: the extern "ptx-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_ptx.rs:11:12
    |
 LL |     extern "ptx-kernel" fn mu();
@@ -18,7 +18,7 @@ LL |     extern "ptx-kernel" fn mu();
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: PTX ABIs are experimental and subject to change
+error[E0658]: the extern "ptx-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_ptx.rs:12:12
    |
 LL |     extern "ptx-kernel" fn dmu() {}
@@ -28,7 +28,7 @@ LL |     extern "ptx-kernel" fn dmu() {}
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: PTX ABIs are experimental and subject to change
+error[E0658]: the extern "ptx-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_ptx.rs:17:12
    |
 LL |     extern "ptx-kernel" fn mu() {}
@@ -38,7 +38,7 @@ LL |     extern "ptx-kernel" fn mu() {}
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: PTX ABIs are experimental and subject to change
+error[E0658]: the extern "ptx-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_ptx.rs:21:12
    |
 LL |     extern "ptx-kernel" fn imu() {}
@@ -48,7 +48,7 @@ LL |     extern "ptx-kernel" fn imu() {}
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: PTX ABIs are experimental and subject to change
+error[E0658]: the extern "ptx-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_ptx.rs:24:19
    |
 LL | type TAU = extern "ptx-kernel" fn();
@@ -58,7 +58,7 @@ LL | type TAU = extern "ptx-kernel" fn();
    = help: add `#![feature(abi_ptx)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: PTX ABIs are experimental and subject to change
+error[E0658]: the extern "ptx-kernel" ABI is experimental and subject to change
   --> $DIR/feature-gate-abi_ptx.rs:26:8
    |
 LL | extern "ptx-kernel" {}
diff --git a/tests/ui/feature-gates/feature-gate-abi_unadjusted.rs b/tests/ui/feature-gates/feature-gate-abi_unadjusted.rs
index 35a7d73288b5d..1dc6adc0e1495 100644
--- a/tests/ui/feature-gates/feature-gate-abi_unadjusted.rs
+++ b/tests/ui/feature-gates/feature-gate-abi_unadjusted.rs
@@ -1,5 +1,5 @@
 extern "unadjusted" fn foo() {
-//~^ ERROR: unadjusted ABI is an implementation detail and perma-unstable
+//~^ ERROR: "unadjusted" ABI is an implementation detail and perma-unstable
 }
 
 fn main() {
diff --git a/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr b/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr
index 1d5fb11cd3d2b..462fb79d55703 100644
--- a/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr
+++ b/tests/ui/feature-gates/feature-gate-abi_unadjusted.stderr
@@ -1,4 +1,4 @@
-error[E0658]: unadjusted ABI is an implementation detail and perma-unstable
+error[E0658]: the extern "unadjusted" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-abi_unadjusted.rs:1:8
    |
 LL | extern "unadjusted" fn foo() {
diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.rs b/tests/ui/feature-gates/feature-gate-intrinsics.rs
index e0dc3cc579d79..65806a0223e74 100644
--- a/tests/ui/feature-gates/feature-gate-intrinsics.rs
+++ b/tests/ui/feature-gates/feature-gate-intrinsics.rs
@@ -1,8 +1,8 @@
-extern "rust-intrinsic" {   //~ ERROR intrinsics are subject to change
+extern "rust-intrinsic" {   //~ ERROR "rust-intrinsic" ABI is an implementation detail
     fn bar(); //~ ERROR unrecognized intrinsic function: `bar`
 }
 
-extern "rust-intrinsic" fn baz() {} //~ ERROR intrinsics are subject to change
+extern "rust-intrinsic" fn baz() {} //~ ERROR "rust-intrinsic" ABI is an implementation detail
 //~^ ERROR intrinsic must be in
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-intrinsics.stderr b/tests/ui/feature-gates/feature-gate-intrinsics.stderr
index 577a620e2d2c5..97246f05258f0 100644
--- a/tests/ui/feature-gates/feature-gate-intrinsics.stderr
+++ b/tests/ui/feature-gates/feature-gate-intrinsics.stderr
@@ -1,4 +1,4 @@
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-intrinsics.rs:1:8
    |
 LL | extern "rust-intrinsic" {
@@ -7,7 +7,7 @@ LL | extern "rust-intrinsic" {
    = help: add `#![feature(intrinsics)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gate-intrinsics.rs:5:8
    |
 LL | extern "rust-intrinsic" fn baz() {}
diff --git a/tests/ui/feature-gates/feature-gate-rust_cold_cc.rs b/tests/ui/feature-gates/feature-gate-rust_cold_cc.rs
index 9ba8e32ac07a3..4f47eb55b395f 100644
--- a/tests/ui/feature-gates/feature-gate-rust_cold_cc.rs
+++ b/tests/ui/feature-gates/feature-gate-rust_cold_cc.rs
@@ -1,21 +1,21 @@
 #![crate_type = "lib"]
 
-extern "rust-cold" fn fu() {} //~ ERROR rust-cold is experimental
+extern "rust-cold" fn fu() {} //~ ERROR "rust-cold" ABI is experimental
 
 trait T {
-    extern "rust-cold" fn mu(); //~ ERROR rust-cold is experimental
-    extern "rust-cold" fn dmu() {} //~ ERROR rust-cold is experimental
+    extern "rust-cold" fn mu(); //~ ERROR "rust-cold" ABI is experimental
+    extern "rust-cold" fn dmu() {} //~ ERROR "rust-cold" ABI is experimental
 }
 
 struct S;
 impl T for S {
-    extern "rust-cold" fn mu() {} //~ ERROR rust-cold is experimental
+    extern "rust-cold" fn mu() {} //~ ERROR "rust-cold" ABI is experimental
 }
 
 impl S {
-    extern "rust-cold" fn imu() {} //~ ERROR rust-cold is experimental
+    extern "rust-cold" fn imu() {} //~ ERROR "rust-cold" ABI is experimental
 }
 
-type TAU = extern "rust-cold" fn(); //~ ERROR rust-cold is experimental
+type TAU = extern "rust-cold" fn(); //~ ERROR "rust-cold" ABI is experimental
 
-extern "rust-cold" {} //~ ERROR rust-cold is experimental
+extern "rust-cold" {} //~ ERROR "rust-cold" ABI is experimental
diff --git a/tests/ui/feature-gates/feature-gate-rust_cold_cc.stderr b/tests/ui/feature-gates/feature-gate-rust_cold_cc.stderr
index eeff9534d528f..9547c64f2b2ec 100644
--- a/tests/ui/feature-gates/feature-gate-rust_cold_cc.stderr
+++ b/tests/ui/feature-gates/feature-gate-rust_cold_cc.stderr
@@ -1,4 +1,4 @@
-error[E0658]: rust-cold is experimental and subject to change
+error[E0658]: the extern "rust-cold" ABI is experimental and subject to change
   --> $DIR/feature-gate-rust_cold_cc.rs:3:8
    |
 LL | extern "rust-cold" fn fu() {}
@@ -8,7 +8,7 @@ LL | extern "rust-cold" fn fu() {}
    = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-cold is experimental and subject to change
+error[E0658]: the extern "rust-cold" ABI is experimental and subject to change
   --> $DIR/feature-gate-rust_cold_cc.rs:6:12
    |
 LL |     extern "rust-cold" fn mu();
@@ -18,7 +18,7 @@ LL |     extern "rust-cold" fn mu();
    = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-cold is experimental and subject to change
+error[E0658]: the extern "rust-cold" ABI is experimental and subject to change
   --> $DIR/feature-gate-rust_cold_cc.rs:7:12
    |
 LL |     extern "rust-cold" fn dmu() {}
@@ -28,7 +28,7 @@ LL |     extern "rust-cold" fn dmu() {}
    = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-cold is experimental and subject to change
+error[E0658]: the extern "rust-cold" ABI is experimental and subject to change
   --> $DIR/feature-gate-rust_cold_cc.rs:12:12
    |
 LL |     extern "rust-cold" fn mu() {}
@@ -38,7 +38,7 @@ LL |     extern "rust-cold" fn mu() {}
    = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-cold is experimental and subject to change
+error[E0658]: the extern "rust-cold" ABI is experimental and subject to change
   --> $DIR/feature-gate-rust_cold_cc.rs:16:12
    |
 LL |     extern "rust-cold" fn imu() {}
@@ -48,7 +48,7 @@ LL |     extern "rust-cold" fn imu() {}
    = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-cold is experimental and subject to change
+error[E0658]: the extern "rust-cold" ABI is experimental and subject to change
   --> $DIR/feature-gate-rust_cold_cc.rs:19:19
    |
 LL | type TAU = extern "rust-cold" fn();
@@ -58,7 +58,7 @@ LL | type TAU = extern "rust-cold" fn();
    = help: add `#![feature(rust_cold_cc)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-cold is experimental and subject to change
+error[E0658]: the extern "rust-cold" ABI is experimental and subject to change
   --> $DIR/feature-gate-rust_cold_cc.rs:21:8
    |
 LL | extern "rust-cold" {}
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs
index ff528274c59be..7b40c8760e368 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.rs
@@ -11,7 +11,7 @@ impl Fn<()> for Foo {
     //~| ERROR manual implementations of `Fn` are experimental
     //~| ERROR expected a `FnMut()` closure, found `Foo`
     extern "rust-call" fn call(self, args: ()) -> () {}
-    //~^ ERROR rust-call ABI is subject to change
+    //~^ ERROR "rust-call" ABI is experimental and subject to change
     //~| ERROR `call` has an incompatible type for trait
 }
 struct Foo1;
@@ -20,7 +20,7 @@ impl FnOnce() for Foo1 {
     //~| ERROR manual implementations of `FnOnce` are experimental
     //~| ERROR not all trait items implemented
     extern "rust-call" fn call_once(self, args: ()) -> () {}
-    //~^ ERROR rust-call ABI is subject to change
+    //~^ ERROR "rust-call" ABI is experimental and subject to change
 }
 struct Bar;
 impl FnMut<()> for Bar {
@@ -28,7 +28,7 @@ impl FnMut<()> for Bar {
     //~| ERROR manual implementations of `FnMut` are experimental
     //~| ERROR expected a `FnOnce()` closure, found `Bar`
     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
-    //~^ ERROR rust-call ABI is subject to change
+    //~^ ERROR "rust-call" ABI is experimental and subject to change
     //~| ERROR incompatible type for trait
 }
 struct Baz;
@@ -37,7 +37,7 @@ impl FnOnce<()> for Baz {
     //~| ERROR manual implementations of `FnOnce` are experimental
     //~| ERROR not all trait items implemented
     extern "rust-call" fn call_once(&self, args: ()) -> () {}
-    //~^ ERROR rust-call ABI is subject to change
+    //~^ ERROR "rust-call" ABI is experimental and subject to change
 }
 
 fn main() {}
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
index 584724dfe59cc..f9d231dc78f7c 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures-manual-impls.stderr
@@ -1,4 +1,4 @@
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:13:12
    |
 LL |     extern "rust-call" fn call(self, args: ()) -> () {}
@@ -8,7 +8,7 @@ LL |     extern "rust-call" fn call(self, args: ()) -> () {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:22:12
    |
 LL |     extern "rust-call" fn call_once(self, args: ()) -> () {}
@@ -18,7 +18,7 @@ LL |     extern "rust-call" fn call_once(self, args: ()) -> () {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:30:12
    |
 LL |     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
@@ -28,7 +28,7 @@ LL |     extern "rust-call" fn call_mut(&self, args: ()) -> () {}
    = help: add `#![feature(unboxed_closures)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-unboxed-closures-manual-impls.rs:39:12
    |
 LL |     extern "rust-call" fn call_once(&self, args: ()) -> () {}
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures.rs b/tests/ui/feature-gates/feature-gate-unboxed-closures.rs
index ebc5a2536f672..74cc20c581cb9 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures.rs
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures.rs
@@ -10,7 +10,7 @@ impl FnOnce<(u32, u32)> for Test {
     extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
         a + b
     }
-    //~^^^ ERROR rust-call ABI is subject to change
+    //~^^^ ERROR "rust-call" ABI is experimental and subject to change
 }
 
 fn main() {
diff --git a/tests/ui/feature-gates/feature-gate-unboxed-closures.stderr b/tests/ui/feature-gates/feature-gate-unboxed-closures.stderr
index 52c18ec34c564..36932c1f86f9f 100644
--- a/tests/ui/feature-gates/feature-gate-unboxed-closures.stderr
+++ b/tests/ui/feature-gates/feature-gate-unboxed-closures.stderr
@@ -1,4 +1,4 @@
-error[E0658]: rust-call ABI is subject to change
+error[E0658]: the extern "rust-call" ABI is experimental and subject to change
   --> $DIR/feature-gate-unboxed-closures.rs:10:12
    |
 LL |     extern "rust-call" fn call_once(self, (a, b): (u32, u32)) -> u32 {
diff --git a/tests/ui/feature-gates/feature-gate-vectorcall.rs b/tests/ui/feature-gates/feature-gate-vectorcall.rs
index 73a11a842f377..aafa6a2ed629b 100644
--- a/tests/ui/feature-gates/feature-gate-vectorcall.rs
+++ b/tests/ui/feature-gates/feature-gate-vectorcall.rs
@@ -9,23 +9,23 @@ trait Sized { }
 // Test that the "vectorcall" ABI is feature-gated, and cannot be used when
 // the `vectorcall` feature gate is not used.
 
-extern "vectorcall" fn f() {} //~ ERROR vectorcall is experimental
+extern "vectorcall" fn f() {} //~ ERROR "vectorcall" ABI is experimental
 
 trait T {
-    extern "vectorcall" fn m(); //~ ERROR vectorcall is experimental
+    extern "vectorcall" fn m(); //~ ERROR "vectorcall" ABI is experimental
 
-    extern "vectorcall" fn dm() {} //~ ERROR vectorcall is experimental
+    extern "vectorcall" fn dm() {} //~ ERROR "vectorcall" ABI is experimental
 }
 
 struct S;
 impl T for S {
-    extern "vectorcall" fn m() {} //~ ERROR vectorcall is experimental
+    extern "vectorcall" fn m() {} //~ ERROR "vectorcall" ABI is experimental
 }
 
 impl S {
-    extern "vectorcall" fn im() {} //~ ERROR vectorcall is experimental
+    extern "vectorcall" fn im() {} //~ ERROR "vectorcall" ABI is experimental
 }
 
-type TA = extern "vectorcall" fn(); //~ ERROR vectorcall is experimental
+type TA = extern "vectorcall" fn(); //~ ERROR "vectorcall" ABI is experimental
 
-extern "vectorcall" {} //~ ERROR vectorcall is experimental
+extern "vectorcall" {} //~ ERROR "vectorcall" ABI is experimental
diff --git a/tests/ui/feature-gates/feature-gate-vectorcall.stderr b/tests/ui/feature-gates/feature-gate-vectorcall.stderr
index b20e41887b9bf..8f3f47a3d4888 100644
--- a/tests/ui/feature-gates/feature-gate-vectorcall.stderr
+++ b/tests/ui/feature-gates/feature-gate-vectorcall.stderr
@@ -1,4 +1,4 @@
-error[E0658]: vectorcall is experimental and subject to change
+error[E0658]: the extern "vectorcall" ABI is experimental and subject to change
   --> $DIR/feature-gate-vectorcall.rs:12:8
    |
 LL | extern "vectorcall" fn f() {}
@@ -8,7 +8,7 @@ LL | extern "vectorcall" fn f() {}
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: vectorcall is experimental and subject to change
+error[E0658]: the extern "vectorcall" ABI is experimental and subject to change
   --> $DIR/feature-gate-vectorcall.rs:15:12
    |
 LL |     extern "vectorcall" fn m();
@@ -18,7 +18,7 @@ LL |     extern "vectorcall" fn m();
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: vectorcall is experimental and subject to change
+error[E0658]: the extern "vectorcall" ABI is experimental and subject to change
   --> $DIR/feature-gate-vectorcall.rs:17:12
    |
 LL |     extern "vectorcall" fn dm() {}
@@ -28,7 +28,7 @@ LL |     extern "vectorcall" fn dm() {}
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: vectorcall is experimental and subject to change
+error[E0658]: the extern "vectorcall" ABI is experimental and subject to change
   --> $DIR/feature-gate-vectorcall.rs:22:12
    |
 LL |     extern "vectorcall" fn m() {}
@@ -38,7 +38,7 @@ LL |     extern "vectorcall" fn m() {}
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: vectorcall is experimental and subject to change
+error[E0658]: the extern "vectorcall" ABI is experimental and subject to change
   --> $DIR/feature-gate-vectorcall.rs:26:12
    |
 LL |     extern "vectorcall" fn im() {}
@@ -48,7 +48,7 @@ LL |     extern "vectorcall" fn im() {}
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: vectorcall is experimental and subject to change
+error[E0658]: the extern "vectorcall" ABI is experimental and subject to change
   --> $DIR/feature-gate-vectorcall.rs:29:18
    |
 LL | type TA = extern "vectorcall" fn();
@@ -58,7 +58,7 @@ LL | type TA = extern "vectorcall" fn();
    = help: add `#![feature(abi_vectorcall)]` to the crate attributes to enable
    = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
 
-error[E0658]: vectorcall is experimental and subject to change
+error[E0658]: the extern "vectorcall" ABI is experimental and subject to change
   --> $DIR/feature-gate-vectorcall.rs:31:8
    |
 LL | extern "vectorcall" {}
diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs
index 37b7d52fafcae..2328798d74c32 100644
--- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs
+++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.rs
@@ -5,7 +5,7 @@
 fn main() {
     let a = &[1, 2, 3];
     println!("{}", {
-        extern "rust-intrinsic" { //~ ERROR intrinsics are subject to change
+        extern "rust-intrinsic" { //~ ERROR "rust-intrinsic" ABI is an implementation detail
             fn atomic_fence();
         }
         atomic_fence(); //~ ERROR: is unsafe
diff --git a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr
index 3dc11b5612ca9..86f88fdff5fc8 100644
--- a/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr
+++ b/tests/ui/feature-gates/feature-gated-feature-in-macro-arg.stderr
@@ -1,4 +1,4 @@
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/feature-gated-feature-in-macro-arg.rs:8:16
    |
 LL |         extern "rust-intrinsic" {
diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs b/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs
index 66de1f60ed9bc..5520430e140b3 100644
--- a/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs
+++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.rs
@@ -3,5 +3,5 @@ fn main() {
 }
 
 extern "rust-intrinsic" fn read_via_copy() {}
-//~^ ERROR intrinsics are subject to change
+//~^ ERROR "rust-intrinsic" ABI is an implementation detail
 //~| ERROR intrinsic must be in `extern "rust-intrinsic" { ... }` block
diff --git a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr
index 362ee185b7b17..c6682693f7409 100644
--- a/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr
+++ b/tests/ui/intrinsics/incorrect-read_via_copy-defn.stderr
@@ -1,4 +1,4 @@
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/incorrect-read_via_copy-defn.rs:5:8
    |
 LL | extern "rust-intrinsic" fn read_via_copy() {}
diff --git a/tests/ui/intrinsics/incorrect-transmute.rs b/tests/ui/intrinsics/incorrect-transmute.rs
index eed524ae8a8a2..15d1ab939ed0b 100644
--- a/tests/ui/intrinsics/incorrect-transmute.rs
+++ b/tests/ui/intrinsics/incorrect-transmute.rs
@@ -3,5 +3,5 @@ fn main() {
 }
 
 extern "rust-intrinsic" fn transmute() {}
-//~^ ERROR intrinsics are subject to change
+//~^ ERROR "rust-intrinsic" ABI is an implementation detail
 //~| ERROR intrinsic must be in `extern "rust-intrinsic" { ... }` block
diff --git a/tests/ui/intrinsics/incorrect-transmute.stderr b/tests/ui/intrinsics/incorrect-transmute.stderr
index 8123f3d71a295..99dfb9847ff2e 100644
--- a/tests/ui/intrinsics/incorrect-transmute.stderr
+++ b/tests/ui/intrinsics/incorrect-transmute.stderr
@@ -1,4 +1,4 @@
-error[E0658]: intrinsics are subject to change
+error[E0658]: the extern "rust-intrinsic" ABI is an implementation detail and perma-unstable
   --> $DIR/incorrect-transmute.rs:5:8
    |
 LL | extern "rust-intrinsic" fn transmute() {}
diff --git a/tests/ui/self/invalid-self-dyn-receiver.rs b/tests/ui/self/invalid-self-dyn-receiver.rs
new file mode 100644
index 0000000000000..a989b331b5e0b
--- /dev/null
+++ b/tests/ui/self/invalid-self-dyn-receiver.rs
@@ -0,0 +1,20 @@
+// Makes sure we don't ICE when encountering a receiver that is *ostensibly* dyn safe,
+// because it satisfies `&dyn Bar: DispatchFromDyn<&dyn Bar>`, but is not a valid receiver
+// in wfcheck.
+
+#![feature(arbitrary_self_types)]
+
+use std::ops::Deref;
+
+trait Foo: Deref<Target = dyn Bar> {
+     fn method(self: &dyn Bar) {}
+     //~^ ERROR invalid `self` parameter type: `&dyn Bar`
+}
+
+trait Bar {}
+
+fn test(x: &dyn Foo) {
+     x.method();
+}
+
+fn main() {}
diff --git a/tests/ui/self/invalid-self-dyn-receiver.stderr b/tests/ui/self/invalid-self-dyn-receiver.stderr
new file mode 100644
index 0000000000000..f77f5686ad282
--- /dev/null
+++ b/tests/ui/self/invalid-self-dyn-receiver.stderr
@@ -0,0 +1,12 @@
+error[E0307]: invalid `self` parameter type: `&dyn Bar`
+  --> $DIR/invalid-self-dyn-receiver.rs:10:22
+   |
+LL |      fn method(self: &dyn Bar) {}
+   |                      ^^^^^^^^
+   |
+   = note: type of `self` must be `Self` or some type implementing `Receiver`
+   = help: consider changing to `self`, `&self`, `&mut self`, or a type implementing `Receiver` such as `self: Box<Self>`, `self: Rc<Self>`, or `self: Arc<Self>`
+
+error: aborting due to 1 previous error
+
+For more information about this error, try `rustc --explain E0307`.
diff --git a/tests/ui/type/pattern_types/assoc_const.default.stderr b/tests/ui/type/pattern_types/assoc_const.default.stderr
index abda40e468162..c5d9691a02918 100644
--- a/tests/ui/type/pattern_types/assoc_const.default.stderr
+++ b/tests/ui/type/pattern_types/assoc_const.default.stderr
@@ -1,3 +1,24 @@
+error[E0658]: wraparound pattern type ranges cause monomorphization time errors
+  --> $DIR/assoc_const.rs:17:19
+   |
+LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
+   = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: wraparound pattern type ranges cause monomorphization time errors
+  --> $DIR/assoc_const.rs:17:19
+   |
+LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
+   = help: add `#![feature(generic_pattern_types)]` 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error: constant expression depends on a generic parameter
   --> $DIR/assoc_const.rs:17:19
    |
@@ -15,8 +36,29 @@ LL | fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)
    = note: this may fail depending on what value the parameter takes
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
+error[E0658]: wraparound pattern type ranges cause monomorphization time errors
+  --> $DIR/assoc_const.rs:22:19
+   |
+LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
+   = help: add `#![feature(generic_pattern_types)]` to the crate attributes to enable
+   = note: this compiler was built on YYYY-MM-DD; consider upgrading it if it is out of date
+
+error[E0658]: wraparound pattern type ranges cause monomorphization time errors
+  --> $DIR/assoc_const.rs:22:19
+   |
+LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
+   |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
+   |
+   = note: see issue #136574 <https://github.com/rust-lang/rust/issues/136574> for more information
+   = help: add `#![feature(generic_pattern_types)]` 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: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
+
 error: constant expression depends on a generic parameter
-  --> $DIR/assoc_const.rs:20:19
+  --> $DIR/assoc_const.rs:22:19
    |
 LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -24,7 +66,7 @@ LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
    = note: this may fail depending on what value the parameter takes
 
 error: constant expression depends on a generic parameter
-  --> $DIR/assoc_const.rs:20:19
+  --> $DIR/assoc_const.rs:22:19
    |
 LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
    |                   ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
@@ -32,5 +74,6 @@ LL | fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
    = note: this may fail depending on what value the parameter takes
    = note: duplicate diagnostic emitted due to `-Z deduplicate-diagnostics=no`
 
-error: aborting due to 4 previous errors
+error: aborting due to 8 previous errors
 
+For more information about this error, try `rustc --explain E0658`.
diff --git a/tests/ui/type/pattern_types/assoc_const.rs b/tests/ui/type/pattern_types/assoc_const.rs
index af0f7e4cbf32f..87886587d5153 100644
--- a/tests/ui/type/pattern_types/assoc_const.rs
+++ b/tests/ui/type/pattern_types/assoc_const.rs
@@ -1,8 +1,8 @@
 #![feature(pattern_types)]
 #![feature(pattern_type_macro)]
-#![cfg_attr(const_arg, feature(generic_const_exprs))]
+#![cfg_attr(const_arg, feature(generic_const_exprs, generic_pattern_types))]
 #![expect(incomplete_features)]
-
+// gate-test-generic_pattern_types line to the test file.
 //@ revisions: default const_arg
 
 //@[const_arg] check-pass
@@ -17,8 +17,12 @@ trait Foo {
 fn foo<T: Foo>(_: pattern_type!(u32 is <T as Foo>::START..=<T as Foo>::END)) {}
 //[default]~^ ERROR: constant expression depends on a generic parameter
 //[default]~| ERROR: constant expression depends on a generic parameter
+//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
+//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
 fn bar<T: Foo>(_: pattern_type!(u32 is T::START..=T::END)) {}
 //[default]~^ ERROR: constant expression depends on a generic parameter
 //[default]~| ERROR: constant expression depends on a generic parameter
+//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
+//[default]~| ERROR: wraparound pattern type ranges cause monomorphization time errors
 
 fn main() {}
diff --git a/tests/ui/type/pattern_types/const_generics.rs b/tests/ui/type/pattern_types/const_generics.rs
index 5cef0dc030552..79d46c010d733 100644
--- a/tests/ui/type/pattern_types/const_generics.rs
+++ b/tests/ui/type/pattern_types/const_generics.rs
@@ -1,7 +1,7 @@
 //@ check-pass
 
-#![feature(pattern_types)]
-#![feature(pattern_type_macro)]
+#![feature(pattern_types, generic_pattern_types, pattern_type_macro)]
+#![expect(incomplete_features)]
 
 use std::pat::pattern_type;
 
diff --git a/tests/ui/type/pattern_types/transmute.rs b/tests/ui/type/pattern_types/transmute.rs
index cb76b2b938dc6..43dd62a19e706 100644
--- a/tests/ui/type/pattern_types/transmute.rs
+++ b/tests/ui/type/pattern_types/transmute.rs
@@ -1,5 +1,5 @@
-#![feature(pattern_types)]
-#![feature(pattern_type_macro)]
+#![feature(pattern_types, pattern_type_macro, generic_pattern_types)]
+#![expect(incomplete_features)]
 
 use std::pat::pattern_type;
 
diff --git a/triagebot.toml b/triagebot.toml
index efd694994f9f7..169a6121615ac 100644
--- a/triagebot.toml
+++ b/triagebot.toml
@@ -1096,6 +1096,8 @@ bootstrap = [
 infra-ci = [
     "@Mark-Simulacrum",
     "@Kobzol",
+    "@marcoieni",
+    "@jdno",
 ]
 rustdoc = [
     "@GuillaumeGomez",