1use std::path::PathBuf;
2
3use rustc_ast::{LitIntType, LitKind, MetaItemLit};
4use rustc_hir::LangItem;
5use rustc_hir::attrs::{
6 BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior,
7 DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcMirKind,
8};
9use rustc_session::errors;
10use rustc_span::Symbol;
11
12use super::prelude::*;
13use super::util::parse_single_integer;
14use crate::session_diagnostics::{
15 AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange, UnknownLangItem,
16};
17
18pub(crate) struct RustcMainParser;
19
20impl<S: Stage> NoArgsAttributeParser<S> for RustcMainParser {
21 const PATH: &[Symbol] = &[sym::rustc_main];
22 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
23 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
24 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain;
25}
26
27pub(crate) struct RustcMustImplementOneOfParser;
28
29impl<S: Stage> SingleAttributeParser<S> for RustcMustImplementOneOfParser {
30 const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of];
31 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
32 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
33 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&["function1, function2, ..."]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["function1, function2, ..."]);
34 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
35 let Some(list) = args.list() else {
36 let span = cx.attr_span;
37 cx.adcx().expected_list(span, args);
38 return None;
39 };
40
41 let mut fn_names = ThinVec::new();
42
43 let inputs: Vec<_> = list.mixed().collect();
44
45 if inputs.len() < 2 {
46 cx.adcx().expected_list_with_num_args_or_more(2, list.span);
47 return None;
48 }
49
50 let mut errored = false;
51 for argument in inputs {
52 let Some(meta) = argument.meta_item() else {
53 cx.adcx().expected_identifier(argument.span());
54 return None;
55 };
56
57 let Some(ident) = meta.ident() else {
58 cx.dcx().emit_err(errors::MustBeNameOfAssociatedFunction { span: meta.span() });
59 errored = true;
60 continue;
61 };
62
63 fn_names.push(ident);
64 }
65 if errored {
66 return None;
67 }
68
69 Some(AttributeKind::RustcMustImplementOneOf { attr_span: cx.attr_span, fn_names })
70 }
71}
72
73pub(crate) struct RustcNeverReturnsNullPtrParser;
74
75impl<S: Stage> NoArgsAttributeParser<S> for RustcNeverReturnsNullPtrParser {
76 const PATH: &[Symbol] = &[sym::rustc_never_returns_null_ptr];
77 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
78 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
79 Allow(Target::Fn),
80 Allow(Target::Method(MethodKind::Inherent)),
81 Allow(Target::Method(MethodKind::Trait { body: false })),
82 Allow(Target::Method(MethodKind::Trait { body: true })),
83 Allow(Target::Method(MethodKind::TraitImpl)),
84 ]);
85 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPtr;
86}
87pub(crate) struct RustcNoImplicitAutorefsParser;
88
89impl<S: Stage> NoArgsAttributeParser<S> for RustcNoImplicitAutorefsParser {
90 const PATH: &[Symbol] = &[sym::rustc_no_implicit_autorefs];
91 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
92 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
93 Allow(Target::Fn),
94 Allow(Target::Method(MethodKind::Inherent)),
95 Allow(Target::Method(MethodKind::Trait { body: false })),
96 Allow(Target::Method(MethodKind::Trait { body: true })),
97 Allow(Target::Method(MethodKind::TraitImpl)),
98 ]);
99
100 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs;
101}
102
103pub(crate) struct RustcLayoutScalarValidRangeStartParser;
104
105impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeStartParser {
106 const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_start];
107 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
108 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
109 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&["start"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["start"]);
110
111 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
112 parse_single_integer(cx, args)
113 .map(|n| AttributeKind::RustcLayoutScalarValidRangeStart(Box::new(n), cx.attr_span))
114 }
115}
116
117pub(crate) struct RustcLayoutScalarValidRangeEndParser;
118
119impl<S: Stage> SingleAttributeParser<S> for RustcLayoutScalarValidRangeEndParser {
120 const PATH: &[Symbol] = &[sym::rustc_layout_scalar_valid_range_end];
121 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
122 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
123 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&["end"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["end"]);
124
125 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
126 parse_single_integer(cx, args)
127 .map(|n| AttributeKind::RustcLayoutScalarValidRangeEnd(Box::new(n), cx.attr_span))
128 }
129}
130
131pub(crate) struct RustcLegacyConstGenericsParser;
132
133impl<S: Stage> SingleAttributeParser<S> for RustcLegacyConstGenericsParser {
134 const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics];
135 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
136 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
137 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&["N"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["N"]);
138
139 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
140 let ArgParser::List(meta_items) = args else {
141 let attr_span = cx.attr_span;
142 cx.adcx().expected_list(attr_span, args);
143 return None;
144 };
145
146 let mut parsed_indexes = ThinVec::new();
147 let mut errored = false;
148
149 for possible_index in meta_items.mixed() {
150 if let MetaItemOrLitParser::Lit(MetaItemLit {
151 kind: LitKind::Int(index, LitIntType::Unsuffixed),
152 ..
153 }) = possible_index
154 {
155 parsed_indexes.push((index.0 as usize, possible_index.span()));
156 } else {
157 cx.adcx().expected_integer_literal(possible_index.span());
158 errored = true;
159 }
160 }
161 if errored {
162 return None;
163 } else if parsed_indexes.is_empty() {
164 cx.adcx().expected_at_least_one_argument(args.span()?);
165 return None;
166 }
167
168 Some(AttributeKind::RustcLegacyConstGenerics {
169 fn_indexes: parsed_indexes,
170 attr_span: cx.attr_span,
171 })
172 }
173}
174
175pub(crate) struct RustcInheritOverflowChecksParser;
176
177impl<S: Stage> NoArgsAttributeParser<S> for RustcInheritOverflowChecksParser {
178 const PATH: &[Symbol] = &[sym::rustc_inherit_overflow_checks];
179 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
180 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
181 Allow(Target::Fn),
182 Allow(Target::Method(MethodKind::Inherent)),
183 Allow(Target::Method(MethodKind::TraitImpl)),
184 Allow(Target::Closure),
185 ]);
186 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInheritOverflowChecks;
187}
188
189pub(crate) struct RustcLintOptDenyFieldAccessParser;
190
191impl<S: Stage> SingleAttributeParser<S> for RustcLintOptDenyFieldAccessParser {
192 const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access];
193 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
194 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Field)]);
195 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: true,
list: None,
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word);
196 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
197 let Some(arg) = args.list().and_then(MetaItemListParser::single) else {
198 let attr_span = cx.attr_span;
199 cx.adcx().expected_single_argument(attr_span);
200 return None;
201 };
202
203 let MetaItemOrLitParser::Lit(MetaItemLit { kind: LitKind::Str(lint_message, _), .. }) = arg
204 else {
205 cx.adcx().expected_string_literal(arg.span(), arg.lit());
206 return None;
207 };
208
209 Some(AttributeKind::RustcLintOptDenyFieldAccess { lint_message: *lint_message })
210 }
211}
212
213pub(crate) struct RustcLintOptTyParser;
214
215impl<S: Stage> NoArgsAttributeParser<S> for RustcLintOptTyParser {
216 const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty];
217 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
218 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
219 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy;
220}
221
222fn parse_cgu_fields<S: Stage>(
223 cx: &mut AcceptContext<'_, '_, S>,
224 args: &ArgParser,
225 accepts_kind: bool,
226) -> Option<(Symbol, Symbol, Option<CguKind>)> {
227 let Some(args) = args.list() else {
228 let attr_span = cx.attr_span;
229 cx.adcx().expected_list(attr_span, args);
230 return None;
231 };
232
233 let mut cfg = None::<(Symbol, Span)>;
234 let mut module = None::<(Symbol, Span)>;
235 let mut kind = None::<(Symbol, Span)>;
236
237 for arg in args.mixed() {
238 let Some(arg) = arg.meta_item() else {
239 cx.adcx().expected_name_value(args.span, None);
240 continue;
241 };
242
243 let res = match arg.ident().map(|i| i.name) {
244 Some(sym::cfg) => &mut cfg,
245 Some(sym::module) => &mut module,
246 Some(sym::kind) if accepts_kind => &mut kind,
247 _ => {
248 cx.adcx().expected_specific_argument(
249 arg.path().span(),
250 if accepts_kind {
251 &[sym::cfg, sym::module, sym::kind]
252 } else {
253 &[sym::cfg, sym::module]
254 },
255 );
256 continue;
257 }
258 };
259
260 let Some(i) = arg.args().name_value() else {
261 cx.adcx().expected_name_value(arg.span(), None);
262 continue;
263 };
264
265 let Some(str) = i.value_as_str() else {
266 cx.adcx().expected_string_literal(i.value_span, Some(i.value_as_lit()));
267 continue;
268 };
269
270 if res.is_some() {
271 cx.adcx().duplicate_key(arg.span(), arg.ident().unwrap().name);
272 continue;
273 }
274
275 *res = Some((str, i.value_span));
276 }
277
278 let Some((cfg, _)) = cfg else {
279 cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::cfg });
280 return None;
281 };
282 let Some((module, _)) = module else {
283 cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::module });
284 return None;
285 };
286 let kind = if let Some((kind, span)) = kind {
287 Some(match kind {
288 sym::no => CguKind::No,
289 sym::pre_dash_lto => CguKind::PreDashLto,
290 sym::post_dash_lto => CguKind::PostDashLto,
291 sym::any => CguKind::Any,
292 _ => {
293 cx.adcx().expected_specific_argument_strings(
294 span,
295 &[sym::no, sym::pre_dash_lto, sym::post_dash_lto, sym::any],
296 );
297 return None;
298 }
299 })
300 } else {
301 if accepts_kind {
303 cx.emit_err(CguFieldsMissing {
304 span: args.span,
305 name: &cx.attr_path,
306 field: sym::kind,
307 });
308 return None;
309 };
310
311 None
312 };
313
314 Some((cfg, module, kind))
315}
316
317#[derive(#[automatically_derived]
impl ::core::default::Default for RustcCguTestAttributeParser {
#[inline]
fn default() -> RustcCguTestAttributeParser {
RustcCguTestAttributeParser {
items: ::core::default::Default::default(),
}
}
}Default)]
318pub(crate) struct RustcCguTestAttributeParser {
319 items: ThinVec<(Span, CguFields)>,
320}
321
322impl<S: Stage> AttributeParser<S> for RustcCguTestAttributeParser {
323 const ATTRIBUTES: AcceptMapping<Self, S> = &[
324 (
325 &[sym::rustc_partition_reused],
326 ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&[r#"cfg = "...", module = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"cfg = "...", module = "...""#]),
327 |this, cx, args| {
328 this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| {
329 (cx.attr_span, CguFields::PartitionReused { cfg, module })
330 }));
331 },
332 ),
333 (
334 &[sym::rustc_partition_codegened],
335 ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&[r#"cfg = "...", module = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"cfg = "...", module = "...""#]),
336 |this, cx, args| {
337 this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| {
338 (cx.attr_span, CguFields::PartitionCodegened { cfg, module })
339 }));
340 },
341 ),
342 (
343 &[sym::rustc_expected_cgu_reuse],
344 ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&[r#"cfg = "...", module = "...", kind = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]),
345 |this, cx, args| {
346 this.items.extend(parse_cgu_fields(cx, args, true).map(|(cfg, module, kind)| {
347 (cx.attr_span, CguFields::ExpectedCguReuse { cfg, module, kind: kind.unwrap() })
349 }));
350 },
351 ),
352 ];
353
354 const ALLOWED_TARGETS: AllowedTargets =
355 AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]);
356
357 fn finalize(self, _cx: &FinalizeContext<'_, '_, S>) -> Option<AttributeKind> {
358 Some(AttributeKind::RustcCguTestAttr(self.items))
359 }
360}
361
362pub(crate) struct RustcDeprecatedSafe2024Parser;
363
364impl<S: Stage> SingleAttributeParser<S> for RustcDeprecatedSafe2024Parser {
365 const PATH: &[Symbol] = &[sym::rustc_deprecated_safe_2024];
366 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
367 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
368 Allow(Target::Fn),
369 Allow(Target::Method(MethodKind::Inherent)),
370 Allow(Target::Method(MethodKind::Trait { body: false })),
371 Allow(Target::Method(MethodKind::Trait { body: true })),
372 Allow(Target::Method(MethodKind::TraitImpl)),
373 ]);
374 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&[r#"audit_that = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"audit_that = "...""#]);
375
376 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
377 let Some(args) = args.list() else {
378 let attr_span = cx.attr_span;
379 cx.adcx().expected_list(attr_span, args);
380 return None;
381 };
382
383 let Some(single) = args.single() else {
384 cx.adcx().expected_single_argument(args.span);
385 return None;
386 };
387
388 let Some(arg) = single.meta_item() else {
389 cx.adcx().expected_name_value(args.span, None);
390 return None;
391 };
392
393 let Some(args) = arg.word_is(sym::audit_that) else {
394 cx.adcx().expected_specific_argument(arg.span(), &[sym::audit_that]);
395 return None;
396 };
397
398 let Some(nv) = args.name_value() else {
399 cx.adcx().expected_name_value(arg.span(), Some(sym::audit_that));
400 return None;
401 };
402
403 let Some(suggestion) = nv.value_as_str() else {
404 cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
405 return None;
406 };
407
408 Some(AttributeKind::RustcDeprecatedSafe2024 { suggestion })
409 }
410}
411
412pub(crate) struct RustcConversionSuggestionParser;
413
414impl<S: Stage> NoArgsAttributeParser<S> for RustcConversionSuggestionParser {
415 const PATH: &[Symbol] = &[sym::rustc_conversion_suggestion];
416 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
417 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
418 Allow(Target::Fn),
419 Allow(Target::Method(MethodKind::Inherent)),
420 Allow(Target::Method(MethodKind::Trait { body: false })),
421 Allow(Target::Method(MethodKind::Trait { body: true })),
422 Allow(Target::Method(MethodKind::TraitImpl)),
423 ]);
424 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConversionSuggestion;
425}
426
427pub(crate) struct RustcCaptureAnalysisParser;
428
429impl<S: Stage> NoArgsAttributeParser<S> for RustcCaptureAnalysisParser {
430 const PATH: &[Symbol] = &[sym::rustc_capture_analysis];
431 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
432 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Closure)]);
433 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis;
434}
435
436pub(crate) struct RustcNeverTypeOptionsParser;
437
438impl<S: Stage> SingleAttributeParser<S> for RustcNeverTypeOptionsParser {
439 const PATH: &[Symbol] = &[sym::rustc_never_type_options];
440 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
441 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Crate)]);
442 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&[r#"fallback = "unit", "never", "no""#,
r#"diverging_block_default = "unit", "never""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[
443 r#"fallback = "unit", "never", "no""#,
444 r#"diverging_block_default = "unit", "never""#,
445 ]);
446
447 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
448 let Some(list) = args.list() else {
449 let attr_span = cx.attr_span;
450 cx.adcx().expected_list(attr_span, args);
451 return None;
452 };
453
454 let mut fallback = None::<Ident>;
455 let mut diverging_block_default = None::<Ident>;
456
457 for arg in list.mixed() {
458 let Some(meta) = arg.meta_item() else {
459 cx.adcx().expected_name_value(arg.span(), None);
460 continue;
461 };
462
463 let res = match meta.ident().map(|i| i.name) {
464 Some(sym::fallback) => &mut fallback,
465 Some(sym::diverging_block_default) => &mut diverging_block_default,
466 _ => {
467 cx.adcx().expected_specific_argument(
468 meta.path().span(),
469 &[sym::fallback, sym::diverging_block_default],
470 );
471 continue;
472 }
473 };
474
475 let Some(nv) = meta.args().name_value() else {
476 cx.adcx().expected_name_value(meta.span(), None);
477 continue;
478 };
479
480 let Some(field) = nv.value_as_str() else {
481 cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
482 continue;
483 };
484
485 if res.is_some() {
486 cx.adcx().duplicate_key(meta.span(), meta.ident().unwrap().name);
487 continue;
488 }
489
490 *res = Some(Ident { name: field, span: nv.value_span });
491 }
492
493 let fallback = match fallback {
494 None => None,
495 Some(Ident { name: sym::unit, .. }) => Some(DivergingFallbackBehavior::ToUnit),
496 Some(Ident { name: sym::never, .. }) => Some(DivergingFallbackBehavior::ToNever),
497 Some(Ident { name: sym::no, .. }) => Some(DivergingFallbackBehavior::NoFallback),
498 Some(Ident { span, .. }) => {
499 cx.adcx()
500 .expected_specific_argument_strings(span, &[sym::unit, sym::never, sym::no]);
501 return None;
502 }
503 };
504
505 let diverging_block_default = match diverging_block_default {
506 None => None,
507 Some(Ident { name: sym::unit, .. }) => Some(DivergingBlockBehavior::Unit),
508 Some(Ident { name: sym::never, .. }) => Some(DivergingBlockBehavior::Never),
509 Some(Ident { span, .. }) => {
510 cx.adcx().expected_specific_argument_strings(span, &[sym::unit, sym::no]);
511 return None;
512 }
513 };
514
515 Some(AttributeKind::RustcNeverTypeOptions { fallback, diverging_block_default })
516 }
517}
518
519pub(crate) struct RustcTrivialFieldReadsParser;
520
521impl<S: Stage> NoArgsAttributeParser<S> for RustcTrivialFieldReadsParser {
522 const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads];
523 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
524 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Trait)]);
525 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads;
526}
527
528pub(crate) struct RustcNoMirInlineParser;
529
530impl<S: Stage> NoArgsAttributeParser<S> for RustcNoMirInlineParser {
531 const PATH: &[Symbol] = &[sym::rustc_no_mir_inline];
532 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
533 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
534 Allow(Target::Fn),
535 Allow(Target::Method(MethodKind::Inherent)),
536 Allow(Target::Method(MethodKind::Trait { body: false })),
537 Allow(Target::Method(MethodKind::Trait { body: true })),
538 Allow(Target::Method(MethodKind::TraitImpl)),
539 ]);
540 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline;
541}
542
543pub(crate) struct RustcLintQueryInstabilityParser;
544
545impl<S: Stage> NoArgsAttributeParser<S> for RustcLintQueryInstabilityParser {
546 const PATH: &[Symbol] = &[sym::rustc_lint_query_instability];
547 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
548 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
549 Allow(Target::Fn),
550 Allow(Target::Method(MethodKind::Inherent)),
551 Allow(Target::Method(MethodKind::Trait { body: false })),
552 Allow(Target::Method(MethodKind::Trait { body: true })),
553 Allow(Target::Method(MethodKind::TraitImpl)),
554 ]);
555 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability;
556}
557
558pub(crate) struct RustcRegionsParser;
559
560impl<S: Stage> NoArgsAttributeParser<S> for RustcRegionsParser {
561 const PATH: &[Symbol] = &[sym::rustc_regions];
562 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
563 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
564 Allow(Target::Fn),
565 Allow(Target::Method(MethodKind::Inherent)),
566 Allow(Target::Method(MethodKind::Trait { body: false })),
567 Allow(Target::Method(MethodKind::Trait { body: true })),
568 Allow(Target::Method(MethodKind::TraitImpl)),
569 ]);
570
571 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcRegions;
572}
573
574pub(crate) struct RustcLintUntrackedQueryInformationParser;
575
576impl<S: Stage> NoArgsAttributeParser<S> for RustcLintUntrackedQueryInformationParser {
577 const PATH: &[Symbol] = &[sym::rustc_lint_untracked_query_information];
578 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
579 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
580 Allow(Target::Fn),
581 Allow(Target::Method(MethodKind::Inherent)),
582 Allow(Target::Method(MethodKind::Trait { body: false })),
583 Allow(Target::Method(MethodKind::Trait { body: true })),
584 Allow(Target::Method(MethodKind::TraitImpl)),
585 ]);
586
587 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation;
588}
589
590pub(crate) struct RustcSimdMonomorphizeLaneLimitParser;
591
592impl<S: Stage> SingleAttributeParser<S> for RustcSimdMonomorphizeLaneLimitParser {
593 const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit];
594 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
595 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
596 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["N"]),
docs: None,
}template!(NameValueStr: "N");
597
598 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
599 let ArgParser::NameValue(nv) = args else {
600 let attr_span = cx.attr_span;
601 cx.adcx().expected_name_value(attr_span, None);
602 return None;
603 };
604 Some(AttributeKind::RustcSimdMonomorphizeLaneLimit(cx.parse_limit_int(nv)?))
605 }
606}
607
608pub(crate) struct RustcScalableVectorParser;
609
610impl<S: Stage> SingleAttributeParser<S> for RustcScalableVectorParser {
611 const PATH: &[Symbol] = &[sym::rustc_scalable_vector];
612 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
613 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
614 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: true,
list: Some(&["count"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word, List: &["count"]);
615
616 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
617 if args.no_args().is_ok() {
618 return Some(AttributeKind::RustcScalableVector {
619 element_count: None,
620 span: cx.attr_span,
621 });
622 }
623
624 let n = parse_single_integer(cx, args)?;
625 let Ok(n) = n.try_into() else {
626 cx.emit_err(RustcScalableVectorCountOutOfRange { span: cx.attr_span, n });
627 return None;
628 };
629 Some(AttributeKind::RustcScalableVector { element_count: Some(n), span: cx.attr_span })
630 }
631}
632
633pub(crate) struct LangParser;
634
635impl<S: Stage> SingleAttributeParser<S> for LangParser {
636 const PATH: &[Symbol] = &[sym::lang];
637 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
638 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["name"]),
docs: None,
}template!(NameValueStr: "name");
640
641 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
642 let Some(nv) = args.name_value() else {
643 let attr_span = cx.attr_span;
644 cx.adcx().expected_name_value(attr_span, None);
645 return None;
646 };
647 let Some(name) = nv.value_as_str() else {
648 cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
649 return None;
650 };
651 let Some(lang_item) = LangItem::from_name(name) else {
652 cx.emit_err(UnknownLangItem { span: cx.attr_span, name });
653 return None;
654 };
655 Some(AttributeKind::Lang(lang_item, cx.attr_span))
656 }
657}
658
659pub(crate) struct RustcHasIncoherentInherentImplsParser;
660
661impl<S: Stage> NoArgsAttributeParser<S> for RustcHasIncoherentInherentImplsParser {
662 const PATH: &[Symbol] = &[sym::rustc_has_incoherent_inherent_impls];
663 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
664 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
665 Allow(Target::Trait),
666 Allow(Target::Struct),
667 Allow(Target::Enum),
668 Allow(Target::Union),
669 Allow(Target::ForeignTy),
670 ]);
671 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;
672}
673
674pub(crate) struct PanicHandlerParser;
675
676impl<S: Stage> NoArgsAttributeParser<S> for PanicHandlerParser {
677 const PATH: &[Symbol] = &[sym::panic_handler];
678 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
679 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(ALL_TARGETS); const CREATE: fn(Span) -> AttributeKind = |span| AttributeKind::Lang(LangItem::PanicImpl, span);
681}
682
683pub(crate) struct RustcNounwindParser;
684
685impl<S: Stage> NoArgsAttributeParser<S> for RustcNounwindParser {
686 const PATH: &[Symbol] = &[sym::rustc_nounwind];
687 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
688 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
689 Allow(Target::Fn),
690 Allow(Target::ForeignFn),
691 Allow(Target::Method(MethodKind::Inherent)),
692 Allow(Target::Method(MethodKind::TraitImpl)),
693 Allow(Target::Method(MethodKind::Trait { body: true })),
694 ]);
695 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNounwind;
696}
697
698pub(crate) struct RustcOffloadKernelParser;
699
700impl<S: Stage> NoArgsAttributeParser<S> for RustcOffloadKernelParser {
701 const PATH: &[Symbol] = &[sym::rustc_offload_kernel];
702 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
703 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
704 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;
705}
706
707pub(crate) struct RustcMirParser;
708
709impl<S: Stage> CombineAttributeParser<S> for RustcMirParser {
710 const PATH: &[Symbol] = &[sym::rustc_mir];
711
712 type Item = RustcMirKind;
713
714 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcMir(items);
715
716 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
717 Allow(Target::Fn),
718 Allow(Target::Method(MethodKind::Inherent)),
719 Allow(Target::Method(MethodKind::TraitImpl)),
720 Allow(Target::Method(MethodKind::Trait { body: false })),
721 Allow(Target::Method(MethodKind::Trait { body: true })),
722 ]);
723
724 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&["arg1, arg2, ..."]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["arg1, arg2, ..."]);
725
726 fn extend(
727 cx: &mut AcceptContext<'_, '_, S>,
728 args: &ArgParser,
729 ) -> impl IntoIterator<Item = Self::Item> {
730 let Some(list) = args.list() else {
731 let attr_span = cx.attr_span;
732 cx.adcx().expected_list(attr_span, args);
733 return ThinVec::new();
734 };
735
736 list.mixed()
737 .filter_map(|arg| arg.meta_item())
738 .filter_map(|mi| {
739 if let Some(ident) = mi.ident() {
740 match ident.name {
741 sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit),
742 sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit),
743 sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness),
744 sym::stop_after_dataflow => Some(RustcMirKind::StopAfterDataflow),
745 sym::borrowck_graphviz_postflow => {
746 let Some(nv) = mi.args().name_value() else {
747 cx.adcx().expected_name_value(
748 mi.span(),
749 Some(sym::borrowck_graphviz_postflow),
750 );
751 return None;
752 };
753 let Some(path) = nv.value_as_str() else {
754 cx.adcx().expected_string_literal(nv.value_span, None);
755 return None;
756 };
757 let path = PathBuf::from(path.to_string());
758 if path.file_name().is_some() {
759 Some(RustcMirKind::BorrowckGraphvizPostflow { path })
760 } else {
761 cx.adcx().expected_filename_literal(nv.value_span);
762 None
763 }
764 }
765 sym::borrowck_graphviz_format => {
766 let Some(nv) = mi.args().name_value() else {
767 cx.adcx().expected_name_value(
768 mi.span(),
769 Some(sym::borrowck_graphviz_format),
770 );
771 return None;
772 };
773 let Some(format) = nv.value_as_ident() else {
774 cx.adcx().expected_identifier(nv.value_span);
775 return None;
776 };
777 match format.name {
778 sym::two_phase => Some(RustcMirKind::BorrowckGraphvizFormat {
779 format: BorrowckGraphvizFormatKind::TwoPhase,
780 }),
781 _ => {
782 cx.adcx()
783 .expected_specific_argument(format.span, &[sym::two_phase]);
784 None
785 }
786 }
787 }
788 _ => None,
789 }
790 } else {
791 None
792 }
793 })
794 .collect()
795 }
796}
797pub(crate) struct RustcNonConstTraitMethodParser;
798
799impl<S: Stage> NoArgsAttributeParser<S> for RustcNonConstTraitMethodParser {
800 const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method];
801 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
802 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
803 Allow(Target::Method(MethodKind::Trait { body: true })),
804 Allow(Target::Method(MethodKind::Trait { body: false })),
805 ]);
806 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod;
807}
808
809pub(crate) struct RustcCleanParser;
810
811impl<S: Stage> CombineAttributeParser<S> for RustcCleanParser {
812 const PATH: &[Symbol] = &[sym::rustc_clean];
813
814 type Item = RustcCleanAttribute;
815
816 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcClean(items);
817
818 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
819 Allow(Target::AssocConst),
821 Allow(Target::AssocTy),
822 Allow(Target::Const),
823 Allow(Target::Enum),
824 Allow(Target::Expression),
825 Allow(Target::Field),
826 Allow(Target::Fn),
827 Allow(Target::ForeignMod),
828 Allow(Target::Impl { of_trait: false }),
829 Allow(Target::Impl { of_trait: true }),
830 Allow(Target::Method(MethodKind::Inherent)),
831 Allow(Target::Method(MethodKind::Trait { body: false })),
832 Allow(Target::Method(MethodKind::Trait { body: true })),
833 Allow(Target::Method(MethodKind::TraitImpl)),
834 Allow(Target::Mod),
835 Allow(Target::Static),
836 Allow(Target::Struct),
837 Allow(Target::Trait),
838 Allow(Target::TyAlias),
839 Allow(Target::Union),
840 ]);
842
843 const TEMPLATE: AttributeTemplate =
844 ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]);
845
846 fn extend(
847 cx: &mut AcceptContext<'_, '_, S>,
848 args: &ArgParser,
849 ) -> impl IntoIterator<Item = Self::Item> {
850 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
851 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
852 }
853 let Some(list) = args.list() else {
854 let attr_span = cx.attr_span;
855 cx.adcx().expected_list(attr_span, args);
856 return None;
857 };
858 let mut except = None;
859 let mut loaded_from_disk = None;
860 let mut cfg = None;
861
862 for item in list.mixed() {
863 let Some((value, name)) =
864 item.meta_item().and_then(|m| Option::zip(m.args().name_value(), m.ident()))
865 else {
866 cx.adcx().expected_name_value(item.span(), None);
867 continue;
868 };
869 let value_span = value.value_span;
870 let Some(value) = value.value_as_str() else {
871 cx.adcx().expected_string_literal(value_span, None);
872 continue;
873 };
874 match name.name {
875 sym::cfg if cfg.is_some() => {
876 cx.adcx().duplicate_key(item.span(), sym::cfg);
877 }
878
879 sym::cfg => {
880 cfg = Some(value);
881 }
882 sym::except if except.is_some() => {
883 cx.adcx().duplicate_key(item.span(), sym::except);
884 }
885 sym::except => {
886 let entries =
887 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();
888 except = Some(RustcCleanQueries { entries, span: value_span });
889 }
890 sym::loaded_from_disk if loaded_from_disk.is_some() => {
891 cx.adcx().duplicate_key(item.span(), sym::loaded_from_disk);
892 }
893 sym::loaded_from_disk => {
894 let entries =
895 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();
896 loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span });
897 }
898 _ => {
899 cx.adcx().expected_specific_argument(
900 name.span,
901 &[sym::cfg, sym::except, sym::loaded_from_disk],
902 );
903 }
904 }
905 }
906 let Some(cfg) = cfg else {
907 cx.adcx().expected_specific_argument(list.span, &[sym::cfg]);
908 return None;
909 };
910
911 Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk })
912 }
913}
914
915pub(crate) struct RustcIfThisChangedParser;
916
917impl<S: Stage> SingleAttributeParser<S> for RustcIfThisChangedParser {
918 const PATH: &[Symbol] = &[sym::rustc_if_this_changed];
919
920 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
921
922 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
923 Allow(Target::AssocConst),
925 Allow(Target::AssocTy),
926 Allow(Target::Const),
927 Allow(Target::Enum),
928 Allow(Target::Expression),
929 Allow(Target::Field),
930 Allow(Target::Fn),
931 Allow(Target::ForeignMod),
932 Allow(Target::Impl { of_trait: false }),
933 Allow(Target::Impl { of_trait: true }),
934 Allow(Target::Method(MethodKind::Inherent)),
935 Allow(Target::Method(MethodKind::Trait { body: false })),
936 Allow(Target::Method(MethodKind::Trait { body: true })),
937 Allow(Target::Method(MethodKind::TraitImpl)),
938 Allow(Target::Mod),
939 Allow(Target::Static),
940 Allow(Target::Struct),
941 Allow(Target::Trait),
942 Allow(Target::TyAlias),
943 Allow(Target::Union),
944 ]);
946
947 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: true,
list: Some(&["DepNode"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word, List: &["DepNode"]);
948
949 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
950 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
951 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
952 }
953 match args {
954 ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),
955 ArgParser::List(list) => {
956 let Some(item) = list.single() else {
957 let attr_span = cx.attr_span;
958 cx.adcx().expected_single_argument(attr_span);
959 return None;
960 };
961 let Some(ident) = item.meta_item().and_then(|item| item.ident()) else {
962 cx.adcx().expected_identifier(item.span());
963 return None;
964 };
965 Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name)))
966 }
967 ArgParser::NameValue(_) => {
968 let inner_span = cx.inner_span;
969 cx.adcx().expected_list_or_no_args(inner_span);
970 None
971 }
972 }
973 }
974}
975
976pub(crate) struct RustcThenThisWouldNeedParser;
977
978impl<S: Stage> CombineAttributeParser<S> for RustcThenThisWouldNeedParser {
979 const PATH: &[Symbol] = &[sym::rustc_then_this_would_need];
980 type Item = Ident;
981
982 const CONVERT: ConvertFn<Self::Item> =
983 |items, span| AttributeKind::RustcThenThisWouldNeed(span, items);
984 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
985 Allow(Target::AssocConst),
987 Allow(Target::AssocTy),
988 Allow(Target::Const),
989 Allow(Target::Enum),
990 Allow(Target::Expression),
991 Allow(Target::Field),
992 Allow(Target::Fn),
993 Allow(Target::ForeignMod),
994 Allow(Target::Impl { of_trait: false }),
995 Allow(Target::Impl { of_trait: true }),
996 Allow(Target::Method(MethodKind::Inherent)),
997 Allow(Target::Method(MethodKind::Trait { body: false })),
998 Allow(Target::Method(MethodKind::Trait { body: true })),
999 Allow(Target::Method(MethodKind::TraitImpl)),
1000 Allow(Target::Mod),
1001 Allow(Target::Static),
1002 Allow(Target::Struct),
1003 Allow(Target::Trait),
1004 Allow(Target::TyAlias),
1005 Allow(Target::Union),
1006 ]);
1008
1009 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: Some(&["DepNode"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["DepNode"]);
1010
1011 fn extend(
1012 cx: &mut AcceptContext<'_, '_, S>,
1013 args: &ArgParser,
1014 ) -> impl IntoIterator<Item = Self::Item> {
1015 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
1016 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
1017 }
1018 let Some(item) = args.list().and_then(|l| l.single()) else {
1019 let inner_span = cx.inner_span;
1020 cx.adcx().expected_single_argument(inner_span);
1021 return None;
1022 };
1023 let Some(ident) = item.meta_item().and_then(|item| item.ident()) else {
1024 cx.adcx().expected_identifier(item.span());
1025 return None;
1026 };
1027 Some(ident)
1028 }
1029}
1030
1031pub(crate) struct RustcInsignificantDtorParser;
1032
1033impl<S: Stage> NoArgsAttributeParser<S> for RustcInsignificantDtorParser {
1034 const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor];
1035 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1036 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
1037 Allow(Target::Enum),
1038 Allow(Target::Struct),
1039 Allow(Target::ForeignTy),
1040 ]);
1041 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor;
1042}
1043
1044pub(crate) struct RustcEffectiveVisibilityParser;
1045
1046impl<S: Stage> NoArgsAttributeParser<S> for RustcEffectiveVisibilityParser {
1047 const PATH: &[Symbol] = &[sym::rustc_effective_visibility];
1048 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1049 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
1050 Allow(Target::Use),
1051 Allow(Target::Static),
1052 Allow(Target::Const),
1053 Allow(Target::Fn),
1054 Allow(Target::Closure),
1055 Allow(Target::Mod),
1056 Allow(Target::ForeignMod),
1057 Allow(Target::TyAlias),
1058 Allow(Target::Enum),
1059 Allow(Target::Variant),
1060 Allow(Target::Struct),
1061 Allow(Target::Field),
1062 Allow(Target::Union),
1063 Allow(Target::Trait),
1064 Allow(Target::TraitAlias),
1065 Allow(Target::Impl { of_trait: false }),
1066 Allow(Target::Impl { of_trait: true }),
1067 Allow(Target::AssocConst),
1068 Allow(Target::Method(MethodKind::Inherent)),
1069 Allow(Target::Method(MethodKind::Trait { body: false })),
1070 Allow(Target::Method(MethodKind::Trait { body: true })),
1071 Allow(Target::Method(MethodKind::TraitImpl)),
1072 Allow(Target::AssocTy),
1073 Allow(Target::ForeignFn),
1074 Allow(Target::ForeignStatic),
1075 Allow(Target::ForeignTy),
1076 Allow(Target::MacroDef),
1077 Allow(Target::PatField),
1078 Allow(Target::Crate),
1079 ]);
1080 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility;
1081}
1082
1083pub(crate) struct RustcDiagnosticItemParser;
1084
1085impl<S: Stage> SingleAttributeParser<S> for RustcDiagnosticItemParser {
1086 const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];
1087 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1088 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
1089 Allow(Target::Trait),
1090 Allow(Target::Struct),
1091 Allow(Target::Enum),
1092 Allow(Target::MacroDef),
1093 Allow(Target::TyAlias),
1094 Allow(Target::AssocTy),
1095 Allow(Target::AssocConst),
1096 Allow(Target::Fn),
1097 Allow(Target::Const),
1098 Allow(Target::Mod),
1099 Allow(Target::Impl { of_trait: false }),
1100 Allow(Target::Method(MethodKind::Inherent)),
1101 Allow(Target::Method(MethodKind::Trait { body: false })),
1102 Allow(Target::Method(MethodKind::Trait { body: true })),
1103 Allow(Target::Method(MethodKind::TraitImpl)),
1104 Allow(Target::Crate),
1105 ]);
1106 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["name"]),
docs: None,
}template!(NameValueStr: "name");
1107
1108 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
1109 let Some(nv) = args.name_value() else {
1110 let attr_span = cx.attr_span;
1111 cx.adcx().expected_name_value(attr_span, None);
1112 return None;
1113 };
1114 let Some(value) = nv.value_as_str() else {
1115 cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
1116 return None;
1117 };
1118 Some(AttributeKind::RustcDiagnosticItem(value))
1119 }
1120}
1121
1122pub(crate) struct RustcDoNotConstCheckParser;
1123
1124impl<S: Stage> NoArgsAttributeParser<S> for RustcDoNotConstCheckParser {
1125 const PATH: &[Symbol] = &[sym::rustc_do_not_const_check];
1126 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1127 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
1128 Allow(Target::Fn),
1129 Allow(Target::Method(MethodKind::Inherent)),
1130 Allow(Target::Method(MethodKind::TraitImpl)),
1131 Allow(Target::Method(MethodKind::Trait { body: false })),
1132 Allow(Target::Method(MethodKind::Trait { body: true })),
1133 ]);
1134 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck;
1135}
1136
1137pub(crate) struct RustcNonnullOptimizationGuaranteedParser;
1138
1139impl<S: Stage> NoArgsAttributeParser<S> for RustcNonnullOptimizationGuaranteedParser {
1140 const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed];
1141 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1142 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
1143 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed;
1144}
1145
1146pub(crate) struct RustcStrictCoherenceParser;
1147
1148impl<S: Stage> NoArgsAttributeParser<S> for RustcStrictCoherenceParser {
1149 const PATH: &[Symbol] = &[sym::rustc_strict_coherence];
1150 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1151 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[
1152 Allow(Target::Trait),
1153 Allow(Target::Struct),
1154 Allow(Target::Enum),
1155 Allow(Target::Union),
1156 Allow(Target::ForeignTy),
1157 ]);
1158 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence;
1159}
1160
1161pub(crate) struct RustcReservationImplParser;
1162
1163impl<S: Stage> SingleAttributeParser<S> for RustcReservationImplParser {
1164 const PATH: &[Symbol] = &[sym::rustc_reservation_impl];
1165 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1166 const ALLOWED_TARGETS: AllowedTargets =
1167 AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]);
1168
1169 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["reservation message"]),
docs: None,
}template!(NameValueStr: "reservation message");
1170
1171 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
1172 let Some(nv) = args.name_value() else {
1173 let attr_span = cx.attr_span;
1174 cx.adcx().expected_name_value(args.span().unwrap_or(attr_span), None);
1175 return None;
1176 };
1177
1178 let Some(value_str) = nv.value_as_str() else {
1179 cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
1180 return None;
1181 };
1182
1183 Some(AttributeKind::RustcReservationImpl(cx.attr_span, value_str))
1184 }
1185}
1186
1187pub(crate) struct PreludeImportParser;
1188
1189impl<S: Stage> NoArgsAttributeParser<S> for PreludeImportParser {
1190 const PATH: &[Symbol] = &[sym::prelude_import];
1191 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Warn;
1192 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Use)]);
1193 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport;
1194}
1195
1196pub(crate) struct RustcDocPrimitiveParser;
1197
1198impl<S: Stage> SingleAttributeParser<S> for RustcDocPrimitiveParser {
1199 const PATH: &[Symbol] = &[sym::rustc_doc_primitive];
1200 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1201 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Mod)]);
1202 const TEMPLATE: AttributeTemplate = ::rustc_feature::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["primitive name"]),
docs: None,
}template!(NameValueStr: "primitive name");
1203
1204 fn convert(cx: &mut AcceptContext<'_, '_, S>, args: &ArgParser) -> Option<AttributeKind> {
1205 let Some(nv) = args.name_value() else {
1206 let span = cx.attr_span;
1207 cx.adcx().expected_name_value(args.span().unwrap_or(span), None);
1208 return None;
1209 };
1210
1211 let Some(value_str) = nv.value_as_str() else {
1212 cx.adcx().expected_string_literal(nv.value_span, Some(nv.value_as_lit()));
1213 return None;
1214 };
1215
1216 Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str))
1217 }
1218}
1219
1220pub(crate) struct RustcIntrinsicParser;
1221
1222impl<S: Stage> NoArgsAttributeParser<S> for RustcIntrinsicParser {
1223 const PATH: &[Symbol] = &[sym::rustc_intrinsic];
1224 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1225 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1226 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic;
1227}
1228
1229pub(crate) struct RustcIntrinsicConstStableIndirectParser;
1230
1231impl<S: Stage> NoArgsAttributeParser<S> for RustcIntrinsicConstStableIndirectParser {
1232 const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];
1233 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1234 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1235 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;
1236}
1237
1238pub(crate) struct RustcExhaustiveParser;
1239
1240impl<S: Stage> NoArgsAttributeParser<S> for RustcExhaustiveParser {
1241 const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively];
1242 const ON_DUPLICATE: OnDuplicate<S> = OnDuplicate::Error;
1243 const ALLOWED_TARGETS: AllowedTargets = AllowedTargets::AllowList(&[Allow(Target::Enum)]);
1244 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively;
1245}