Skip to main content

rustc_attr_parsing/attributes/
traits.rs

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