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