rustc_attr_parsing/attributes/
macro_attrs.rs1use rustc_feature::AttributeStability;
2use rustc_hir::attrs::{CollapseMacroDebuginfo, MacroUseArgs};
3use rustc_session::lint::builtin::INVALID_MACRO_EXPORT_ARGUMENTS;
4
5use super::prelude::*;
6
7pub(crate) struct MacroEscapeParser;
8impl NoArgsAttributeParser for MacroEscapeParser {
9 const PATH: &[Symbol] = &[sym::macro_escape];
10 const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
11 const ALLOWED_TARGETS: AllowedTargets = MACRO_USE_ALLOWED_TARGETS;
12 const STABILITY: AttributeStability = AttributeStability::Stable;
13 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::MacroEscape;
14}
15
16#[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)]
21pub(crate) struct MacroUseParser {
22 state: MacroUseArgs,
23
24 uses_attr_spans: ThinVec<Span>,
26 first_span: Option<Span>,
29}
30
31const 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!(
32 Word, List: &["name1, name2, ..."],
33 "https://doc.rust-lang.org/reference/macros-by-example.html#the-macro_use-attribute"
34);
35const MACRO_USE_ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
36 Allow(Target::Mod),
37 Allow(Target::ExternCrate),
38 Allow(Target::Crate),
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) struct AllowInternalUnsafeParser;
118
119impl NoArgsAttributeParser for AllowInternalUnsafeParser {
120 const PATH: &[Symbol] = &[sym::allow_internal_unsafe];
121 const ON_DUPLICATE: OnDuplicate = OnDuplicate::Ignore;
122 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
123 Allow(Target::Fn),
124 Allow(Target::MacroDef),
125 Warn(Target::Field),
126 Warn(Target::Arm),
127 ]);
128 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);
129 const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::AllowInternalUnsafe(span);
130}
131
132pub(crate) struct MacroExportParser;
133
134impl SingleAttributeParser for MacroExportParser {
135 const PATH: &[Symbol] = &[sym::macro_export];
136 const ON_DUPLICATE: OnDuplicate = OnDuplicate::Warn;
137 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"]);
138 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowListWarnRest(&[
139 Allow(Target::MacroDef),
140 Error(Target::WherePredicate),
141 Error(Target::Crate),
142 ]);
143 const STABILITY: AttributeStability = AttributeStability::Stable;
144
145 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
146 let local_inner_macros = match args {
147 ArgParser::NoArgs => false,
148 ArgParser::List(list) => {
149 let Some(l) = list.as_single() else {
150 cx.adcx().warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
151 return None;
152 };
153 match l.meta_item_no_args().and_then(|i| i.path().word_sym()) {
154 Some(sym::local_inner_macros) => true,
155 _ => {
156 cx.adcx().warn_ill_formed_attribute_input(INVALID_MACRO_EXPORT_ARGUMENTS);
157 return None;
158 }
159 }
160 }
161 ArgParser::NameValue(nv) => {
162 cx.adcx().expected_list_or_no_args(nv.args_span());
163 return None;
164 }
165 };
166 Some(AttributeKind::MacroExport { span: cx.attr_span, local_inner_macros })
167 }
168}
169
170pub(crate) struct CollapseDebugInfoParser;
171
172impl SingleAttributeParser for CollapseDebugInfoParser {
173 const PATH: &[Symbol] = &[sym::collapse_debuginfo];
174 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!(
175 List: &["no", "external", "yes"],
176 "https://doc.rust-lang.org/reference/attributes/debugger.html#the-collapse_debuginfo-attribute"
177 );
178 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::MacroDef)]);
179 const STABILITY: AttributeStability = AttributeStability::Stable;
180
181 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
182 let single = cx.expect_single_element_list(args, cx.attr_span)?;
183 let Some(mi) = single.meta_item() else {
184 cx.adcx().expected_not_literal(single.span());
185 return None;
186 };
187 let _ = cx.expect_no_args(mi.args());
188 let path = mi.path().word_sym();
189 let info = match path {
190 Some(sym::yes) => CollapseMacroDebuginfo::Yes,
191 Some(sym::no) => CollapseMacroDebuginfo::No,
192 Some(sym::external) => CollapseMacroDebuginfo::External,
193 _ => {
194 cx.adcx()
195 .expected_specific_argument(mi.span(), &[sym::yes, sym::no, sym::external]);
196 return None;
197 }
198 };
199
200 Some(AttributeKind::CollapseDebugInfo(info))
201 }
202}
203
204pub(crate) struct RustcProcMacroDeclsParser;
205
206impl NoArgsAttributeParser for RustcProcMacroDeclsParser {
207 const PATH: &[Symbol] = &[sym::rustc_proc_macro_decls];
208 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Static)]);
209 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
210 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcProcMacroDecls;
211}