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