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