Skip to main content

rustc_attr_parsing/attributes/
traits.rs

1use std::mem;
2
3use super::prelude::*;
4use crate::attributes::{NoArgsAttributeParser, OnDuplicate, SingleAttributeParser};
5use crate::context::{AcceptContext, Stage};
6use crate::parser::ArgParser;
7use crate::target_checking::Policy::{Allow, Warn};
8use crate::target_checking::{ALL_TARGETS, AllowedTargets};
9
10pub(crate) struct RustcSkipDuringMethodDispatchParser;
11impl<S: Stage> SingleAttributeParser<S> for RustcSkipDuringMethodDispatchParser {
12    const PATH: &[Symbol] = &[sym::rustc_skip_during_method_dispatch];
13    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
14    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
15
16    const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
    word: false,
    list: Some(&["array, boxed_slice"]),
    one_of: &[],
    name_value_str: None,
    docs: None,
}template!(List: &["array, boxed_slice"]);
17
18    fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
19        let mut array = false;
20        let mut boxed_slice = false;
21        let Some(args) = args.list() else {
22            let attr_span = cx.attr_span;
23            cx.adcx().expected_list(attr_span, args);
24            return None;
25        };
26        if args.is_empty() {
27            cx.adcx().expected_at_least_one_argument(args.span);
28            return None;
29        }
30        for arg in args.mixed() {
31            let Some(arg) = arg.meta_item() else {
32                cx.adcx().unexpected_literal(arg.span());
33                continue;
34            };
35            if let Err(span) = arg.args().no_args() {
36                cx.adcx().expected_no_args(span);
37            }
38            let path = arg.path();
39            let (key, skip): (Symbol, &mut bool) = match path.word_sym() {
40                Some(key @ sym::array) => (key, &mut array),
41                Some(key @ sym::boxed_slice) => (key, &mut boxed_slice),
42                _ => {
43                    cx.adcx()
44                        .expected_specific_argument(path.span(), &[sym::array, sym::boxed_slice]);
45                    continue;
46                }
47            };
48            if mem::replace(skip, true) {
49                cx.adcx().duplicate_key(arg.span(), key);
50            }
51        }
52        Some(AttributeKind::RustcSkipDuringMethodDispatch {
53            array,
54            boxed_slice,
55            span: cx.attr_span,
56        })
57    }
58}
59
60pub(crate) struct RustcParenSugarParser;
61impl<S: Stage> NoArgsAttributeParser<S> for RustcParenSugarParser {
62    const PATH: &[Symbol] = &[sym::rustc_paren_sugar];
63    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
64    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
65    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar;
66}
67
68// Markers
69
70pub(crate) struct MarkerParser;
71impl<S: Stage> NoArgsAttributeParser<S> for MarkerParser {
72    const PATH: &[Symbol] = &[sym::marker];
73    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
74    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
75        Allow(Target::Trait),
76        Warn(Target::Field),
77        Warn(Target::Arm),
78        Warn(Target::MacroDef),
79    ]);
80    const CREATE: fn(Span) -> AttributeKind = AttributeKind::Marker;
81}
82
83pub(crate) struct RustcDenyExplicitImplParser;
84impl<S: Stage> NoArgsAttributeParser<S> for RustcDenyExplicitImplParser {
85    const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl];
86    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
87    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
88    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDenyExplicitImpl;
89}
90
91pub(crate) struct RustcDynIncompatibleTraitParser;
92impl<S: Stage> NoArgsAttributeParser<S> for RustcDynIncompatibleTraitParser {
93    const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_trait];
94    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
95    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
96    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDynIncompatibleTrait;
97}
98
99// Specialization
100
101pub(crate) struct RustcSpecializationTraitParser;
102impl<S: Stage> NoArgsAttributeParser<S> for RustcSpecializationTraitParser {
103    const PATH: &[Symbol] = &[sym::rustc_specialization_trait];
104    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
105    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
106    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcSpecializationTrait;
107}
108
109pub(crate) struct RustcUnsafeSpecializationMarkerParser;
110impl<S: Stage> NoArgsAttributeParser<S> for RustcUnsafeSpecializationMarkerParser {
111    const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker];
112    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
113    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
114    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcUnsafeSpecializationMarker;
115}
116
117// Coherence
118
119pub(crate) struct RustcCoinductiveParser;
120impl<S: Stage> NoArgsAttributeParser<S> for RustcCoinductiveParser {
121    const PATH: &[Symbol] = &[sym::rustc_coinductive];
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::RustcCoinductive;
125}
126
127pub(crate) struct RustcAllowIncoherentImplParser;
128impl<S: Stage> NoArgsAttributeParser<S> for RustcAllowIncoherentImplParser {
129    const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl];
130    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
131    const ALLOWED_TARGETS: AllowedTargets =
132        AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]);
133    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAllowIncoherentImpl;
134}
135
136pub(crate) struct FundamentalParser;
137impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
138    const PATH: &[Symbol] = &[sym::fundamental];
139    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
140    const ALLOWED_TARGETS: AllowedTargets =
141        AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]);
142    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
143}
144
145pub(crate) struct PointeeParser;
146impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
147    const PATH: &[Symbol] = &[sym::pointee];
148    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
149    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
150    const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
151}