Skip to main content

rustc_attr_parsing/attributes/
rustc_internal.rs

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