Skip to main content

rustc_attr_parsing/attributes/
rustc_internal.rs

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