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