Skip to main content

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 = ::rustc_feature::AttributeTemplate {
    word: false,
    list: Some(&["array, boxed_slice"]),
    one_of: &[],
    name_value_str: None,
    docs: None,
}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, args);
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::RustcSkipDuringMethodDispatch {
54            array,
55            boxed_slice,
56            span: cx.attr_span,
57        })
58    }
59}
60
61pub(crate) struct ParenSugarParser;
62impl<S: Stage> NoArgsAttributeParser<S> for ParenSugarParser {
63    const PATH: &[Symbol] = &[sym::rustc_paren_sugar];
64    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
65    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
66    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcParenSugar;
67}
68
69pub(crate) struct TypeConstParser;
70impl<S: Stage> NoArgsAttributeParser<S> for TypeConstParser {
71    const PATH: &[Symbol] = &[sym::type_const];
72    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
73    const ALLOWED_TARGETS: AllowedTargets =
74        AllowedTargets::AllowList(&[Allow(Target::Const), Allow(Target::AssocConst)]);
75    const CREATE: fn(Span) -> AttributeKind = AttributeKind::TypeConst;
76}
77
78// Markers
79
80pub(crate) struct MarkerParser;
81impl<S: Stage> NoArgsAttributeParser<S> for MarkerParser {
82    const PATH: &[Symbol] = &[sym::marker];
83    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
84    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
85        Allow(Target::Trait),
86        Warn(Target::Field),
87        Warn(Target::Arm),
88        Warn(Target::MacroDef),
89    ]);
90    const CREATE: fn(Span) -> AttributeKind = AttributeKind::Marker;
91}
92
93pub(crate) struct DenyExplicitImplParser;
94impl<S: Stage> NoArgsAttributeParser<S> for DenyExplicitImplParser {
95    const PATH: &[Symbol] = &[sym::rustc_deny_explicit_impl];
96    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
97    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
98    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcDenyExplicitImpl;
99}
100
101pub(crate) struct DynIncompatibleTraitParser;
102impl<S: Stage> NoArgsAttributeParser<S> for DynIncompatibleTraitParser {
103    const PATH: &[Symbol] = &[sym::rustc_dyn_incompatible_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::RustcDynIncompatibleTrait;
107}
108
109// Specialization
110
111pub(crate) struct SpecializationTraitParser;
112impl<S: Stage> NoArgsAttributeParser<S> for SpecializationTraitParser {
113    const PATH: &[Symbol] = &[sym::rustc_specialization_trait];
114    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
115    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
116    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcSpecializationTrait;
117}
118
119pub(crate) struct UnsafeSpecializationMarkerParser;
120impl<S: Stage> NoArgsAttributeParser<S> for UnsafeSpecializationMarkerParser {
121    const PATH: &[Symbol] = &[sym::rustc_unsafe_specialization_marker];
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::RustcUnsafeSpecializationMarker;
125}
126
127// Coherence
128
129pub(crate) struct CoinductiveParser;
130impl<S: Stage> NoArgsAttributeParser<S> for CoinductiveParser {
131    const PATH: &[Symbol] = &[sym::rustc_coinductive];
132    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
133    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
134    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcCoinductive;
135}
136
137pub(crate) struct AllowIncoherentImplParser;
138impl<S: Stage> NoArgsAttributeParser<S> for AllowIncoherentImplParser {
139    const PATH: &[Symbol] = &[sym::rustc_allow_incoherent_impl];
140    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
141    const ALLOWED_TARGETS: AllowedTargets =
142        AllowedTargets::AllowList(&[Allow(Target::Method(MethodKind::Inherent))]);
143    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcAllowIncoherentImpl;
144}
145
146pub(crate) struct FundamentalParser;
147impl<S: Stage> NoArgsAttributeParser<S> for FundamentalParser {
148    const PATH: &[Symbol] = &[sym::fundamental];
149    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
150    const ALLOWED_TARGETS: AllowedTargets =
151        AllowedTargets::AllowList(&[Allow(Target::Struct), Allow(Target::Trait)]);
152    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Fundamental;
153}
154
155pub(crate) struct PointeeParser;
156impl<S: Stage> NoArgsAttributeParser<S> for PointeeParser {
157    const PATH: &[Symbol] = &[sym::pointee];
158    const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
159    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); //FIXME Still checked fully in `check_attr.rs`
160    const CREATE: fn(Span) -> AttributeKind = AttributeKind::Pointee;
161}