rustc_attr_parsing/attributes/
allow_unstable.rs
1use std::iter;
2
3use rustc_attr_data_structures::AttributeKind;
4use rustc_span::{Span, Symbol, sym};
5
6use super::{CombineAttributeParser, ConvertFn};
7use crate::context::AcceptContext;
8use crate::parser::ArgParser;
9use crate::session_diagnostics;
10
11pub(crate) struct AllowInternalUnstableParser;
12impl CombineAttributeParser for AllowInternalUnstableParser {
13 const PATH: &'static [rustc_span::Symbol] = &[sym::allow_internal_unstable];
14 type Item = (Symbol, Span);
15 const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowInternalUnstable;
16
17 fn extend<'a>(
18 cx: &'a AcceptContext<'a>,
19 args: &'a ArgParser<'a>,
20 ) -> impl IntoIterator<Item = Self::Item> + 'a {
21 parse_unstable(cx, args, Self::PATH[0]).into_iter().zip(iter::repeat(cx.attr_span))
22 }
23}
24
25pub(crate) struct AllowConstFnUnstableParser;
26impl CombineAttributeParser for AllowConstFnUnstableParser {
27 const PATH: &'static [rustc_span::Symbol] = &[sym::rustc_allow_const_fn_unstable];
28 type Item = Symbol;
29 const CONVERT: ConvertFn<Self::Item> = AttributeKind::AllowConstFnUnstable;
30
31 fn extend<'a>(
32 cx: &'a AcceptContext<'a>,
33 args: &'a ArgParser<'a>,
34 ) -> impl IntoIterator<Item = Self::Item> + 'a {
35 parse_unstable(cx, args, Self::PATH[0])
36 }
37}
38
39fn parse_unstable<'a>(
40 cx: &AcceptContext<'_>,
41 args: &'a ArgParser<'a>,
42 symbol: Symbol,
43) -> impl IntoIterator<Item = Symbol> {
44 let mut res = Vec::new();
45
46 let Some(list) = args.list() else {
47 cx.emit_err(session_diagnostics::ExpectsFeatureList {
48 span: cx.attr_span,
49 name: symbol.to_ident_string(),
50 });
51 return res;
52 };
53
54 for param in list.mixed() {
55 let param_span = param.span();
56 if let Some(ident) = param.meta_item().and_then(|i| i.word_without_args()) {
57 res.push(ident.name);
58 } else {
59 cx.emit_err(session_diagnostics::ExpectsFeatures {
60 span: param_span,
61 name: symbol.to_ident_string(),
62 });
63 }
64 }
65
66 res
67}