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<S: Stage> NoArgsAttributeParser<S> for MacroEscapeParser {
8 const PATH: &[Symbol] = &[sym::macro_escape];
9 const ON_DUPLICATE: OnDuplicate<S> = 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<S: Stage> AttributeParser<S> for MacroUseParser {
41 const ATTRIBUTES: AcceptMapping<Self, S> = &[(
42 &[sym::macro_use],
43 MACRO_USE_TEMPLATE,
44 |group: &mut Self, cx: &mut AcceptContext<'_, '_, S>, 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.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.expected_identifier(item.span());
87 continue;
88 };
89 if let Err(err_span) = item.args().no_args() {
90 cx.expected_no_args(err_span);
91 continue;
92 }
93 let Some(item) = item.path().word() else {
94 cx.expected_identifier(item.span());
95 continue;
96 };
97 arguments.push(item);
98 }
99 }
100 }
101 }
102 ArgParser::NameValue(nv) => {
103 cx.expected_list_or_no_args(nv.args_span());
104 }
105 }
106 },
107 )];
108 const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS;
109
110 fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
111 Some(AttributeKind::MacroUse { span: self.first_span?, arguments: self.state })
112 }
113}
114
115pub(crate) struct AllowInternalUnsafeParser;
116
117impl<S: Stage> NoArgsAttributeParser<S> for AllowInternalUnsafeParser {
118 const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
119 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Ignore;
120 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
121 Allow(Target::Fn),
122 Allow(Target::MacroDef),
123 Warn(Target::Field),
124 Warn(Target::Arm),
125 ]);
126 const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
127}
128
129pub(crate) struct MacroExportParser;
130
131impl<S: Stage> SingleAttributeParser<S> for MacroExportParser {
132 const PATH: &[Symbol] = &[sym::macro_export];
133 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
134 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"]);
135 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
136 Allow(Target::MacroDef),
137 Error(Target::WherePredicate),
138 Error(Target::Crate),
139 ]);
140
141 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
142 let local_inner_macros = match args {
143 ArgParser::NoArgs => false,
144 ArgParser::List(list) => {
145 let Some(l) = list.single() else {
146 cx.warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
147 return None;
148 };
149 match l.meta_item().and_then(|i| i.path().word_sym()) {
150 Some(sym::local_inner_macros) => true,
151 _ => {
152 cx.warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
153 return None;
154 }
155 }
156 }
157 ArgParser::NameValue(nv) => {
158 cx.expected_list_or_no_args(nv.args_span());
159 return None;
160 }
161 };
162 Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros })
163 }
164}
165
166pub(crate) struct CollapseDebugInfoParser;
167
168impl<S: Stage> SingleAttributeParser<S> for CollapseDebugInfoParser {
169 const PATH: &[Symbol] = &[sym::collapse_debuginfo];
170 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
171 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!(
172 List: &["no", "external", "yes"],
173 "https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute"
174 );
175 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]);
176
177 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
178 let Some(list) = args.list() else {
179 cx.expected_list(cx.attr_span, args);
180 return None;
181 };
182 let Some(single) = list.single() else {
183 cx.expected_single_argument(list.span);
184 return None;
185 };
186 let Some(mi) = single.meta_item() else {
187 cx.unexpected_literal(single.span());
188 return None;
189 };
190 if let Err(err) = mi.args().no_args() {
191 cx.expected_no_args(err);
192 }
193 let path = mi.path().word_sym();
194 let info = match path {
195 Some(sym::yes) => CollapseMacroDebuginfo::Yes,
196 Some(sym::no) => CollapseMacroDebuginfo::No,
197 Some(sym::external) => CollapseMacroDebuginfo::External,
198 _ => {
199 cx.expected_specific_argument(mi.span(), &[sym::yes, sym::no, sym::external]);
200 return None;
201 }
202 };
203
204 Some(AttributeKind::CollapseDebugInfo(info))
205 }
206}
207
208pub(crate) struct RustcProcMacroDeclsParser;
209
210impl<S: Stage> NoArgsAttributeParser<S> for RustcProcMacroDeclsParser {
211 const PATH: &[Symbol] = &[sym::rustc_proc_macro_decls];
212 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
213 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]);
214 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcProcMacroDecls;
215}