rustc_attr_parsing/attributes/
macro_attrs.rs1use rustc_feature::AttributeStability;
2use rustc_hir::attrs::{CollapseMacroDebuginfo, MacroUseArgs};
3use rustc_hir::find_attr;
4use rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS;
5
6use super::prelude::*;
7use crate::session_diagnostics::MacroOnlyAttribute;
8
9pub(crate) struct MacroEscapeParser;
10impl NoArgsAttributeParser for MacroEscapeParser {
11 const PATH: &[Symbol] = &[sym::macro_escape];
12 const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
13 const ALLOWED_TARGETS: AllowedTargets<'_> = MACRO_USE_ALLOWED_TARGETS;
14 const STABILITY: AttributeStability = AttributeStability::Stable;
15 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::MacroEscape;
16}
17
18#[derive(#[automatically_derived]
impl ::core::default::Default for MacroUseParser {
#[inline]
fn default() -> MacroUseParser {
MacroUseParser {
state: ::core::default::Default::default(),
uses_attr_spans: ::core::default::Default::default(),
first_span: ::core::default::Default::default(),
}
}
}Default)]
23pub(crate) struct MacroUseParser {
24 state: MacroUseArgs,
25
26 uses_attr_spans: ThinVec<Span>,
28 first_span: Option<Span>,
31}
32
33const MACRO_USE_TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: true,
list: Some(&["name1, name2, ..."]),
one_of: &[],
name_value_str: None,
docs: Some("https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute"),
}template!(
34 Word, List: &["name1, name2, ..."],
35 "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute"
36);
37const MACRO_USE_ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[
38 Allow(Target::Mod),
39 Allow(Target::ExternCrate),
40 Error(Target::WherePredicate),
41]);
42
43impl AttributeParser for MacroUseParser {
44 const ATTRIBUTES: AcceptMapping<Self> = &[(
45 &[sym::macro_use],
46 MACRO_USE_TEMPLATE,
47 AttributeStability::Stable,
48 |group: &mut Self, cx: &mut AcceptContext<'_, '_>, args| {
49 let span = cx.attr_span;
50 group.first_span.get_or_insert(span);
51 match args {
52 ArgParser::NoArgs => {
53 match group.state {
54 MacroUseArgs::UseAll => {
55 let first_span = group.first_span.expect(
56 "State is UseAll is some so this is not the first attribute",
57 );
58 cx.warn_unused_duplicate(first_span, span);
60 }
61 MacroUseArgs::UseSpecific(_) => {
62 group.state = MacroUseArgs::UseAll;
63 group.first_span = Some(span);
64 for specific_use in group.uses_attr_spans.drain(..) {
66 cx.warn_unused_duplicate(span, specific_use);
67 }
68 }
69 }
70 }
71 ArgParser::List(list) => {
72 if list.is_empty() {
73 cx.adcx().warn_empty_attribute(list.span);
74 return;
75 }
76
77 match &mut group.state {
78 MacroUseArgs::UseAll => {
79 let first_span = group.first_span.expect(
80 "State is UseAll is some so this is not the first attribute",
81 );
82 cx.warn_unused_duplicate(first_span, span);
83 }
84 MacroUseArgs::UseSpecific(arguments) => {
85 group.uses_attr_spans.push(cx.attr_span);
87
88 for item in list.mixed() {
89 let Some(item) = item.meta_item() else {
90 cx.adcx().expected_identifier(item.span());
91 continue;
92 };
93 let Some(()) = cx.expect_no_args(item.args()) else {
94 continue;
95 };
96 let Some(item) = item.path().word() else {
97 cx.adcx().expected_identifier(item.span());
98 continue;
99 };
100 arguments.push(item);
101 }
102 }
103 }
104 }
105 ArgParser::NameValue(nv) => {
106 cx.adcx().expected_list_or_no_args(nv.args_span());
107 }
108 }
109 },
110 )];
111 const ALLOWED_TARGETS: AllowedTargets<'_> = MACRO_USE_ALLOWED_TARGETS;
112
113 fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {
114 Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
115 }
116}
117
118pub(crate) fn check_macro_only(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
122 if cx.target == Target::Fn
123 && !{
{
'done:
{
for i in cx.parsed_attrs {
#[allow(unused_imports)]
use ::rustc_hir::attrs::AttributeKind::*;
let i: &::rustc_hir::Attribute = i;
match i {
::rustc_hir::Attribute::Parsed(ProcMacro |
ProcMacroAttribute | ProcMacroDerive { .. }) => {
break 'done Some(());
}
::rustc_hir::Attribute::Unparsed(..) =>
{}
#[deny(unreachable_patterns)]
_ => {}
}
}
None
}
}.is_some()
}find_attr!(cx.parsed_attrs, ProcMacro | ProcMacroAttribute | ProcMacroDerive { .. })
124 {
125 cx.emit_err(MacroOnlyAttribute { attr_span, span: cx.target_span });
126 }
127}
128
129pub(crate) struct AllowInternalUnsafeParser;
130
131impl NoArgsAttributeParser for AllowInternalUnsafeParser {
132 const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
133 const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore;
134 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
135 Allow(Target::Fn),
136 Allow(Target::MacroDef),
137 Warn(Target::Field),
138 Warn(Target::Arm),
139 ]);
140 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::allow_internal_unsafe,
gate_check: rustc_feature::Features::allow_internal_unsafe,
notes: &[],
}unstable!(allow_internal_unsafe);
141 const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
142
143 fn finalize_check(cx: &FinalizeCheckContext<'_, '_>, attr_span: Span) {
144 check_macro_only(cx, attr_span);
145 }
146}
147
148pub(crate) struct MacroExportParser;
149
150impl SingleAttributeParser for MacroExportParser {
151 const PATH: &[Symbol] = &[sym::macro_export];
152 const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
153 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: true,
list: Some(&["local_inner_macros"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word, List: &["local_inner_macros"]);
154 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowListWarnRest(&[
155 Allow(Target::MacroDef),
156 Error(Target::WherePredicate),
157 Error(Target::Crate),
158 ]);
159 const STABILITY: AttributeStability = AttributeStability::Stable;
160
161 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
162 let local_inner_macros = match args {
163 ArgParser::NoArgs => false,
164 ArgParser::List(list) => {
165 let Some(l) = list.as_single() else {
166 cx.adcx().warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
167 return None;
168 };
169 if l.meta_item_no_args().is_some_and(|m| m.path().word_is(sym::local_inner_macros))
170 {
171 true
172 } else {
173 cx.adcx().warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
174 return None;
175 }
176 }
177 ArgParser::NameValue(nv) => {
178 cx.adcx().expected_list_or_no_args(nv.args_span());
179 return None;
180 }
181 };
182 Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros })
183 }
184}
185
186pub(crate) struct CollapseDebugInfoParser;
187
188impl SingleAttributeParser for CollapseDebugInfoParser {
189 const PATH: &[Symbol] = &[sym::collapse_debuginfo];
190 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&["no", "external", "yes"]),
one_of: &[],
name_value_str: None,
docs: Some("https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute"),
}template!(
191 List: &["no", "external", "yes"],
192 "https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute"
193 );
194 const ALLOWED_TARGETS: AllowedTargets<'_> =
195 AllowedTargets::AllowList(&[Allow(Target::MacroDef)]);
196 const STABILITY: AttributeStability = AttributeStability::Stable;
197
198 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
199 let single = cx.expect_single_element_list(args, cx.attr_span)?;
200 let Some(mi) = single.meta_item() else {
201 cx.adcx().expected_not_literal(single.span());
202 return None;
203 };
204 let _ = cx.expect_no_args(mi.args());
205 let path = mi.path().word_sym();
206 let info = match path {
207 Some(sym::yes) => CollapseMacroDebuginfo::Yes,
208 Some(sym::no) => CollapseMacroDebuginfo::No,
209 Some(sym::external) => CollapseMacroDebuginfo::External,
210 _ => {
211 cx.adcx()
212 .expected_specific_argument(mi.span(), &[sym::yes, sym::no, sym::external]);
213 return None;
214 }
215 };
216
217 Some(AttributeKind::CollapseDebugInfo(info))
218 }
219}
220
221pub(crate) struct RustcProcMacroDeclsParser;
222
223impl NoArgsAttributeParser for RustcProcMacroDeclsParser {
224 const PATH: &[Symbol] = &[sym::rustc_proc_macro_decls];
225 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Static)]);
226 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
227 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcProcMacroDecls;
228}