rustc_attr_parsing/attributes/
allow_unstable.rs

1use std::iter;
2
3use super::prelude::*;
4use crate::session_diagnostics;
5
6pub(crate) struct AllowInternalUnstableParser;
7impl<S: Stage> CombineAttributeParser<S> for AllowInternalUnstableParser {
8    const PATH: &[Symbol] = &[sym::allow_internal_unstable];
9    type Item = (Symbol, Span);
10    const CONVERT: ConvertFn<Self::Item> =
11        |items, span| AttributeKind::AllowInternalUnstable(items, span);
12    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
13        Allow(Target::MacroDef),
14        Allow(Target::Fn),
15        Warn(Target::Field),
16        Warn(Target::Arm),
17    ]);
18    const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
19
20    fn extend<'c>(
21        cx: &'c mut AcceptContext<'_, '_, S>,
22        args: &'c ArgParser<'_>,
23    ) -> impl IntoIterator<Item = Self::Item> {
24        parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
25            .into_iter()
26            .zip(iter::repeat(cx.attr_span))
27    }
28}
29
30pub(crate) struct UnstableFeatureBoundParser;
31impl<S: Stage> CombineAttributeParser<S> for UnstableFeatureBoundParser {
32    const PATH: &'static [rustc_span::Symbol] = &[sym::unstable_feature_bound];
33    type Item = (Symbol, Span);
34    const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::UnstableFeatureBound(items);
35    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
36        Allow(Target::Fn),
37        Allow(Target::Impl { of_trait: true }),
38        Allow(Target::Trait),
39    ]);
40    const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
41
42    fn extend<'c>(
43        cx: &'c mut AcceptContext<'_, '_, S>,
44        args: &'c ArgParser<'_>,
45    ) -> impl IntoIterator<Item = Self::Item> {
46        if !cx.features().staged_api() {
47            cx.emit_err(session_diagnostics::StabilityOutsideStd { span: cx.attr_span });
48        }
49        parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
50            .into_iter()
51            .zip(iter::repeat(cx.attr_span))
52    }
53}
54
55pub(crate) struct AllowConstFnUnstableParser;
56impl<S: Stage> CombineAttributeParser<S> for AllowConstFnUnstableParser {
57    const PATH: &[Symbol] = &[sym::rustc_allow_const_fn_unstable];
58    type Item = Symbol;
59    const CONVERT: ConvertFn<Self::Item> =
60        |items, first_span| AttributeKind::AllowConstFnUnstable(items, first_span);
61    const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
62        Allow(Target::Fn),
63        Allow(Target::Method(MethodKind::Inherent)),
64        Allow(Target::Method(MethodKind::Trait { body: false })),
65        Allow(Target::Method(MethodKind::Trait { body: true })),
66        Allow(Target::Method(MethodKind::TraitImpl)),
67    ]);
68    const TEMPLATE: AttributeTemplate = template!(Word, List: &["feat1, feat2, ..."]);
69
70    fn extend<'c>(
71        cx: &'c mut AcceptContext<'_, '_, S>,
72        args: &'c ArgParser<'_>,
73    ) -> impl IntoIterator<Item = Self::Item> + 'c {
74        parse_unstable(cx, args, <Self as CombineAttributeParser<S>>::PATH[0])
75    }
76}
77
78fn parse_unstable<S: Stage>(
79    cx: &AcceptContext<'_, '_, S>,
80    args: &ArgParser<'_>,
81    symbol: Symbol,
82) -> impl IntoIterator<Item = Symbol> {
83    let mut res = Vec::new();
84
85    let Some(list) = args.list() else {
86        cx.emit_err(session_diagnostics::ExpectsFeatureList {
87            span: cx.attr_span,
88            name: symbol.to_ident_string(),
89        });
90        return res;
91    };
92
93    for param in list.mixed() {
94        let param_span = param.span();
95        if let Some(ident) = param.meta_item().and_then(|i| i.path().word()) {
96            res.push(ident.name);
97        } else {
98            cx.emit_err(session_diagnostics::ExpectsFeatures {
99                span: param_span,
100                name: symbol.to_ident_string(),
101            });
102        }
103    }
104
105    res
106}