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