about summary refs log tree commit diff
diff options
context:
space:
mode:
authorPavel Grigorenko <GrigorenkoPV@ya.ru>2025-06-23 23:41:33 +0300
committerPavel Grigorenko <GrigorenkoPV@ya.ru>2025-07-09 01:03:00 +0300
commit62f58dbb2d4b9cc0f2a20cb836eb48d869358416 (patch)
tree76bde429674db93c6ebd2746dca68b44add1aabf
parentab68b0fb26485ab1fa6977b2d8b59cc8a171c4aa (diff)
Port `#[const_trait]` to the new attribute system
-rw-r--r--compiler/rustc_attr_data_structures/src/attributes.rs3
-rw-r--r--compiler/rustc_attr_data_structures/src/encode_cross_crate.rs1
-rw-r--r--compiler/rustc_attr_parsing/src/attributes/traits.rs13
-rw-r--r--compiler/rustc_attr_parsing/src/context.rs3
-rw-r--r--compiler/rustc_hir_analysis/src/collect.rs40
-rw-r--r--compiler/rustc_middle/src/ty/mod.rs11
-rw-r--r--compiler/rustc_parse/src/validate_attr.rs1
-rw-r--r--compiler/rustc_passes/src/check_attr.rs10
8 files changed, 49 insertions, 33 deletions
diff --git a/compiler/rustc_attr_data_structures/src/attributes.rs b/compiler/rustc_attr_data_structures/src/attributes.rs
index b656db32528..6ea98f66405 100644
--- a/compiler/rustc_attr_data_structures/src/attributes.rs
+++ b/compiler/rustc_attr_data_structures/src/attributes.rs
@@ -234,6 +234,9 @@ pub enum AttributeKind {
     /// Represents `#[rustc_const_stable_indirect]`.
     ConstStabilityIndirect,
 
+    /// Represents `#[const_trait]`.
+    ConstTrait(Span),
+
     /// Represents [`#[deprecated]`](https://doc.rust-lang.org/stable/reference/attributes/diagnostics.html#the-deprecated-attribute).
     Deprecation { deprecation: Deprecation, span: Span },
 
diff --git a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
index 5414c7b103b..f22a64b2fd0 100644
--- a/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
+++ b/compiler/rustc_attr_data_structures/src/encode_cross_crate.rs
@@ -23,6 +23,7 @@ impl AttributeKind {
             ConstContinue(..) => No,
             ConstStability { .. } => Yes,
             ConstStabilityIndirect => No,
+            ConstTrait(..) => No,
             Deprecation { .. } => Yes,
             DocComment { .. } => Yes,
             Dummy => No,
diff --git a/compiler/rustc_attr_parsing/src/attributes/traits.rs b/compiler/rustc_attr_parsing/src/attributes/traits.rs
index 83a98c53c7f..e897fc76ad7 100644
--- a/compiler/rustc_attr_parsing/src/attributes/traits.rs
+++ b/compiler/rustc_attr_parsing/src/attributes/traits.rs
@@ -2,9 +2,11 @@ use core::mem;
 
 use rustc_attr_data_structures::AttributeKind;
 use rustc_feature::{AttributeTemplate, template};
-use rustc_span::{Symbol, sym};
+use rustc_span::{Span, Symbol, sym};
 
-use crate::attributes::{AttributeOrder, OnDuplicate, SingleAttributeParser};
+use crate::attributes::{
+    AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
+};
 use crate::context::{AcceptContext, Stage};
 use crate::parser::ArgParser;
 
@@ -52,3 +54,10 @@ impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
         Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
     }
 }
+
+pub(crate) struct ConstTraitParser;
+impl<S: Stage> NoArgsAttributeParser<S> for ConstTraitParser {
+    const PATH: &[Symbol] = &[sym::const_trait];
+    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
+    const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait;
+}
diff --git a/compiler/rustc_attr_parsing/src/context.rs b/compiler/rustc_attr_parsing/src/context.rs
index dbe1a5b2ad0..9d294b0528d 100644
--- a/compiler/rustc_attr_parsing/src/context.rs
+++ b/compiler/rustc_attr_parsing/src/context.rs
@@ -43,7 +43,7 @@ use crate::attributes::stability::{
     BodyStabilityParser, ConstStabilityIndirectParser, ConstStabilityParser, StabilityParser,
 };
 use crate::attributes::test_attrs::IgnoreParser;
