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