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