Skip to main content

rustc_attr_parsing/attributes/
allow_unstable.rs

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