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}