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