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