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