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::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}