rustc_attr_parsing/attributes/
allow_unstable.rs1use 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}