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