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