rustc_attr_parsing/attributes/
traits.rs

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