Skip to main content

rustc_attr_parsing/attributes/
unroll.rs

1use rustc_ast::{LitIntType, LitKind};
2use rustc_feature::AttributeStability;
3use rustc_hir::attrs::UnrollAttr;
4
5use super::prelude::*;
6
7pub(crate) struct UnrollParser;
8impl SingleAttributeParser for UnrollParser {
9    // FIXME(#159429): temporarily renamed to mitigate `#[unroll]` nameres ambiguity.
10    const PATH: &[Symbol] = &[sym::rustc_unroll];
11    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
12        Allow(Target::Loop),
13        Allow(Target::ForLoop),
14        Allow(Target::While),
15    ]);
16    const STABILITY: AttributeStability = AttributeStability::Unstable {
    gate_name: rustc_span::sym::loop_hints,
    gate_check: rustc_feature::Features::loop_hints,
    notes: &[],
}unstable!(loop_hints);
17    const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
    word: true,
    list: Some(&["full", "never", "<integer>"]),
    one_of: &[],
    name_value_str: None,
    docs: None,
}template!(
18        Word,
19        List: &["full", "never", "<integer>"]
20    );
21
22    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
23        match args {
24            ArgParser::NoArgs => Some(AttributeKind::Unroll(UnrollAttr::Hint)),
25            ArgParser::List(list) => {
26                let l = cx.expect_single(list)?;
27
28                if let Some(lit) = l.as_lit()
29                    && let LitKind::Int(val, LitIntType::Unsuffixed) = lit.kind
30                {
31                    if let Ok(val) = u32::try_from(val.get()) {
32                        return Some(AttributeKind::Unroll(UnrollAttr::Count(val)));
33                    } else {
34                        cx.adcx().expected_integer_literal_in_range(l.span(), 0, u32::MAX as isize);
35                        return None;
36                    }
37                }
38
39                match l.meta_item_no_args().and_then(|i| i.path().word_sym()) {
40                    Some(sym::full) => Some(AttributeKind::Unroll(UnrollAttr::Full)),
41                    Some(sym::never) => Some(AttributeKind::Unroll(UnrollAttr::Never)),
42                    _ => {
43                        cx.adcx().expected_specific_argument(l.span(), &[sym::full, sym::never]);
44                        None
45                    }
46                }
47            }
48            ArgParser::NameValue(_) => {
49                let inner_span = cx.inner_span;
50                cx.adcx().expected_list_or_no_args(inner_span);
51                None
52            }
53        }
54    }
55}