rustc_attr_parsing/attributes/
unroll.rs1use 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}