about summary refs log tree commit diff
path: root/compiler/rustc_feature/src
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_feature/src')
-rw-r--r--compiler/rustc_feature/src/builtin_attrs.rs254
-rw-r--r--compiler/rustc_feature/src/lib.rs13
-rw-r--r--compiler/rustc_feature/src/removed.rs2
-rw-r--r--compiler/rustc_feature/src/unstable.rs6
4 files changed, 153 insertions, 122 deletions
diff --git a/compiler/rustc_feature/src/builtin_attrs.rs b/compiler/rustc_feature/src/builtin_attrs.rs
index c117e0fcf7c..b5218ec267c 100644
--- a/compiler/rustc_feature/src/builtin_attrs.rs
+++ b/compiler/rustc_feature/src/builtin_attrs.rs
@@ -9,7 +9,7 @@ use rustc_data_structures::fx::FxHashMap;
 use rustc_span::edition::Edition;
 use rustc_span::{Symbol, sym};
 
-use crate::{Features, Stability};
+use crate::Features;
 
 type GateFn = fn(&Features) -> bool;
 
@@ -94,34 +94,24 @@ pub enum AttributeSafety {
     Unsafe { unsafe_since: Option<Edition> },
 }
 
-#[derive(Clone, Copy)]
+#[derive(Clone, Debug, Copy)]
 pub enum AttributeGate {
-    /// Is gated by a given feature gate, reason
-    /// and function to check if enabled
-    Gated(Stability, Symbol, &'static str, fn(&Features) -> bool),
-
+    /// A gated attribute which requires a feature gate to be enabled.
+    Gated {
+        /// The feature gate, for example `#![feature(rustc_attrs)]` for rustc_* attributes.
+        feature: Symbol,
+        /// The error message displayed when an attempt is made to use the attribute without its feature gate.
+        message: &'static str,
+        /// Check function to be called during the `PostExpansionVisitor` pass.
+        check: fn(&Features) -> bool,
+        /// Notes to be displayed when an attempt is made to use the attribute without its feature gate.
+        notes: &'static [&'static str],
+    },
     /// Ungated attribute, can be used on all release channels
     Ungated,
 }
 
-// fn() is not Debug
-impl std::fmt::Debug for AttributeGate {
-    fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
-        match *self {
-            Self::Gated(ref stab, name, expl, _) => {
-                write!(fmt, "Gated({stab:?}, {name}, {expl})")
-            }
-            Self::Ungated => write!(fmt, "Ungated"),
-        }
-    }
-}
-
-impl AttributeGate {
-    fn is_deprecated(&self) -> bool {
-        matches!(*self, Self::Gated(Stability::Deprecated(_, _), ..))
-    }
-}
-
+// FIXME(jdonszelmann): move to rustc_attr_data_structures
 /// A template that the attribute input must match.
 /// Only top-level shape (`#[attr]` vs `#[attr(...)]` vs `#[attr = ...]`) is considered now.
 #[derive(Clone, Copy, Default)]
@@ -138,6 +128,26 @@ pub struct AttributeTemplate {
     pub name_value_str: Option<&'static str>,
 }
 
