rustc_attr_parsing/attributes/
inline.rs1use rustc_feature::AttributeStability;
6use rustc_hir::attrs::{AttributeKind, InlineAttr};
7use rustc_session::lint::builtin::ILL_FORMED_ATTRIBUTE_INPUT;
8
9use super::prelude::*;
10
11pub(crate) struct InlineParser;
12
13impl SingleAttributeParser for InlineParser {
14 const PATH: &[Symbol] = &[sym::inline];
15 const ON_DUPLICATE: OnDuplicate = OnDuplicate::WarnButFutureError;
16 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
17 Allow(Target::Fn),
18 Allow(Target::Method(MethodKind::Inherent)),
19 Allow(Target::Method(MethodKind::Trait { body: true })),
20 Allow(Target::Method(MethodKind::TraitImpl)),
21 Allow(Target::Closure),
22 Allow(Target::Delegation { mac: false }),
23 Warn(Target::Method(MethodKind::Trait { body: false })),
24 Warn(Target::ForeignFn),
25 Warn(Target::Field),
26 Warn(Target::MacroDef),
27 Warn(Target::Arm),
28 Warn(Target::AssocConst),
29 Warn(Target::MacroCall),
30 ]);
31 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: true,
list: Some(&["always", "never"]),
one_of: &[],
name_value_str: None,
docs: Some("https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute"),
}template!(
32 Word,
33 List: &["always", "never"],
34 "https://doc.rust-lang.org/reference/attributes/codegen.html#the-inline-attribute"
35 );
36 const STABILITY: AttributeStability = AttributeStability::Stable;
37
38 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
39 match args {
40 ArgParser::NoArgs => Some(AttributeKind::Inline(InlineAttr::Hint, cx.attr_span)),
41 ArgParser::List(list) => {
42 let l = cx.expect_single(list)?;
43
44 match l.meta_item_no_args().and_then(|i| i.path().word_sym()) {
45 Some(sym::always) => {
46 Some(AttributeKind::Inline(InlineAttr::Always, cx.attr_span))
47 }
48 Some(sym::never) => {
49 Some(AttributeKind::Inline(InlineAttr::Never, cx.attr_span))
50 }
51 _ => {
52 cx.adcx().expected_specific_argument(l.span(), &[sym::always, sym::never]);
53 return None;
54 }
55 }
56 }
57 ArgParser::NameValue(_) => {
58 cx.adcx().warn_ill_formed_attribute_input(ILL_FORMED_ATTRIBUTE_INPUT);
59 return None;
60 }
61 }
62 }
63}
64
65pub(crate) struct RustcForceInlineParser;
66
67impl SingleAttributeParser for RustcForceInlineParser {
68 const PATH: &[Symbol] = &[sym::rustc_force_inline];
69 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
70 Allow(Target::Fn),
71 Allow(Target::Method(MethodKind::Inherent)),
72 ]);
73 const STABILITY: AttributeStability =
74 AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &["`#[rustc_force_inline]` forces a free function to be inlined"],
}unstable!(rustc_attrs, "`#[rustc_force_inline]` forces a free function to be inlined");
75 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: true,
list: Some(&["reason"]),
one_of: &[],
name_value_str: Some(&["reason"]),
docs: None,
}template!(Word, List: &["reason"], NameValueStr: "reason");
76
77 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
78 let reason = match args {
79 ArgParser::NoArgs => None,
80 ArgParser::List(list) => {
81 let l = cx.expect_single(list)?;
82
83 let reason = cx.expect_string_literal(l)?;
84
85 Some(reason)
86 }
87 ArgParser::NameValue(v) => cx.expect_string_literal(v),
88 };
89
90 Some(AttributeKind::Inline(
91 InlineAttr::Force { attr_span: cx.attr_span, reason },
92 cx.attr_span,
93 ))
94 }
95}