-use crate::attributes::traits::SkipDuringMethodDispatchParser;
+use crate::attributes::traits::{ConstTraitParser, SkipDuringMethodDispatchParser};
 use crate::attributes::transparency::TransparencyParser;
 use crate::attributes::{AttributeParser as _, Combine, Single, WithoutArgs};
 use crate::parser::{ArgParser, MetaItemParser, PathParser};
@@ -150,6 +150,7 @@ attribute_parsers!(
         Single<WithoutArgs<ColdParser>>,
         Single<WithoutArgs<ConstContinueParser>>,
         Single<WithoutArgs<ConstStabilityIndirectParser>>,
+        Single<WithoutArgs<ConstTraitParser>>,
         Single<WithoutArgs<ExportStableParser>>,
         Single<WithoutArgs<FfiConstParser>>,
         Single<WithoutArgs<FfiPureParser>>,
diff --git a/compiler/rustc_hir_analysis/src/collect.rs b/compiler/rustc_hir_analysis/src/collect.rs
index a185291887d..75e732ff461 100644
--- a/compiler/rustc_hir_analysis/src/collect.rs
+++ b/compiler/rustc_hir_analysis/src/collect.rs
@@ -852,39 +852,42 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
         _ => span_bug!(item.span, "trait_def_of_item invoked on non-trait"),
     };
 
+    let attrs = tcx.get_all_attrs(def_id);
     // Only regular traits can be const.
-    let constness = if !is_alias && tcx.has_attr(def_id, sym::const_trait) {
+    let constness = if !is_alias && find_attr!(attrs, AttributeKind::ConstTrait(_)) {
         hir::Constness::Const
     } else {
         hir::Constness::NotConst
     };
 
-    let paren_sugar = tcx.has_attr(def_id, sym::rustc_paren_sugar);
+    let paren_sugar = attrs.iter().any(|attr| attr.has_name(sym::rustc_paren_sugar));
     if paren_sugar && !tcx.features().unboxed_closures() {
         tcx.dcx().emit_err(errors::ParenSugarAttribute { span: item.span });
     }
 
     // Only regular traits can be marker.
-    let is_marker = !is_alias && tcx.has_attr(def_id, sym::marker);
+    let is_marker = !is_alias && attrs.iter().any(|attr| attr.has_name(sym::marker));
 
-    let rustc_coinductive = tcx.has_attr(def_id, sym::rustc_coinductive);
-    let is_fundamental = tcx.has_attr(def_id, sym::fundamental);
+    let rustc_coinductive = attrs.iter().any(|attr| attr.has_name(sym::rustc_coinductive));
+    let is_fundamental = attrs.iter().any(|attr| attr.has_name(sym::fundamental));
 
     let [skip_array_during_method_dispatch, skip_boxed_slice_during_method_dispatch] = find_attr!(
-        tcx.get_all_attrs(def_id),
-        AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span:_ } => [*array, *boxed_slice]
+        attrs,
+        AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: _ } => [*array, *boxed_slice]
     )
     .unwrap_or([false; 2]);
 
