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