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() || lang_item.is_weak_only())
586 {
587 cx.emit_err(UnknownExternLangItem { span: cx.attr_span, lang_item: lang_item.name() });
588 return None;
589 }
590
591 let allowed_targets: &[_] = &[Allow(lang_item.target())];
593 cx.check_target(&::alloc::__export::must_use({
::alloc::fmt::format(format_args!(" = \"{0}\"", name))
})format!(" = \"{name}\""), &AllowedTargets::AllowList(allowed_targets));
594
595 Some(AttributeKind::Lang(lang_item))
596 }
597}
598
599pub(crate) struct RustcHasIncoherentInherentImplsParser;
600
601impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParser {
602 const PATH: &[Symbol] = &[sym::rustc_has_incoherent_inherent_impls];
603 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
604 Allow(Target::Trait),
605 Allow(Target::Struct),
606 Allow(Target::Enum),
607 Allow(Target::Union),
608 Allow(Target::ForeignTy),
609 ]);
610 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
611 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;
612}
613
614pub(crate) struct PanicHandlerParser;
615
616impl NoArgsAttributeParser for PanicHandlerParser {
617 const PATH: &[Symbol] = &[sym::panic_handler];
618 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
619 const STABILITY: AttributeStability = AttributeStability::Stable;
620 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Lang(LangItem::PanicImpl);
621}
622
623pub(crate) struct RustcNounwindParser;
624
625impl NoArgsAttributeParser for RustcNounwindParser {
626 const PATH: &[Symbol] = &[sym::rustc_nounwind];
627 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
628 Allow(Target::Fn),
629 Allow(Target::ForeignFn),
630 Allow(Target::Method(MethodKind::Inherent)),
631 Allow(Target::Method(MethodKind::TraitImpl)),
632 Allow(Target::Method(MethodKind::Trait { body: true })),
633 ]);
634 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
635 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNounwind;
636}
637
638pub(crate) struct RustcOffloadKernelParser;
639
640impl NoArgsAttributeParser for RustcOffloadKernelParser {
641 const PATH: &[Symbol] = &[sym::rustc_offload_kernel];
642 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
643 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
644 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;
645}
646
647pub(crate) struct RustcMirParser;
648
649impl CombineAttributeParser for RustcMirParser {
650 const PATH: &[Symbol] = &[sym::rustc_mir];
651
652 type Item = RustcMirKind;
653
654 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcMir(items);
655 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
656 Allow(Target::Fn),
657 Allow(Target::Method(MethodKind::Inherent)),
658 Allow(Target::Method(MethodKind::TraitImpl)),
659 Allow(Target::Method(MethodKind::Trait { body: false })),
660 Allow(Target::Method(MethodKind::Trait { body: true })),
661 ]);
662 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&["arg1, arg2, ..."]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["arg1, arg2, ..."]);
663 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
664
665 fn extend(
666 cx: &mut AcceptContext<'_, '_>,
667 args: &ArgParser,
668 ) -> impl IntoIterator<Item = Self::Item> {
669 let Some(list) = cx.expect_list(args, cx.attr_span) else {
670 return ThinVec::new();
671 };
672
673 list.mixed()
674 .filter_map(|arg| arg.meta_item())
675 .filter_map(|mi| {
676 if let Some(ident) = mi.ident() {
677 match ident.name {
678 sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit),
679 sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit),
680 sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness),
681 sym::stop_after_dataflow => Some(RustcMirKind::StopAfterDataflow),
682 sym::borrowck_graphviz_postflow => {
683 let nv = cx.expect_name_value(
684 mi.args(),
685 mi.span(),
686 Some(sym::borrowck_graphviz_postflow),
687 )?;
688 let path = cx.expect_string_literal(nv)?;
689 let path = PathBuf::from(path.to_string());
690 if path.file_name().is_some() {
691 Some(RustcMirKind::BorrowckGraphvizPostflow { path })
692 } else {
693 cx.adcx().expected_filename_literal(nv.value_span);
694 None
695 }
696 }
697 sym::borrowck_graphviz_format => {
698 let nv = cx.expect_name_value(
699 mi.args(),
700 mi.span(),
701 Some(sym::borrowck_graphviz_format),
702 )?;
703 let Some(format) = nv.value_as_ident() else {
704 cx.adcx().expected_identifier(nv.value_span);
705 return None;
706 };
707 match format.name {
708 sym::two_phase => Some(RustcMirKind::BorrowckGraphvizFormat {
709 format: BorrowckGraphvizFormatKind::TwoPhase,
710 }),
711 _ => {
712 cx.adcx()
713 .expected_specific_argument(format.span, &[sym::two_phase]);
714 None
715 }
716 }
717 }
718 _ => None,
719 }
720 } else {
721 None
722 }
723 })
724 .collect()
725 }
726}
727pub(crate) struct RustcNonConstTraitMethodParser;
728
729impl NoArgsAttributeParser for RustcNonConstTraitMethodParser {
730 const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method];
731 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
732 Allow(Target::Method(MethodKind::Trait { body: true })),
733 Allow(Target::Method(MethodKind::Trait { body: false })),
734 ]);
735 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!(
736 rustc_attrs,
737 "`#[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"
738 );
739 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod;
740}
741
742pub(crate) struct RustcCleanParser;
743
744impl CombineAttributeParser for RustcCleanParser {
745 const PATH: &[Symbol] = &[sym::rustc_clean];
746
747 type Item = RustcCleanAttribute;
748
749 const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcClean(items);
750 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
751 Allow(Target::AssocConst),
753 Allow(Target::AssocTy),
754 Allow(Target::Const),
755 Allow(Target::Enum),
756 Allow(Target::Expression),
757 Allow(Target::Field),
758 Allow(Target::Fn),
759 Allow(Target::ForeignMod),
760 Allow(Target::Impl { of_trait: false }),
761 Allow(Target::Impl { of_trait: true }),
762 Allow(Target::Method(MethodKind::Inherent)),
763 Allow(Target::Method(MethodKind::Trait { body: false })),
764 Allow(Target::Method(MethodKind::Trait { body: true })),
765 Allow(Target::Method(MethodKind::TraitImpl)),
766 Allow(Target::Mod),
767 Allow(Target::Static),
768 Allow(Target::Struct),
769 Allow(Target::Trait),
770 Allow(Target::TyAlias),
771 Allow(Target::Union),
772 ]);
774 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
775 const TEMPLATE: AttributeTemplate =
776 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 = "...""#]);
777
778 fn extend(
779 cx: &mut AcceptContext<'_, '_>,
780 args: &ArgParser,
781 ) -> impl IntoIterator<Item = Self::Item> {
782 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
783 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
784 }
785 let list = cx.expect_list(args, cx.attr_span)?;
786
787 let mut except = None;
788 let mut loaded_from_disk = None;
789 let mut cfg = None;
790
791 for item in list.mixed() {
792 let Some((ident, value)) = cx.expect_name_value(item, item.span(), None) else {
793 continue;
794 };
795 let value_span = value.value_span;
796 let Some(value) = cx.expect_string_literal(value) else {
797 continue;
798 };
799 match ident.name {
800 sym::cfg if cfg.is_some() => {
801 cx.adcx().duplicate_key(item.span(), sym::cfg);
802 }
803 sym::cfg => {
804 cfg = Some(value);
805 }
806 sym::except if except.is_some() => {
807 cx.adcx().duplicate_key(item.span(), sym::except);
808 }
809 sym::except => {
810 let entries =
811 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();
812 except = Some(RustcCleanQueries { entries, span: value_span });
813 }
814 sym::loaded_from_disk if loaded_from_disk.is_some() => {
815 cx.adcx().duplicate_key(item.span(), sym::loaded_from_disk);
816 }
817 sym::loaded_from_disk => {
818 let entries =
819 value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();
820 loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span });
821 }
822 _ => {
823 cx.adcx().expected_specific_argument(
824 ident.span,
825 &[sym::cfg, sym::except, sym::loaded_from_disk],
826 );
827 }
828 }
829 }
830 let Some(cfg) = cfg else {
831 cx.adcx().expected_specific_argument(list.span, &[sym::cfg]);
832 return None;
833 };
834
835 Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk })
836 }
837}
838
839pub(crate) struct RustcIfThisChangedParser;
840
841impl SingleAttributeParser for RustcIfThisChangedParser {
842 const PATH: &[Symbol] = &[sym::rustc_if_this_changed];
843 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
844 Allow(Target::AssocConst),
846 Allow(Target::AssocTy),
847 Allow(Target::Const),
848 Allow(Target::Enum),
849 Allow(Target::Expression),
850 Allow(Target::Field),
851 Allow(Target::Fn),
852 Allow(Target::ForeignMod),
853 Allow(Target::Impl { of_trait: false }),
854 Allow(Target::Impl { of_trait: true }),
855 Allow(Target::Method(MethodKind::Inherent)),
856 Allow(Target::Method(MethodKind::Trait { body: false })),
857 Allow(Target::Method(MethodKind::Trait { body: true })),
858 Allow(Target::Method(MethodKind::TraitImpl)),
859 Allow(Target::Mod),
860 Allow(Target::Static),
861 Allow(Target::Struct),
862 Allow(Target::Trait),
863 Allow(Target::TyAlias),
864 Allow(Target::Union),
865 ]);
867 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: true,
list: Some(&["DepNode"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(Word, List: &["DepNode"]);
868 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
869
870 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
871 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
872 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
873 }
874 match args {
875 ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),
876 ArgParser::List(list) => {
877 let item = cx.expect_single(list)?;
878 let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {
879 cx.adcx().expected_identifier(item.span());
880 return None;
881 };
882 Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name)))
883 }
884 ArgParser::NameValue(_) => {
885 let inner_span = cx.inner_span;
886 cx.adcx().expected_list_or_no_args(inner_span);
887 None
888 }
889 }
890 }
891}
892
893pub(crate) struct RustcThenThisWouldNeedParser;
894
895impl CombineAttributeParser for RustcThenThisWouldNeedParser {
896 const PATH: &[Symbol] = &[sym::rustc_then_this_would_need];
897 type Item = Ident;
898
899 const CONVERT: ConvertFn<Self::Item> =
900 |items, _span| AttributeKind::RustcThenThisWouldNeed(items);
901 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
902 Allow(Target::AssocConst),
904 Allow(Target::AssocTy),
905 Allow(Target::Const),
906 Allow(Target::Enum),
907 Allow(Target::Expression),
908 Allow(Target::Field),
909 Allow(Target::Fn),
910 Allow(Target::ForeignMod),
911 Allow(Target::Impl { of_trait: false }),
912 Allow(Target::Impl { of_trait: true }),
913 Allow(Target::Method(MethodKind::Inherent)),
914 Allow(Target::Method(MethodKind::Trait { body: false })),
915 Allow(Target::Method(MethodKind::Trait { body: true })),
916 Allow(Target::Method(MethodKind::TraitImpl)),
917 Allow(Target::Mod),
918 Allow(Target::Static),
919 Allow(Target::Struct),
920 Allow(Target::Trait),
921 Allow(Target::TyAlias),
922 Allow(Target::Union),
923 ]);
925 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: Some(&["DepNode"]),
one_of: &[],
name_value_str: None,
docs: None,
}template!(List: &["DepNode"]);
926 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
927
928 fn extend(
929 cx: &mut AcceptContext<'_, '_>,
930 args: &ArgParser,
931 ) -> impl IntoIterator<Item = Self::Item> {
932 if !cx.cx.sess.opts.unstable_opts.query_dep_graph {
933 cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });
934 }
935 let item = cx.expect_single_element_list(args, cx.attr_span)?;
936 let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {
937 cx.adcx().expected_identifier(item.span());
938 return None;
939 };
940 Some(ident)
941 }
942}
943
944pub(crate) struct RustcInsignificantDtorParser;
945
946impl NoArgsAttributeParser for RustcInsignificantDtorParser {
947 const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor];
948 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
949 Allow(Target::Enum),
950 Allow(Target::Struct),
951 Allow(Target::ForeignTy),
952 ]);
953 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
954 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor;
955}
956
957pub(crate) struct RustcEffectiveVisibilityParser;
958
959impl NoArgsAttributeParser for RustcEffectiveVisibilityParser {
960 const PATH: &[Symbol] = &[sym::rustc_effective_visibility];
961 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
962 Allow(Target::Use),
963 Allow(Target::Static),
964 Allow(Target::Const),
965 Allow(Target::Fn),
966 Allow(Target::Closure),
967 Allow(Target::Mod),
968 Allow(Target::ForeignMod),
969 Allow(Target::TyAlias),
970 Allow(Target::Enum),
971 Allow(Target::Variant),
972 Allow(Target::Struct),
973 Allow(Target::Field),
974 Allow(Target::Union),
975 Allow(Target::Trait),
976 Allow(Target::TraitAlias),
977 Allow(Target::Impl { of_trait: false }),
978 Allow(Target::Impl { of_trait: true }),
979 Allow(Target::AssocConst),
980 Allow(Target::Method(MethodKind::Inherent)),
981 Allow(Target::Method(MethodKind::Trait { body: false })),
982 Allow(Target::Method(MethodKind::Trait { body: true })),
983 Allow(Target::Method(MethodKind::TraitImpl)),
984 Allow(Target::AssocTy),
985 Allow(Target::ForeignFn),
986 Allow(Target::ForeignStatic),
987 Allow(Target::ForeignTy),
988 Allow(Target::MacroDef),
989 Allow(Target::PatField),
990 Allow(Target::Crate),
991 ]);
992 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
993 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility;
994}
995
996pub(crate) struct RustcDiagnosticItemParser;
997
998impl SingleAttributeParser for RustcDiagnosticItemParser {
999 const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];
1000 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1001 Allow(Target::Trait),
1002 Allow(Target::Struct),
1003 Allow(Target::Enum),
1004 Allow(Target::MacroDef),
1005 Allow(Target::TyAlias),
1006 Allow(Target::AssocTy),
1007 Allow(Target::AssocConst),
1008 Allow(Target::Fn),
1009 Allow(Target::Const),
1010 Allow(Target::Mod),
1011 Allow(Target::Impl { of_trait: false }),
1012 Allow(Target::Method(MethodKind::Inherent)),
1013 Allow(Target::Method(MethodKind::Trait { body: false })),
1014 Allow(Target::Method(MethodKind::Trait { body: true })),
1015 Allow(Target::Method(MethodKind::TraitImpl)),
1016 Allow(Target::Crate),
1017 ]);
1018 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["name"]),
docs: None,
}template!(NameValueStr: "name");
1019 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!(
1020 rustc_attrs,
1021 "the `#[rustc_diagnostic_item]` attribute allows the compiler to reference types from the standard library for diagnostic purposes"
1022 );
1023
1024 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
1025 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
1026 let value = cx.expect_string_literal(nv)?;
1027 Some(AttributeKind::RustcDiagnosticItem(value))
1028 }
1029}
1030
1031pub(crate) struct RustcDoNotConstCheckParser;
1032
1033impl NoArgsAttributeParser for RustcDoNotConstCheckParser {
1034 const PATH: &[Symbol] = &[sym::rustc_do_not_const_check];
1035 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1036 Allow(Target::Fn),
1037 Allow(Target::Method(MethodKind::Inherent)),
1038 Allow(Target::Method(MethodKind::TraitImpl)),
1039 Allow(Target::Method(MethodKind::Trait { body: false })),
1040 Allow(Target::Method(MethodKind::Trait { body: true })),
1041 ]);
1042 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!(
1043 rustc_attrs,
1044 "`#[rustc_do_not_const_check]` skips const-check for this function's body"
1045 );
1046 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck;
1047}
1048
1049pub(crate) struct RustcNonnullOptimizationGuaranteedParser;
1050
1051impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser {
1052 const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed];
1053 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);
1054 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!(
1055 rustc_attrs,
1056 "the `#[rustc_nonnull_optimization_guaranteed]` attribute is just used to document guaranteed niche optimizations in the standard library",
1057 "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"
1058 );
1059 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed;
1060}
1061
1062pub(crate) struct RustcStrictCoherenceParser;
1063
1064impl NoArgsAttributeParser for RustcStrictCoherenceParser {
1065 const PATH: &[Symbol] = &[sym::rustc_strict_coherence];
1066 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[
1067 Allow(Target::Trait),
1068 Allow(Target::Struct),
1069 Allow(Target::Enum),
1070 Allow(Target::Union),
1071 Allow(Target::ForeignTy),
1072 ]);
1073 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
1074 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence;
1075}
1076
1077pub(crate) struct RustcReservationImplParser;
1078
1079impl SingleAttributeParser for RustcReservationImplParser {
1080 const PATH: &[Symbol] = &[sym::rustc_reservation_impl];
1081 const ALLOWED_TARGETS: AllowedTargets<'_> =
1082 AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]);
1083 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["reservation message"]),
docs: None,
}template!(NameValueStr: "reservation message");
1084 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
1085
1086 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
1087 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
1088 let value_str = cx.expect_string_literal(nv)?;
1089
1090 Some(AttributeKind::RustcReservationImpl(value_str))
1091 }
1092}
1093
1094pub(crate) struct PreludeImportParser;
1095
1096impl NoArgsAttributeParser for PreludeImportParser {
1097 const PATH: &[Symbol] = &[sym::prelude_import];
1098 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Use)]);
1099 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::prelude_import,
gate_check: rustc_feature::Features::prelude_import,
notes: &[],
}unstable!(prelude_import);
1100 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport;
1101}
1102
1103pub(crate) struct RustcDocPrimitiveParser;
1104
1105impl SingleAttributeParser for RustcDocPrimitiveParser {
1106 const PATH: &[Symbol] = &[sym::rustc_doc_primitive];
1107 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Mod)]);
1108 const TEMPLATE: AttributeTemplate = crate::AttributeTemplate {
word: false,
list: None,
one_of: &[],
name_value_str: Some(&["primitive name"]),
docs: None,
}template!(NameValueStr: "primitive name");
1109 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!(
1110 rustc_attrs,
1111 "the `#[rustc_doc_primitive]` attribute is used by the standard library to provide a way to generate documentation for primitive types"
1112 );
1113
1114 fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {
1115 let nv = cx.expect_name_value(args, cx.attr_span, None)?;
1116 let value_str = cx.expect_string_literal(nv)?;
1117
1118 Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str))
1119 }
1120}
1121
1122pub(crate) struct RustcIntrinsicParser;
1123
1124impl NoArgsAttributeParser for RustcIntrinsicParser {
1125 const PATH: &[Symbol] = &[sym::rustc_intrinsic];
1126 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1127 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::intrinsics,
gate_check: rustc_feature::Features::intrinsics,
notes: &[],
}unstable!(intrinsics);
1128 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic;
1129}
1130
1131pub(crate) struct RustcIntrinsicConstStableIndirectParser;
1132
1133impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser {
1134 const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];
1135 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);
1136 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
1137 const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;
1138}
1139
1140pub(crate) struct RustcExhaustiveParser;
1141
1142impl NoArgsAttributeParser for RustcExhaustiveParser {
1143 const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively];
1144 const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Enum)]);
1145 const STABILITY: AttributeStability = AttributeStability::Unstable {
gate_name: rustc_span::sym::rustc_attrs,
gate_check: rustc_feature::Features::rustc_attrs,
notes: &[],
}unstable!(rustc_attrs);
1146 const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively;
1147}