+impl AttributeTemplate {
+    pub fn suggestions(&self, inner: bool, name: impl std::fmt::Display) -> Vec<String> {
+        let mut suggestions = vec![];
+        let inner = if inner { "!" } else { "" };
+        if self.word {
+            suggestions.push(format!("#{inner}[{name}]"));
+        }
+        if let Some(descr) = self.list {
+            suggestions.push(format!("#{inner}[{name}({descr})]"));
+        }
+        suggestions.extend(self.one_of.iter().map(|&word| format!("#{inner}[{name}({word})]")));
+        if let Some(descr) = self.name_value_str {
+            suggestions.push(format!("#{inner}[{name} = \"{descr}\"]"));
+        }
+        suggestions.sort();
+
+        suggestions
+    }
+}
+
 /// How to handle multiple duplicate attributes on the same item.
 #[derive(Clone, Copy, Default)]
 pub enum AttributeDuplicates {
@@ -192,20 +202,21 @@ pub enum AttributeDuplicates {
 /// A convenience macro for constructing attribute templates.
 /// E.g., `template!(Word, List: "description")` means that the attribute
 /// supports forms `#[attr]` and `#[attr(description)]`.
+#[macro_export]
 macro_rules! template {
-    (Word) => { template!(@ true, None, &[], None) };
-    (List: $descr: expr) => { template!(@ false, Some($descr), &[], None) };
-    (OneOf: $one_of: expr) => { template!(@ false, None, $one_of, None) };
-    (NameValueStr: $descr: expr) => { template!(@ false, None, &[], Some($descr)) };
-    (Word, List: $descr: expr) => { template!(@ true, Some($descr), &[], None) };
-    (Word, NameValueStr: $descr: expr) => { template!(@ true, None, &[], Some($descr)) };
+    (Word) => { $crate::template!(@ true, None, &[], None) };
+    (List: $descr: expr) => { $crate::template!(@ false, Some($descr), &[], None) };
+    (OneOf: $one_of: expr) => { $crate::template!(@ false, None, $one_of, None) };
+    (NameValueStr: $descr: expr) => { $crate::template!(@ false, None, &[], Some($descr)) };
+    (Word, List: $descr: expr) => { $crate::template!(@ true, Some($descr), &[], None) };
+    (Word, NameValueStr: $descr: expr) => { $crate::template!(@ true, None, &[], Some($descr)) };
     (List: $descr1: expr, NameValueStr: $descr2: expr) => {
-        template!(@ false, Some($descr1), &[], Some($descr2))
+        $crate::template!(@ false, Some($descr1), &[], Some($descr2))
     };
     (Word, List: $descr1: expr, NameValueStr: $descr2: expr) => {
-        template!(@ true, Some($descr1), &[], Some($descr2))
+        $crate::template!(@ true, Some($descr1), &[], Some($descr2))
     };
-    (@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr) => { AttributeTemplate {
+    (@ $word: expr, $list: expr, $one_of: expr, $name_value_str: expr) => { $crate::AttributeTemplate {
         word: $word, list: $list, one_of: $one_of, name_value_str: $name_value_str
     } };
 }
@@ -247,7 +258,7 @@ macro_rules! ungated {
 }
 
 macro_rules! gated {
-    (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => {
+    (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $message:expr $(,)?) => {
         BuiltinAttribute {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
@@ -255,10 +266,15 @@ macro_rules! gated {
             safety: AttributeSafety::Unsafe { unsafe_since: None },
             template: $tpl,
             duplicates: $duplicates,
-            gate: Gated(Stability::Unstable, sym::$gate, $msg, Features::$gate),
+            gate: Gated {
+                feature: sym::$gate,
+                message: $message,
+                check: Features::$gate,
+                notes: &[],
+            },
         }
     };
-    (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => {
+    (unsafe $attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $message:expr $(,)?) => {
         BuiltinAttribute {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
@@ -266,10 +282,15 @@ macro_rules! gated {
             safety: AttributeSafety::Unsafe { unsafe_since: None },
             template: $tpl,
             duplicates: $duplicates,
-            gate: Gated(Stability::Unstable, sym::$attr, $msg, Features::$attr),
+            gate: Gated {
+                feature: sym::$attr,
+                message: $message,
+                check: Features::$attr,
+                notes: &[],
+            },
         }
     };
-    ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $msg:expr $(,)?) => {
+    ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $gate:ident, $message:expr $(,)?) => {
         BuiltinAttribute {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
@@ -277,10 +298,15 @@ macro_rules! gated {
             safety: AttributeSafety::Normal,
             template: $tpl,
             duplicates: $duplicates,
-            gate: Gated(Stability::Unstable, sym::$gate, $msg, Features::$gate),
+            gate: Gated {
+                feature: sym::$gate,
+                message: $message,
+                check: Features::$gate,
+                notes: &[],
+            },
         }
     };
-    ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => {
+    ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $message:expr $(,)?) => {
         BuiltinAttribute {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
@@ -288,7 +314,12 @@ macro_rules! gated {
             safety: AttributeSafety::Normal,
             template: $tpl,
             duplicates: $duplicates,
-            gate: Gated(Stability::Unstable, sym::$attr, $msg, Features::$attr),
+            gate: Gated {
+                feature: sym::$attr,
+                message: $message,
+                check: Features::$attr,
+                notes: &[],
+            },
         }
     };
 }
@@ -304,12 +335,11 @@ macro_rules! rustc_attr {
             concat!(
                 "the `#[",
                 stringify!($attr),
-                "]` attribute is just used for rustc unit tests \
-                and will never be stable",
+                "]` attribute is used for rustc unit tests"
             ),
         )
     };
-    ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $msg:expr $(,)?) => {
+    ($attr:ident, $typ:expr, $tpl:expr, $duplicates:expr, $encode_cross_crate:expr, $($notes:expr),* $(,)?) => {
         BuiltinAttribute {
             name: sym::$attr,
             encode_cross_crate: $encode_cross_crate,
@@ -317,7 +347,17 @@ macro_rules! rustc_attr {
             safety: AttributeSafety::Normal,
             template: $tpl,
             duplicates: $duplicates,
-            gate: Gated(Stability::Unstable, sym::rustc_attrs, $msg, Features::rustc_attrs),
+            gate: Gated {
+                feature: sym::rustc_attrs,
+                message: "use of an internal attribute",
+                check: Features::rustc_attrs,
+                notes: &[
+                    concat!("the `#[",
+                    stringify!($attr),
+                    "]` attribute is an internal implementation detail that will never be stable"),
+                    $($notes),*
+                    ]
+            },
         }
     };
 }
@@ -328,9 +368,6 @@ macro_rules! experimental {
     };
 }
 
-const IMPL_DETAIL: &str = "internal implementation detail";
-const INTERNAL_UNSTABLE: &str = "this is an internal attribute that will never be stable";
-
 #[derive(PartialEq)]
 pub enum EncodeCrossCrate {
     Yes,
@@ -668,7 +705,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         rustc_deprecated_safe_2024, Normal, template!(List: r#"audit_that = "...""#),
         ErrorFollowing, EncodeCrossCrate::Yes,
-        "rustc_deprecated_safe_2024 is supposed to be used in libstd only",
+        "`#[rustc_deprecated_safe_2024]` is used to declare functions unsafe across the edition 2024 boundary",
     ),
     rustc_attr!(
         rustc_pub_transparent, Normal, template!(Word),
@@ -695,7 +732,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         ErrorFollowing,
         EncodeCrossCrate::No,
         "`rustc_never_type_options` is used to experiment with never type fallback and work on \
-         never type stabilization, and will never be stable"
+         never type stabilization"
     ),
 
     // ==========================================================================
@@ -704,23 +741,23 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
 
     rustc_attr!(
         rustc_allocator, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, IMPL_DETAIL
+        EncodeCrossCrate::No,
     ),
     rustc_attr!(
         rustc_nounwind, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, IMPL_DETAIL
+        EncodeCrossCrate::No,
     ),
     rustc_attr!(
         rustc_reallocator, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, IMPL_DETAIL
+        EncodeCrossCrate::No,
     ),
     rustc_attr!(
         rustc_deallocator, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, IMPL_DETAIL
+        EncodeCrossCrate::No,
     ),
     rustc_attr!(
         rustc_allocator_zeroed, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, IMPL_DETAIL
+        EncodeCrossCrate::No,
     ),
     gated!(
         default_lib_allocator, Normal, template!(Word), WarnFollowing,
@@ -762,7 +799,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     rustc_attr!(
         rustc_std_internal_symbol, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, INTERNAL_UNSTABLE
+        EncodeCrossCrate::No,
     ),
 
     // ==========================================================================
@@ -772,11 +809,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         rustc_builtin_macro, Normal,
         template!(Word, List: "name, /*opt*/ attributes(name1, name2, ...)"), ErrorFollowing,
-        EncodeCrossCrate::Yes, IMPL_DETAIL
+        EncodeCrossCrate::Yes,
     ),
     rustc_attr!(
         rustc_proc_macro_decls, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, INTERNAL_UNSTABLE
+        EncodeCrossCrate::No,
     ),
     rustc_attr!(
         rustc_macro_transparency, Normal,
@@ -786,7 +823,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         rustc_autodiff, Normal,
         template!(Word, List: r#""...""#), DuplicatesOk,
-        EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        EncodeCrossCrate::Yes,
     ),
     // Traces that are left when `cfg` and `cfg_attr` attributes are expanded.
     // The attributes are not gated, to avoid stability errors, but they cannot be used in stable
@@ -812,54 +849,53 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
             NameValueStr: "message"
         ),
         ErrorFollowing, EncodeCrossCrate::Yes,
-        INTERNAL_UNSTABLE
+        "see `#[diagnostic::on_unimplemented]` for the stable equivalent of this attribute"
     ),
     rustc_attr!(
         rustc_confusables, Normal,
         template!(List: r#""name1", "name2", ..."#),
         ErrorFollowing, EncodeCrossCrate::Yes,
-        INTERNAL_UNSTABLE,
     ),
     // Enumerates "identity-like" conversion methods to suggest on type mismatch.
     rustc_attr!(
         rustc_conversion_suggestion, Normal, template!(Word),
-        WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        WarnFollowing, EncodeCrossCrate::Yes,
     ),
     // Prevents field reads in the marked trait or method to be considered
     // during dead code analysis.
     rustc_attr!(
         rustc_trivial_field_reads, Normal, template!(Word),
-        WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        WarnFollowing, EncodeCrossCrate::Yes,
     ),
     // Used by the `rustc::potential_query_instability` lint to warn methods which
     // might not be stable during incremental compilation.
     rustc_attr!(
         rustc_lint_query_instability, Normal, template!(Word),
-        WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        WarnFollowing, EncodeCrossCrate::Yes,
     ),
     // Used by the `rustc::untracked_query_information` lint to warn methods which
     // might not be stable during incremental compilation.
     rustc_attr!(
         rustc_lint_untracked_query_information, Normal, template!(Word),
-        WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        WarnFollowing, EncodeCrossCrate::Yes,
     ),
     // Used by the `rustc::diagnostic_outside_of_impl` lints to assist in changes to diagnostic
     // APIs. Any function with this attribute will be checked by that lint.
     rustc_attr!(
         rustc_lint_diagnostics, Normal, template!(Word),
-        WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        WarnFollowing, EncodeCrossCrate::Yes,
     ),
     // Used by the `rustc::bad_opt_access` lint to identify `DebuggingOptions` and `CodegenOptions`
     // types (as well as any others in future).
     rustc_attr!(
         rustc_lint_opt_ty, Normal, template!(Word),
-        WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        WarnFollowing, EncodeCrossCrate::Yes,
     ),
     // Used by the `rustc::bad_opt_access` lint on fields
     // types (as well as any others in future).
     rustc_attr!(
         rustc_lint_opt_deny_field_access, Normal, template!(List: "message"),
-        WarnFollowing, EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        WarnFollowing, EncodeCrossCrate::Yes,
     ),
 
     // ==========================================================================
@@ -868,28 +904,30 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
 
     rustc_attr!(
         rustc_promotable, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::No, IMPL_DETAIL),
+        EncodeCrossCrate::No, ),
     rustc_attr!(
         rustc_legacy_const_generics, Normal, template!(List: "N"), ErrorFollowing,
-        EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        EncodeCrossCrate::Yes,
     ),
-    // Do not const-check this function's body. It will always get replaced during CTFE.
+    // Do not const-check this function's body. It will always get replaced during CTFE via `hook_special_const_fn`.
     rustc_attr!(
         rustc_do_not_const_check, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        EncodeCrossCrate::Yes, "`#[rustc_do_not_const_check]` skips const-check for this function's body",
     ),
-    // Ensure the argument to this function is &&str during const-check.
     rustc_attr!(
         rustc_const_panic_str, Normal, template!(Word), WarnFollowing,
-        EncodeCrossCrate::Yes, INTERNAL_UNSTABLE
+        EncodeCrossCrate::Yes, "`#[rustc_const_panic_str]` ensures the argument to this function is &&str during const-check",
     ),
     rustc_attr!(
         rustc_const_stable_indirect, Normal,
-        template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
+        template!(Word),
+        WarnFollowing,
+        EncodeCrossCrate::No,
+        "this is an internal implementation detail",
     ),
     rustc_attr!(
         rustc_intrinsic_const_stable_indirect, Normal,
-        template!(Word), WarnFollowing, EncodeCrossCrate::No, IMPL_DETAIL,
+        template!(Word), WarnFollowing, EncodeCrossCrate::No,  "this is an internal implementation detail",
     ),
     gated!(
         rustc_allow_const_fn_unstable, Normal,
@@ -905,21 +943,21 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_layout_scalar_valid_range_start, Normal, template!(List: "value"), ErrorFollowing,
         EncodeCrossCrate::Yes,
         "the `#[rustc_layout_scalar_valid_range_start]` attribute is just used to enable \
-        niche optimizations in libcore and libstd and will never be stable",
+        niche optimizations in the standard library",
     ),
     rustc_attr!(
         rustc_layout_scalar_valid_range_end, Normal, template!(List: "value"), ErrorFollowing,
         EncodeCrossCrate::Yes,
         "the `#[rustc_layout_scalar_valid_range_end]` attribute is just used to enable \
-        niche optimizations in libcore and libstd and will never be stable",
+        niche optimizations in the standard library",
     ),
     rustc_attr!(
         rustc_nonnull_optimization_guaranteed, Normal, template!(Word), WarnFollowing,
         EncodeCrossCrate::Yes,
         "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document \
-        guaranteed niche optimizations in libcore and libstd and will never be stable\n\
-        (note that the compiler does not even check whether the type indeed is being non-null-optimized; \
-        it is your responsibility to ensure that the attribute is only used on types that are optimized)",
+        guaranteed niche optimizations in the standard library",
+        "the compiler does not even check whether the type indeed is being non-null-optimized; \
+        it is your responsibility to ensure that the attribute is only used on types that are optimized",
     ),
 
     // ==========================================================================
@@ -932,17 +970,17 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         rustc_as_ptr, Normal, template!(Word), ErrorFollowing,
         EncodeCrossCrate::Yes,
-        "#[rustc_as_ptr] is used to mark functions returning pointers to their inner allocations."
+        "`#[rustc_as_ptr]` is used to mark functions returning pointers to their inner allocations."
     ),
     rustc_attr!(
         rustc_pass_by_value, Normal, template!(Word), ErrorFollowing,
         EncodeCrossCrate::Yes,
-        "#[rustc_pass_by_value] is used to mark types that must be passed by value instead of reference."
+        "`#[rustc_pass_by_value]` is used to mark types that must be passed by value instead of reference."
     ),
     rustc_attr!(
         rustc_never_returns_null_ptr, Normal, template!(Word), ErrorFollowing,
         EncodeCrossCrate::Yes,
-        "#[rustc_never_returns_null_ptr] is used to mark functions returning non-null pointers."
+        "`#[rustc_never_returns_null_ptr]` is used to mark functions returning non-null pointers."
     ),
     rustc_attr!(
         rustc_no_implicit_autorefs, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes,
@@ -950,15 +988,15 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     rustc_attr!(
         rustc_coherence_is_core, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
-        "#![rustc_coherence_is_core] allows inherent methods on builtin types, only intended to be used in `core`."
+        "`#![rustc_coherence_is_core]` allows inherent methods on builtin types, only intended to be used in `core`."
     ),
     rustc_attr!(
         rustc_coinductive, AttributeType::Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
-        "#![rustc_coinductive] changes a trait to be coinductive, allowing cycles in the trait solver."
+        "`#[rustc_coinductive]` changes a trait to be coinductive, allowing cycles in the trait solver."
     ),
     rustc_attr!(
         rustc_allow_incoherent_impl, AttributeType::Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
-        "#[rustc_allow_incoherent_impl] has to be added to all impl items of an incoherent inherent impl."
+        "`#[rustc_allow_incoherent_impl]` has to be added to all impl items of an incoherent inherent impl."
     ),
     rustc_attr!(
         rustc_preserve_ub_checks, AttributeType::CrateLevel, template!(Word), ErrorFollowing, EncodeCrossCrate::No,
@@ -970,7 +1008,7 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         template!(Word),
         ErrorFollowing,
         EncodeCrossCrate::No,
-        "#[rustc_deny_explicit_impl] enforces that a trait can have no user-provided impls"
+        "`#[rustc_deny_explicit_impl]` enforces that a trait can have no user-provided impls"
     ),
     rustc_attr!(
         rustc_do_not_implement_via_object,
@@ -978,14 +1016,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         template!(Word),
         ErrorFollowing,
         EncodeCrossCrate::No,
-        "#[rustc_do_not_implement_via_object] opts out of the automatic trait impl for trait objects \
+        "`#[rustc_do_not_implement_via_object]` opts out of the automatic trait impl for trait objects \
         (`impl Trait for dyn Trait`)"
     ),
     rustc_attr!(
         rustc_has_incoherent_inherent_impls, AttributeType::Normal, template!(Word),
         ErrorFollowing, EncodeCrossCrate::Yes,
-        "#[rustc_has_incoherent_inherent_impls] allows the addition of incoherent inherent impls for \
-         the given type by annotating all impl items with #[rustc_allow_incoherent_impl]."
+        "`#[rustc_has_incoherent_inherent_impls]` allows the addition of incoherent inherent impls for \
+         the given type by annotating all impl items with `#[rustc_allow_incoherent_impl]`."
     ),
 
     BuiltinAttribute {
@@ -996,12 +1034,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         safety: AttributeSafety::Normal,
         template: template!(NameValueStr: "name"),
         duplicates: ErrorFollowing,
-        gate: Gated(
-            Stability::Unstable,
-            sym::rustc_attrs,
-            "diagnostic items compiler internal support for linting",
-            Features::rustc_attrs,
-        ),
+        gate: Gated{
+            feature: sym::rustc_attrs,
+            message: "use of an internal attribute",
+            check: Features::rustc_attrs,
+            notes: &["the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types \
+            from the standard library for diagnostic purposes"],
+        },
     },
     gated!(
         // Used in resolve:
@@ -1015,14 +1054,14 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     rustc_attr!(
         rustc_inherit_overflow_checks, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::No,
         "the `#[rustc_inherit_overflow_checks]` attribute is just used to control \
-        overflow checking behavior of several libcore functions that are inlined \
-        across crates and will never be stable",
+        overflow checking behavior of several functions in the standard library that are inlined \
+        across crates",
     ),
     rustc_attr!(
         rustc_reservation_impl, Normal,
         template!(NameValueStr: "reservation message"), ErrorFollowing, EncodeCrossCrate::Yes,
         "the `#[rustc_reservation_impl]` attribute is internally used \
-         for reserving for `for<T> From<!> for T` impl"
+        for reserving `impl<T> From<!> for T` as part of the effort to stabilize `!`"
     ),
     rustc_attr!(
         rustc_test_marker, Normal, template!(NameValueStr: "name"), WarnFollowing,
@@ -1053,12 +1092,13 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
         rustc_must_implement_one_of, Normal, template!(List: "function1, function2, ..."),
         ErrorFollowing, EncodeCrossCrate::No,
         "the `#[rustc_must_implement_one_of]` attribute is used to change minimal complete \
-        definition of a trait, it's currently in experimental form and should be changed before \
-        being exposed outside of the std"
+        definition of a trait. Its syntax and semantics are highly experimental and will be \
+        subject to change before stabilization",
     ),
     rustc_attr!(
         rustc_doc_primitive, Normal, template!(NameValueStr: "primitive name"), ErrorFollowing,
-        EncodeCrossCrate::Yes, r#"`rustc_doc_primitive` is a rustc internal attribute"#,
+        EncodeCrossCrate::Yes, "the `#[rustc_doc_primitive]` attribute is used by the standard library \
+        to provide a way to generate documentation for primitive types",
     ),
     gated!(
         rustc_intrinsic, Normal, template!(Word), ErrorFollowing, EncodeCrossCrate::Yes, intrinsics,
@@ -1066,11 +1106,11 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
     rustc_attr!(
         rustc_no_mir_inline, Normal, template!(Word), WarnFollowing, EncodeCrossCrate::Yes,
-        "#[rustc_no_mir_inline] prevents the MIR inliner from inlining a function while not affecting codegen"
+        "`#[rustc_no_mir_inline]` prevents the MIR inliner from inlining a function while not affecting codegen"
     ),
     rustc_attr!(
         rustc_force_inline, Normal, template!(Word, NameValueStr: "reason"), WarnFollowing, EncodeCrossCrate::Yes,
-        "#[rustc_force_inline] forces a free function to be inlined"
+        "`#[rustc_force_inline]` forces a free function to be inlined"
     ),
 
     // ==========================================================================
@@ -1209,10 +1249,6 @@ pub static BUILTIN_ATTRIBUTES: &[BuiltinAttribute] = &[
     ),
 ];
 
-pub fn deprecated_attributes() -> Vec<&'static BuiltinAttribute> {
-    BUILTIN_ATTRIBUTES.iter().filter(|attr| attr.gate.is_deprecated()).collect()
-}
-
 pub fn is_builtin_attr_name(name: Symbol) -> bool {
     BUILTIN_ATTRIBUTE_MAP.get(&name).is_some()
 }
diff --git a/compiler/rustc_feature/src/lib.rs b/compiler/rustc_feature/src/lib.rs
index 25764755a8f..dbc0daa3d83 100644
--- a/compiler/rustc_feature/src/lib.rs
+++ b/compiler/rustc_feature/src/lib.rs
@@ -40,14 +40,6 @@ pub struct Feature {
     issue: Option<NonZero<u32>>,
 }
 
-#[derive(Copy, Clone, Debug)]
-pub enum Stability {
-    Unstable,
-    // First argument is tracking issue link; second argument is an optional
-    // help message, which defaults to "remove this attribute".
-    Deprecated(&'static str, Option<&'static str>),
-}
-
 #[derive(Clone, Copy, Debug, Hash)]
 pub enum UnstableFeatures {
     /// Disallow use of unstable features, as on beta/stable channels.
@@ -144,9 +136,8 @@ pub fn find_feature_issue(feature: Symbol, issue: GateIssue) -> Option<NonZero<u
 pub use accepted::ACCEPTED_LANG_FEATURES;
 pub use builtin_attrs::{
     AttributeDuplicates, AttributeGate, AttributeSafety, AttributeTemplate, AttributeType,
-    BUILTIN_ATTRIBUTE_MAP, BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg, deprecated_attributes,
-    encode_cross_crate, find_gated_cfg, is_builtin_attr_name, is_stable_diagnostic_attribute,
-    is_valid_for_get_attr,
+    BUILTIN_ATTRIBUTE_MAP, BUILTIN_ATTRIBUTES, BuiltinAttribute, GatedCfg, encode_cross_crate,
+    find_gated_cfg, is_builtin_attr_name, is_stable_diagnostic_attribute, is_valid_for_get_attr,
 };
 pub use removed::REMOVED_LANG_FEATURES;
 pub use unstable::{
diff --git a/compiler/rustc_feature/src/removed.rs b/compiler/rustc_feature/src/removed.rs
index 9738f169595..0cd090b25a4 100644
--- a/compiler/rustc_feature/src/removed.rs
+++ b/compiler/rustc_feature/src/removed.rs
@@ -263,6 +263,8 @@ declare_features! (
     /// Allows unnamed fields of struct and union type
     (removed, unnamed_fields, "1.83.0", Some(49804), Some("feature needs redesign"), 131045),
     (removed, unsafe_no_drop_flag, "1.0.0", None, None),
+    /// Allows unsized rvalues at arguments and parameters.
+    (removed, unsized_locals, "CURRENT_RUSTC_VERSION", Some(48055), Some("removed due to implementation concerns; see https://github.com/rust-lang/rust/issues/111942")),
     (removed, unsized_tuple_coercion, "1.87.0", Some(42877),
      Some("The feature restricts possible layouts for tuples, and this restriction is not worth it."), 137728),
     /// Allows `union` fields that don't implement `Copy` as long as they don't have any drop glue.
diff --git a/compiler/rustc_feature/src/unstable.rs b/compiler/rustc_feature/src/unstable.rs
index 8c6411342f2..a7bc6207149 100644
--- a/compiler/rustc_feature/src/unstable.rs
+++ b/compiler/rustc_feature/src/unstable.rs
@@ -237,6 +237,8 @@ declare_features! (
     (internal, profiler_runtime, "1.18.0", None),
     /// Allows using `rustc_*` attributes (RFC 572).
     (internal, rustc_attrs, "1.0.0", None),
+    /// Introduces a hierarchy of `Sized` traits (RFC 3729).
+    (unstable, sized_hierarchy, "CURRENT_RUSTC_VERSION", None),
     /// Allows using the `#[stable]` and `#[unstable]` attributes.
     (internal, staged_api, "1.0.0", None),
     /// Added for testing unstable lints; perma-unstable.
@@ -353,6 +355,8 @@ declare_features! (
     (unstable, abi_avr_interrupt, "1.45.0", Some(69664)),
     /// Allows `extern "C-cmse-nonsecure-call" fn()`.
     (unstable, abi_c_cmse_nonsecure_call, "1.51.0", Some(81391)),
+    /// Allows `extern "custom" fn()`.
+    (unstable, abi_custom, "CURRENT_RUSTC_VERSION", Some(140829)),
     /// Allows `extern "gpu-kernel" fn()`.
     (unstable, abi_gpu_kernel, "1.86.0", Some(135467)),
     /// Allows `extern "msp430-interrupt" fn()`.
@@ -663,8 +667,6 @@ declare_features! (
     (incomplete, unsized_const_params, "1.82.0", Some(95174)),
     /// Allows unsized fn parameters.
     (internal, unsized_fn_params, "1.49.0", Some(48055)),
-    /// Allows unsized rvalues at arguments and parameters.
-    (incomplete, unsized_locals, "1.30.0", Some(48055)),
     /// Allows using the `#[used(linker)]` (or `#[used(compiler)]`) attribute.
     (unstable, used_with_arg, "1.60.0", Some(93798)),
     /// Allows use of attributes in `where` clauses.