-    let specialization_kind = if tcx.has_attr(def_id, sym::rustc_unsafe_specialization_marker) {
-        ty::trait_def::TraitSpecializationKind::Marker
-    } else if tcx.has_attr(def_id, sym::rustc_specialization_trait) {
-        ty::trait_def::TraitSpecializationKind::AlwaysApplicable
-    } else {
-        ty::trait_def::TraitSpecializationKind::None
-    };
-    let must_implement_one_of = tcx
-        .get_attr(def_id, sym::rustc_must_implement_one_of)
+    let specialization_kind =
+        if attrs.iter().any(|attr| attr.has_name(sym::rustc_unsafe_specialization_marker)) {
+            ty::trait_def::TraitSpecializationKind::Marker
+        } else if attrs.iter().any(|attr| attr.has_name(sym::rustc_specialization_trait)) {
+            ty::trait_def::TraitSpecializationKind::AlwaysApplicable
+        } else {
+            ty::trait_def::TraitSpecializationKind::None
+        };
+    let must_implement_one_of = attrs
+        .iter()
+        .find(|attr| attr.has_name(sym::rustc_must_implement_one_of))
         // Check that there are at least 2 arguments of `#[rustc_must_implement_one_of]`
         // and that they are all identifiers
         .and_then(|attr| match attr.meta_item_list() {
@@ -958,8 +961,9 @@ fn trait_def(tcx: TyCtxt<'_>, def_id: LocalDefId) -> ty::TraitDef {
             no_dups.then_some(list)
         });
 
-    let deny_explicit_impl = tcx.has_attr(def_id, sym::rustc_deny_explicit_impl);
-    let implement_via_object = !tcx.has_attr(def_id, sym::rustc_do_not_implement_via_object);
+    let deny_explicit_impl = attrs.iter().any(|attr| attr.has_name(sym::rustc_deny_explicit_impl));
+    let implement_via_object =
+        !attrs.iter().any(|attr| attr.has_name(sym::rustc_do_not_implement_via_object));
 
     ty::TraitDef {
         def_id: def_id.to_def_id(),
diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs
index b780b1c5776..0177a95498b 100644
--- a/compiler/rustc_middle/src/ty/mod.rs
+++ b/compiler/rustc_middle/src/ty/mod.rs
@@ -1782,21 +1782,18 @@ impl<'tcx> TyCtxt<'tcx> {
         did: impl Into<DefId>,
         attr: Symbol,
     ) -> impl Iterator<Item = &'tcx hir::Attribute> {
-        self.get_all_attrs(did).filter(move |a: &&hir::Attribute| a.has_name(attr))
+        self.get_all_attrs(did).iter().filter(move |a: &&hir::Attribute| a.has_name(attr))
     }
 
     /// Gets all attributes.
     ///
     /// To see if an item has a specific attribute, you should use [`rustc_attr_data_structures::find_attr!`] so you can use matching.
-    pub fn get_all_attrs(
-        self,
-        did: impl Into<DefId>,
-    ) -> impl Iterator<Item = &'tcx hir::Attribute> {
+    pub fn get_all_attrs(self, did: impl Into<DefId>) -> &'tcx [hir::Attribute] {
         let did: DefId = did.into();
         if let Some(did) = did.as_local() {
-            self.hir_attrs(self.local_def_id_to_hir_id(did)).iter()
+            self.hir_attrs(self.local_def_id_to_hir_id(did))
         } else {
-            self.attrs_for_def(did).iter()
+            self.attrs_for_def(did)
         }
     }
 
diff --git a/compiler/rustc_parse/src/validate_attr.rs b/compiler/rustc_parse/src/validate_attr.rs
index 11424ec3724..53346b40e2b 100644
--- a/compiler/rustc_parse/src/validate_attr.rs
+++ b/compiler/rustc_parse/src/validate_attr.rs
@@ -283,6 +283,7 @@ pub fn check_builtin_meta_item(
                 | sym::rustc_confusables
                 | sym::rustc_skip_during_method_dispatch
                 | sym::rustc_pass_by_value
+                | sym::const_trait
                 | sym::repr
                 | sym::align
                 | sym::deprecated
diff --git a/compiler/rustc_passes/src/check_attr.rs b/compiler/rustc_passes/src/check_attr.rs
index 0aa6a2b41cf..744f93506fe 100644
--- a/compiler/rustc_passes/src/check_attr.rs
+++ b/compiler/rustc_passes/src/check_attr.rs
@@ -120,10 +120,10 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
         for attr in attrs {
             let mut style = None;
             match attr {
-                Attribute::Parsed(AttributeKind::SkipDuringMethodDispatch {
-                    span: attr_span,
-                    ..
-                }) => {
+                Attribute::Parsed(
+                    AttributeKind::SkipDuringMethodDispatch { span: attr_span, .. }
+                    | AttributeKind::ConstTrait(attr_span),
+                ) => {
                     self.check_must_be_applied_to_trait(*attr_span, span, target);
                 }
                 Attribute::Parsed(AttributeKind::Confusables { first_span, .. }) => {
@@ -301,7 +301,7 @@ impl<'tcx> CheckAttrVisitor<'tcx> {
                         | [sym::rustc_must_implement_one_of, ..]
                         | [sym::rustc_deny_explicit_impl, ..]
                         | [sym::rustc_do_not_implement_via_object, ..]
-                        | [sym::const_trait, ..] => self.check_must_be_applied_to_trait(attr.span(), span, target),
+                        => self.check_must_be_applied_to_trait(attr.span(), span, target),
                         [sym::collapse_debuginfo, ..] => self.check_collapse_debuginfo(attr, span, target),
                         [sym::must_not_suspend, ..] => self.check_must_not_suspend(attr, span, target),
                         [sym::rustc_allow_incoherent_impl, ..] => {