rustc_attr_parsing/attributes/
traits.rs

1use core::mem;
2
3use rustc_feature::{AttributeTemplate, template};
4use rustc_hir::attrs::AttributeKind;
5use rustc_hir::{MethodKind, Target};
6use rustc_span::{Span, Symbol, sym};
7
8use crate::attributes::{
9    AttributeOrder, NoArgsAttributeParser, OnDuplicate, SingleAttributeParser,
10};
11use crate::context::MaybeWarn::{Allow, Warn};
12use crate::context::{ALL_TARGETS, AcceptContext, AllowedTargets, Stage};
13use crate::parser::ArgParser;
14pub(crate) struct SkipDuringMethodDispatchParser;
15impl<S: Stage> SingleAttributeParser<S> for SkipDuringMethodDispatchParser {
16    const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
17    const ATTRIBUTE_ORDER: AttributeOrder = AttributeOrder::KeepInnermost;
18    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
19    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
20
21    const TEMPLATE: AttributeTemplate = template!(List: &["array, boxed_slice"]);
22
23    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser<'_>) -> Option<AttributeKind> {
24        let mut array = false;
25        let mut boxed_slice = false;
26        let Some(args) = args.list() else {
27            cx.expected_list(cx.attr_span);
28            return None;
29        };
30        if args.is_empty() {
31            cx.expected_at_least_one_argument(args.span);
32            return None;
33        }
34        for arg in args.mixed() {
35            let Some(arg) = arg.meta_item() else {
36                cx.unexpected_literal(arg.span());
37                continue;
38            };
39            if let Err(span) = arg.args().no_args() {
40                cx.expected_no_args(span);
41            }
42            let path = arg.path();
43            let (key, skip): (Symbol, &mut bool) = match path.word_sym() {
44                Some(key @ sym::array) => (key, &mut array),
45                Some(key @ sym::boxed_slice) => (key, &mut boxed_slice),
46                _ => {
47                    cx.expected_specific_argument(path.span(), vec!["array", "boxed_slice"]);
48                    continue;
49                }
50            };
51            if mem::replace(skip, true) {
52                cx.duplicate_key(arg.span(), key);
53            }
54        }
55        Some(AttributeKind::SkipDuringMethodDispatch { array, boxed_slice, span: cx.attr_span })
56    }
57}
58
59pub(crate) struct ParenSugarParser;
60impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
61    const PATH: &[Symbol] = &[sym::rustc_paren_sugar];
62    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
63    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
64    const CREATE: fn(Span) -> AttributeKind = AttributeKind::ParenSugar;
65}
66
67pub(crate) struct TypeConstParser;
68impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
69    const PATH: &[Symbol] = &[sym::type_const];
70    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
71    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::AssocConst)]);
72    const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
73}
74
75// Markers
76
77pub(crate) struct MarkerParser;
78impl<S: Stage> NoArgsAttributeParser<S> for MarkerParser {
79    const PATH: &[Symbol] = &[sym::marker];
80    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
81    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
82        Allow(Target::Trait),
83        Warn(Target::Field),
84        Warn(Target::Arm),
85        Warn(Target::MacroDef),
86    ]);
87    const CREATE: fn(Span) -> AttributeKind = AttributeKind::Marker;
88}
89
90pub(crate) struct DenyExplicitImplParser;
91impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
92    const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl];
93    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
94    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
95    const CREATE: fn(Span) -> AttributeKind = AttributeKind::DenyExplicitImpl;
96}
97
98pub(crate) struct DoNotImplementViaObjectParser;
99impl<S: Stage> NoArgsAttributeParser<S> for DoNotImplementViaObjectParser {
100    const PATH: &[Symbol] = &[sym::rustc_do_not_implement_via_object];
101    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
102    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
103    const CREATE: fn(Span) -> AttributeKind = AttributeKind::DoNotImplementViaObject;
104}
105
106// FIXME(const_trait_impl): remove this
107// Const traits
108
109pub(crate) struct ConstTraitParser;
110impl<S: Stage> NoArgsAttributeParser<S> for ConstTraitParser {
111    const PATH: &[Symbol] = &[sym::const_trait];
112    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
113    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
114    const CREATE: fn(Span) -> AttributeKind = AttributeKind::ConstTrait;
115}
116
117// Specialization
118
119pub(crate) struct SpecializationTraitParser;
120impl<S: Stage> NoArgsAttributeParser<S> for SpecializationTraitParser {
121    const PATH: &[Symbol] = &[sym::rustc_specialization_trait];
122    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
123    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
124    const CREATE: fn(Span) -> AttributeKind = AttributeKind::SpecializationTrait;
125}
126
127pub(crate) struct UnsafeSpecializationMarkerParser;
128impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser {
129    const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker];
130    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
131    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
132    const CREATE: fn(Span) -> AttributeKind = AttributeKind::UnsafeSpecializationMarker;
133}
134
135// Coherence
136
137pub(crate) struct CoinductiveParser;
138impl<S: Stage> NoArgsAttributeParser<S> for CoinductiveParser {
139    const PATH: &[Symbol] = &[sym::rustc_coinductive];
140    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
141    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
142    const CREATE: fn(Span) -> AttributeKind = AttributeKind::Coinductive;
143}
144
145pub(crate) struct AllowIncoherentImplParser;
146impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
147    const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl];
148    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
149    const ALLOWED_TARGETS: AllowedTargets =
150        AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]);
151    const CREATE: fn(Span) -> AttributeKind = AttributeKind::AllowIncoherentImpl;
152}
153
154pub(crate) struct CoherenceIsCoreParser;
155impl<S: Stage> NoArgsAttributeParser<S> for CoherenceIsCoreParser {
156    const PATH: &[Symbol] = &[sym::rustc_coherence_is_core];
157    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
158    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
159    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::CoherenceIsCore;
160}
161
162pub(crate) struct FundamentalParser;
163impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
164    const PATH: &[Symbol] = &[sym::fundamental];
165    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
166    const ALLOWED_TARGETS: AllowedTargets =
167        AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]);
168    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
169}
170
171pub(crate) struct PointeeParser;
172impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
173    const PATH: &[Symbol] = &[sym::pointee];
174    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
175    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
176    const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
177}