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