compiler/rustc_attr_parsing/src/attributes/rustc_internal.rs RUST 1,211 lines View on github.com → Search inside
1use std::path::PathBuf;23use rustc_ast::{LitIntType, LitKind, MetaItemLit};4use rustc_attr_ir::lang_items::LangItem;5use rustc_attr_ir::target::GenericParamKind;6use rustc_attr_ir::{7    BorrowckGraphvizFormatKind, CguFields, CguKind, DivergingBlockBehavior,8    DivergingFallbackBehavior, RustcCleanAttribute, RustcCleanQueries, RustcMirKind,9};10use rustc_data_structures::fx::FxHashMap;11use rustc_feature::AttributeStability;12use rustc_span::Symbol;1314use super::prelude::*;15use super::util::parse_single_integer;16use crate::diagnostics;17use crate::diagnostics::{18    AttributeRequiresOpt, CguFieldsMissing, RustcScalableVectorCountOutOfRange,19    UnknownExternLangItem, UnknownLangItem,20};2122pub(crate) struct RustcMainParser;2324impl NoArgsAttributeParser for RustcMainParser {25    const PATH: &[Symbol] = &[sym::rustc_main];26    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);27    const STABILITY: AttributeStability = unstable!(28        rustc_attrs,29        "the `rustc_main` attribute is used internally to specify test entry point function"30    );31    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcMain;32}3334pub(crate) struct RustcMustImplementOneOfParser;3536impl SingleAttributeParser for RustcMustImplementOneOfParser {37    const PATH: &[Symbol] = &[sym::rustc_must_implement_one_of];38    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]);39    const STABILITY: AttributeStability = unstable!(40        rustc_attrs,41        "the `rustc_must_implement_one_of` attribute is used to change minimal complete definition of a trait. Its syntax and semantics are highly experimental and will be subject to change before stabilization"42    );43    const TEMPLATE: AttributeTemplate = template!(List: &["function1, function2, ..."]);44    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {45        let list = cx.expect_list(args, cx.attr_span)?;4647        let mut fn_names = ThinVec::new();4849        let inputs: Vec<_> = list.mixed().collect();5051        if inputs.len() < 2 {52            cx.adcx().expected_list_with_num_args_or_more(2, list.span);53            return None;54        }5556        let mut errored = false;57        for argument in inputs {58            let Some(meta) = argument.meta_item_no_args() else {59                cx.adcx().expected_identifier(argument.span());60                return None;61            };6263            let Some(ident) = meta.ident() else {64                cx.dcx()65                    .emit_err(diagnostics::MustBeNameOfAssociatedFunction { span: meta.span() });66                errored = true;67                continue;68            };6970            fn_names.push(ident);71        }72        if errored {73            return None;74        }7576        if cx.target == Target::Trait {77            // Check for duplicates78            let mut seen: FxHashMap<Symbol, Span> = FxHashMap::default();79            for ident in &fn_names {80                if let Some(dup) = seen.insert(ident.name, ident.span) {81                    cx.emit_err(diagnostics::FunctionNamesDuplicated {82                        spans: vec![dup, ident.span],83                    });84                }85            }86        }8788        Some(AttributeKind::RustcMustImplementOneOf { attr_span: cx.attr_span, fn_names })89    }90}9192pub(crate) struct RustcNeverReturnsNullPtrParser;9394impl NoArgsAttributeParser for RustcNeverReturnsNullPtrParser {95    const PATH: &[Symbol] = &[sym::rustc_never_returns_null_ptr];96    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[97        Allow(Target::Fn),98        Allow(Target::Method(MethodKind::Inherent)),99        Allow(Target::Method(MethodKind::Trait { body: false })),100        Allow(Target::Method(MethodKind::Trait { body: true })),101        Allow(Target::Method(MethodKind::TraitImpl)),102    ]);103    const STABILITY: AttributeStability = unstable!(rustc_attrs);104105    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNeverReturnsNullPtr;106}107108pub(crate) struct RustcPanicsWhenZeroParser;109110impl NoArgsAttributeParser for RustcPanicsWhenZeroParser {111    const PATH: &[Symbol] = &[sym::rustc_panics_when_zero];112    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[113        Allow(Target::GenericParam { kind: GenericParamKind::Const, has_default: true }),114        Allow(Target::GenericParam { kind: GenericParamKind::Const, has_default: false }),115    ]);116    const STABILITY: AttributeStability = unstable!(rustc_attrs);117118    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcPanicsWhenZero;119}120121pub(crate) struct RustcNoImplicitAutorefsParser;122123impl NoArgsAttributeParser for RustcNoImplicitAutorefsParser {124    const PATH: &[Symbol] = &[sym::rustc_no_implicit_autorefs];125    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[126        Allow(Target::Fn),127        Allow(Target::Method(MethodKind::Inherent)),128        Allow(Target::Method(MethodKind::Trait { body: false })),129        Allow(Target::Method(MethodKind::Trait { body: true })),130        Allow(Target::Method(MethodKind::TraitImpl)),131    ]);132    const STABILITY: AttributeStability = unstable!(rustc_attrs);133134    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoImplicitAutorefs;135}136137pub(crate) struct RustcLegacyConstGenericsParser;138139impl SingleAttributeParser for RustcLegacyConstGenericsParser {140    const PATH: &[Symbol] = &[sym::rustc_legacy_const_generics];141    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);142    const TEMPLATE: AttributeTemplate = template!(List: &["N"]);143    const STABILITY: AttributeStability = unstable!(rustc_attrs);144145    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {146        let meta_items = cx.expect_list(args, cx.attr_span)?;147148        let mut parsed_indexes = ThinVec::new();149        let mut errored = false;150151        for possible_index in meta_items.mixed() {152            if let MetaItemOrLitParser::Lit(MetaItemLit {153                kind: LitKind::Int(index, LitIntType::Unsuffixed),154                ..155            }) = possible_index156            {157                parsed_indexes.push((index.0 as usize, possible_index.span()));158            } else {159                cx.adcx().expected_integer_literal(possible_index.span());160                errored = true;161            }162        }163        if errored {164            return None;165        } else if parsed_indexes.is_empty() {166            cx.adcx().expected_at_least_one_argument(args.span()?);167            return None;168        }169170        Some(AttributeKind::RustcLegacyConstGenerics {171            fn_indexes: parsed_indexes,172            attr_span: cx.attr_span,173        })174    }175}176177pub(crate) struct RustcInheritOverflowChecksParser;178179impl NoArgsAttributeParser for RustcInheritOverflowChecksParser {180    const PATH: &[Symbol] = &[sym::rustc_inherit_overflow_checks];181    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[182        Allow(Target::Fn),183        Allow(Target::Method(MethodKind::Inherent)),184        Allow(Target::Method(MethodKind::TraitImpl)),185        Allow(Target::Closure),186    ]);187    const STABILITY: AttributeStability = unstable!(rustc_attrs);188    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInheritOverflowChecks;189}190191pub(crate) struct RustcLintOptDenyFieldAccessParser;192193impl SingleAttributeParser for RustcLintOptDenyFieldAccessParser {194    const PATH: &[Symbol] = &[sym::rustc_lint_opt_deny_field_access];195    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Field)]);196    const TEMPLATE: AttributeTemplate = template!(Word);197    const STABILITY: AttributeStability = unstable!(rustc_attrs);198    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {199        let arg = cx.expect_single_element_list(args, cx.attr_span)?;200        let lint_message = cx.expect_string_literal(arg)?;201202        Some(AttributeKind::RustcLintOptDenyFieldAccess { lint_message })203    }204}205206pub(crate) struct RustcLintOptTyParser;207208impl NoArgsAttributeParser for RustcLintOptTyParser {209    const PATH: &[Symbol] = &[sym::rustc_lint_opt_ty];210    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);211    const STABILITY: AttributeStability = unstable!(rustc_attrs);212    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintOptTy;213}214215fn parse_cgu_fields(216    cx: &mut AcceptContext<'_, '_>,217    args: &ArgParser,218    accepts_kind: bool,219) -> Option<(Symbol, Symbol, Option<CguKind>)> {220    let args = cx.expect_list(args, cx.attr_span)?;221222    let mut cfg = None::<(Symbol, Span)>;223    let mut module = None::<(Symbol, Span)>;224    let mut kind = None::<(Symbol, Span)>;225226    for arg in args.mixed() {227        let Some((ident, arg)) = cx.expect_name_value(arg, arg.span(), None) else {228            continue;229        };230231        let res = match ident.name {232            sym::cfg => &mut cfg,233            sym::module => &mut module,234            sym::kind if accepts_kind => &mut kind,235            _ => {236                cx.adcx().expected_specific_argument(237                    ident.span,238                    if accepts_kind {239                        &[sym::cfg, sym::module, sym::kind]240                    } else {241                        &[sym::cfg, sym::module]242                    },243                );244                continue;245            }246        };247248        let str = cx.expect_string_literal(arg)?;249250        if res.is_some() {251            cx.adcx().duplicate_key(ident.span.to(arg.args_span()), ident.name);252            continue;253        }254255        *res = Some((str, arg.value_span));256    }257258    let Some((cfg, _)) = cfg else {259        cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::cfg });260        return None;261    };262    let Some((module, _)) = module else {263        cx.emit_err(CguFieldsMissing { span: args.span, name: &cx.attr_path, field: sym::module });264        return None;265    };266    let kind = if let Some((kind, span)) = kind {267        Some(match kind {268            sym::no => CguKind::No,269            sym::pre_dash_lto => CguKind::PreDashLto,270            sym::post_dash_lto => CguKind::PostDashLto,271            sym::any => CguKind::Any,272            _ => {273                cx.adcx().expected_specific_argument_strings(274                    span,275                    &[sym::no, sym::pre_dash_lto, sym::post_dash_lto, sym::any],276                );277                return None;278            }279        })280    } else {281        // return None so that an unwrap for the attributes that need it is ok.282        if accepts_kind {283            cx.emit_err(CguFieldsMissing {284                span: args.span,285                name: &cx.attr_path,286                field: sym::kind,287            });288            return None;289        };290291        None292    };293294    Some((cfg, module, kind))295}296297#[derive(Default)]298pub(crate) struct RustcCguTestAttributeParser {299    items: ThinVec<(Span, CguFields)>,300}301302impl AttributeParser for RustcCguTestAttributeParser {303    const ATTRIBUTES: AcceptMapping<Self> = &[304        (305            &[sym::rustc_partition_reused],306            template!(List: &[r#"cfg = "...", module = "...""#]),307            unstable!(rustc_attrs),308            |this, cx, args| {309                this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| {310                    (cx.attr_span, CguFields::PartitionReused { cfg, module })311                }));312            },313        ),314        (315            &[sym::rustc_partition_codegened],316            template!(List: &[r#"cfg = "...", module = "...""#]),317            unstable!(rustc_attrs),318            |this, cx, args| {319                this.items.extend(parse_cgu_fields(cx, args, false).map(|(cfg, module, _)| {320                    (cx.attr_span, CguFields::PartitionCodegened { cfg, module })321                }));322            },323        ),324        (325            &[sym::rustc_expected_cgu_reuse],326            template!(List: &[r#"cfg = "...", module = "...", kind = "...""#]),327            unstable!(rustc_attrs),328            |this, cx, args| {329                this.items.extend(parse_cgu_fields(cx, args, true).map(|(cfg, module, kind)| {330                    // unwrap ok because if not given, we return None in `parse_cgu_fields`.331                    (cx.attr_span, CguFields::ExpectedCguReuse { cfg, module, kind: kind.unwrap() })332                }));333            },334        ),335    ];336337    const ALLOWED_TARGETS: AllowedTargets<'_> =338        AllowedTargets::AllowList(&[Allow(Target::Mod), Allow(Target::Crate)]);339340    fn finalize(self, _cx: &FinalizeContext<'_, '_>) -> Option<AttributeKind> {341        Some(AttributeKind::RustcCguTestAttr(self.items))342    }343}344345pub(crate) struct RustcDeprecatedSafe2024Parser;346347impl SingleAttributeParser for RustcDeprecatedSafe2024Parser {348    const PATH: &[Symbol] = &[sym::rustc_deprecated_safe_2024];349    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[350        Allow(Target::Fn),351        Allow(Target::Method(MethodKind::Inherent)),352        Allow(Target::Method(MethodKind::Trait { body: false })),353        Allow(Target::Method(MethodKind::Trait { body: true })),354        Allow(Target::Method(MethodKind::TraitImpl)),355    ]);356    const TEMPLATE: AttributeTemplate = template!(List: &[r#"audit_that = "...""#]);357    const STABILITY: AttributeStability = unstable!(rustc_attrs);358359    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {360        let single = cx.expect_single_element_list(args, cx.attr_span)?;361362        let (path, arg) = cx.expect_name_value(single, cx.attr_span, None)?;363364        if path.name != sym::audit_that {365            cx.adcx().expected_specific_argument(path.span, &[sym::audit_that]);366            return None;367        };368369        let suggestion = cx.expect_string_literal(arg)?;370371        Some(AttributeKind::RustcDeprecatedSafe2024 { suggestion })372    }373}374375pub(crate) struct RustcConversionSuggestionParser;376377impl NoArgsAttributeParser for RustcConversionSuggestionParser {378    const PATH: &[Symbol] = &[sym::rustc_conversion_suggestion];379    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[380        Allow(Target::Fn),381        Allow(Target::Method(MethodKind::Inherent)),382        Allow(Target::Method(MethodKind::Trait { body: false })),383        Allow(Target::Method(MethodKind::Trait { body: true })),384        Allow(Target::Method(MethodKind::TraitImpl)),385    ]);386    const STABILITY: AttributeStability = unstable!(rustc_attrs);387    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcConversionSuggestion;388}389390pub(crate) struct RustcCaptureAnalysisParser;391392impl NoArgsAttributeParser for RustcCaptureAnalysisParser {393    const PATH: &[Symbol] = &[sym::rustc_capture_analysis];394    const ALLOWED_TARGETS: AllowedTargets<'_> =395        AllowedTargets::AllowList(&[Allow(Target::Closure)]);396    const STABILITY: AttributeStability = unstable!(rustc_attrs);397    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCaptureAnalysis;398}399400pub(crate) struct RustcNeverTypeOptionsParser;401402impl SingleAttributeParser for RustcNeverTypeOptionsParser {403    const PATH: &[Symbol] = &[sym::rustc_never_type_options];404    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Crate)]);405    const TEMPLATE: AttributeTemplate = template!(List: &[406        r#"fallback = "unit", "never", "no""#,407        r#"diverging_block_default = "unit", "never""#,408    ]);409    const STABILITY: AttributeStability = unstable!(410        rustc_attrs,411        "`rustc_never_type_options` is used to experiment with never type fallback and work on never type stabilization"412    );413414    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {415        let list = cx.expect_list(args, cx.attr_span)?;416417        let mut fallback = None::<Ident>;418        let mut diverging_block_default = None::<Ident>;419420        for arg in list.mixed() {421            let Some((ident, arg)) = cx.expect_name_value(arg, arg.span(), None) else {422                continue;423            };424425            let res = match ident.name {426                sym::fallback => &mut fallback,427                sym::diverging_block_default => &mut diverging_block_default,428                _ => {429                    cx.adcx().expected_specific_argument(430                        ident.span,431                        &[sym::fallback, sym::diverging_block_default],432                    );433                    continue;434                }435            };436437            let field = cx.expect_string_literal(arg)?;438439            if res.is_some() {440                cx.adcx().duplicate_key(ident.span, ident.name);441                continue;442            }443444            *res = Some(Ident { name: field, span: arg.value_span });445        }446447        let fallback = match fallback {448            None => None,449            Some(Ident { name: sym::unit, .. }) => Some(DivergingFallbackBehavior::ToUnit),450            Some(Ident { name: sym::never, .. }) => Some(DivergingFallbackBehavior::ToNever),451            Some(Ident { name: sym::no, .. }) => Some(DivergingFallbackBehavior::NoFallback),452            Some(Ident { span, .. }) => {453                cx.adcx()454                    .expected_specific_argument_strings(span, &[sym::unit, sym::never, sym::no]);455                return None;456            }457        };458459        let diverging_block_default = match diverging_block_default {460            None => None,461            Some(Ident { name: sym::unit, .. }) => Some(DivergingBlockBehavior::Unit),462            Some(Ident { name: sym::never, .. }) => Some(DivergingBlockBehavior::Never),463            Some(Ident { span, .. }) => {464                cx.adcx().expected_specific_argument_strings(span, &[sym::unit, sym::no]);465                return None;466            }467        };468469        Some(AttributeKind::RustcNeverTypeOptions { fallback, diverging_block_default })470    }471}472473pub(crate) struct RustcTrivialFieldReadsParser;474475impl NoArgsAttributeParser for RustcTrivialFieldReadsParser {476    const PATH: &[Symbol] = &[sym::rustc_trivial_field_reads];477    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Trait)]);478    const STABILITY: AttributeStability = unstable!(rustc_attrs);479    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcTrivialFieldReads;480}481482pub(crate) struct RustcNoMirInlineParser;483484impl NoArgsAttributeParser for RustcNoMirInlineParser {485    const PATH: &[Symbol] = &[sym::rustc_no_mir_inline];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 = unstable!(rustc_attrs);494    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoMirInline;495}496497pub(crate) struct RustcNoWritableParser;498499impl NoArgsAttributeParser for RustcNoWritableParser {500    const PATH: &[Symbol] = &[sym::rustc_no_writable];501    const ON_DUPLICATE: OnDuplicate = OnDuplicate::Error;502    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[503        Allow(Target::Fn),504        Allow(Target::Closure),505        Allow(Target::Method(MethodKind::Inherent)),506        Allow(Target::Method(MethodKind::TraitImpl)),507        Allow(Target::Method(MethodKind::Trait { body: true })),508    ]);509    const STABILITY: AttributeStability = unstable!(rustc_attrs);510    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNoWritable;511}512513pub(crate) struct RustcLintQueryInstabilityParser;514515impl NoArgsAttributeParser for RustcLintQueryInstabilityParser {516    const PATH: &[Symbol] = &[sym::rustc_lint_query_instability];517    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[518        Allow(Target::Fn),519        Allow(Target::Method(MethodKind::Inherent)),520        Allow(Target::Method(MethodKind::Trait { body: false })),521        Allow(Target::Method(MethodKind::Trait { body: true })),522        Allow(Target::Method(MethodKind::TraitImpl)),523    ]);524    const STABILITY: AttributeStability = unstable!(rustc_attrs);525    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintQueryInstability;526}527528pub(crate) struct RustcRegionsParser;529530impl NoArgsAttributeParser for RustcRegionsParser {531    const PATH: &[Symbol] = &[sym::rustc_regions];532    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[533        Allow(Target::Fn),534        Allow(Target::Method(MethodKind::Inherent)),535        Allow(Target::Method(MethodKind::Trait { body: false })),536        Allow(Target::Method(MethodKind::Trait { body: true })),537        Allow(Target::Method(MethodKind::TraitImpl)),538    ]);539    const STABILITY: AttributeStability = unstable!(rustc_attrs);540    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcRegions;541}542543pub(crate) struct RustcLintUntrackedQueryInformationParser;544545impl NoArgsAttributeParser for RustcLintUntrackedQueryInformationParser {546    const PATH: &[Symbol] = &[sym::rustc_lint_untracked_query_information];547    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[548        Allow(Target::Fn),549        Allow(Target::Method(MethodKind::Inherent)),550        Allow(Target::Method(MethodKind::Trait { body: false })),551        Allow(Target::Method(MethodKind::Trait { body: true })),552        Allow(Target::Method(MethodKind::TraitImpl)),553    ]);554    const STABILITY: AttributeStability = unstable!(rustc_attrs);555    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcLintUntrackedQueryInformation;556}557558pub(crate) struct RustcSimdMonomorphizeLaneLimitParser;559560impl SingleAttributeParser for RustcSimdMonomorphizeLaneLimitParser {561    const PATH: &[Symbol] = &[sym::rustc_simd_monomorphize_lane_limit];562    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);563    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "N");564    const STABILITY: AttributeStability = unstable!(rustc_attrs);565566    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {567        let nv = cx.expect_name_value(args, cx.attr_span, None)?;568        Some(AttributeKind::RustcSimdMonomorphizeLaneLimit(cx.parse_limit_int(nv)?))569    }570}571572pub(crate) struct RustcScalableVectorParser;573574impl SingleAttributeParser for RustcScalableVectorParser {575    const PATH: &[Symbol] = &[sym::rustc_scalable_vector];576    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);577    const TEMPLATE: AttributeTemplate = template!(Word, List: &["count"]);578    const STABILITY: AttributeStability = unstable!(rustc_attrs);579580    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {581        if args.as_no_args().is_ok() {582            return Some(AttributeKind::RustcScalableVector { element_count: None });583        }584585        let n = parse_single_integer(cx, args)?;586        let Ok(n) = n.try_into() else {587            cx.emit_err(RustcScalableVectorCountOutOfRange { span: cx.attr_span, n });588            return None;589        };590        Some(AttributeKind::RustcScalableVector { element_count: Some(n) })591    }592}593594pub(crate) struct LangParser;595596impl SingleAttributeParser for LangParser {597    const PATH: &[Symbol] = &[sym::lang];598    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::ManuallyChecked;599    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");600    const STABILITY: AttributeStability = unstable!(lang_items);601602    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {603        let nv = cx.expect_name_value(args, cx.attr_span, None)?;604        let name = cx.expect_string_literal(nv)?;605        let Some(lang_item) = LangItem::from_name(name) else {606            cx.emit_err(UnknownLangItem { span: cx.attr_span, name });607            return None;608        };609610        // Only weak lang items may be applied to foreign items,611        // except for `ForeignTy` which can be a normal lang item.612        if [Target::ForeignFn, Target::ForeignStatic, Target::ForeignMod].contains(&cx.target)613            && !lang_item.is_weak()614        {615            cx.emit_err(UnknownExternLangItem { span: cx.attr_span, lang_item: lang_item.name() });616            return None;617        }618619        // Check the target620        let allowed_targets: &[_] = &[Allow(lang_item.target())];621        cx.check_target(&format!(" = \"{name}\""), &AllowedTargets::AllowList(allowed_targets));622623        Some(AttributeKind::Lang(lang_item))624    }625}626627pub(crate) struct RustcHasIncoherentInherentImplsParser;628629impl NoArgsAttributeParser for RustcHasIncoherentInherentImplsParser {630    const PATH: &[Symbol] = &[sym::rustc_has_incoherent_inherent_impls];631    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[632        Allow(Target::Trait),633        Allow(Target::Struct),634        Allow(Target::Enum),635        Allow(Target::Union),636        Allow(Target::ForeignTy),637    ]);638    const STABILITY: AttributeStability = unstable!(rustc_attrs);639    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcHasIncoherentInherentImpls;640}641642pub(crate) struct PanicHandlerParser;643644impl NoArgsAttributeParser for PanicHandlerParser {645    const PATH: &[Symbol] = &[sym::panic_handler];646    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);647    const STABILITY: AttributeStability = AttributeStability::Stable;648    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::Lang(LangItem::PanicImpl);649}650651pub(crate) struct RustcNounwindParser;652653impl NoArgsAttributeParser for RustcNounwindParser {654    const PATH: &[Symbol] = &[sym::rustc_nounwind];655    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[656        Allow(Target::Fn),657        Allow(Target::ForeignFn),658        Allow(Target::Method(MethodKind::Inherent)),659        Allow(Target::Method(MethodKind::TraitImpl)),660        Allow(Target::Method(MethodKind::Trait { body: true })),661    ]);662    const STABILITY: AttributeStability = unstable!(rustc_attrs);663    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNounwind;664}665666pub(crate) struct RustcOffloadKernelParser;667668impl NoArgsAttributeParser for RustcOffloadKernelParser {669    const PATH: &[Symbol] = &[sym::rustc_offload_kernel];670    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);671    const STABILITY: AttributeStability = unstable!(rustc_attrs);672    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcOffloadKernel;673}674675pub(crate) struct RustcMirParser;676677impl CombineAttributeParser for RustcMirParser {678    const PATH: &[Symbol] = &[sym::rustc_mir];679680    type Item = RustcMirKind;681682    const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcMir(items);683    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[684        Allow(Target::Fn),685        Allow(Target::Method(MethodKind::Inherent)),686        Allow(Target::Method(MethodKind::TraitImpl)),687        Allow(Target::Method(MethodKind::Trait { body: false })),688        Allow(Target::Method(MethodKind::Trait { body: true })),689    ]);690    const TEMPLATE: AttributeTemplate = template!(List: &["arg1, arg2, ..."]);691    const STABILITY: AttributeStability = unstable!(rustc_attrs);692693    fn extend(694        cx: &mut AcceptContext<'_, '_>,695        args: &ArgParser,696    ) -> impl IntoIterator<Item = Self::Item> {697        let Some(list) = cx.expect_list(args, cx.attr_span) else {698            return ThinVec::new();699        };700701        list.mixed()702            .filter_map(|arg| arg.meta_item())703            .filter_map(|mi| {704                if let Some(ident) = mi.ident() {705                    match ident.name {706                        sym::rustc_peek_maybe_init => Some(RustcMirKind::PeekMaybeInit),707                        sym::rustc_peek_maybe_uninit => Some(RustcMirKind::PeekMaybeUninit),708                        sym::rustc_peek_liveness => Some(RustcMirKind::PeekLiveness),709                        sym::stop_after_dataflow => Some(RustcMirKind::StopAfterDataflow),710                        sym::borrowck_graphviz_postflow => {711                            let nv = cx.expect_name_value(712                                mi.args(),713                                mi.span(),714                                Some(sym::borrowck_graphviz_postflow),715                            )?;716                            let path = cx.expect_string_literal(nv)?;717                            let path = PathBuf::from(path.to_string());718                            if path.file_name().is_some() {719                                Some(RustcMirKind::BorrowckGraphvizPostflow { path })720                            } else {721                                cx.adcx().expected_filename_literal(nv.value_span);722                                None723                            }724                        }725                        sym::borrowck_graphviz_format => {726                            let nv = cx.expect_name_value(727                                mi.args(),728                                mi.span(),729                                Some(sym::borrowck_graphviz_format),730                            )?;731                            let Some(format) = nv.value_as_ident() else {732                                cx.adcx().expected_identifier(nv.value_span);733                                return None;734                            };735                            match format.name {736                                sym::two_phase => Some(RustcMirKind::BorrowckGraphvizFormat {737                                    format: BorrowckGraphvizFormatKind::TwoPhase,738                                }),739                                _ => {740                                    cx.adcx()741                                        .expected_specific_argument(format.span, &[sym::two_phase]);742                                    None743                                }744                            }745                        }746                        _ => None,747                    }748                } else {749                    None750                }751            })752            .collect()753    }754}755pub(crate) struct RustcNonConstTraitMethodParser;756757impl NoArgsAttributeParser for RustcNonConstTraitMethodParser {758    const PATH: &[Symbol] = &[sym::rustc_non_const_trait_method];759    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[760        Allow(Target::Method(MethodKind::Trait { body: true })),761        Allow(Target::Method(MethodKind::Trait { body: false })),762    ]);763    const STABILITY: AttributeStability = unstable!(764        rustc_attrs,765        "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"766    );767    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonConstTraitMethod;768}769770pub(crate) struct RustcCleanParser;771772impl CombineAttributeParser for RustcCleanParser {773    const PATH: &[Symbol] = &[sym::rustc_clean];774775    type Item = RustcCleanAttribute;776777    const CONVERT: ConvertFn<Self::Item> = |items, _| AttributeKind::RustcClean(items);778    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[779        // tidy-alphabetical-start780        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),781        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),782        Allow(Target::AssocConst(AssocCtxt::Trait)),783        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),784        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),785        Allow(Target::AssocTy(AssocCtxt::Trait)),786        Allow(Target::Const),787        Allow(Target::Enum),788        Allow(Target::Expression),789        Allow(Target::Field),790        Allow(Target::Fn),791        Allow(Target::ForeignMod),792        Allow(Target::Impl { of_trait: false }),793        Allow(Target::Impl { of_trait: true }),794        Allow(Target::Method(MethodKind::Inherent)),795        Allow(Target::Method(MethodKind::Trait { body: false })),796        Allow(Target::Method(MethodKind::Trait { body: true })),797        Allow(Target::Method(MethodKind::TraitImpl)),798        Allow(Target::Mod),799        Allow(Target::Static),800        Allow(Target::Struct),801        Allow(Target::Trait),802        Allow(Target::TyAlias),803        Allow(Target::Union),804        // tidy-alphabetical-end805    ]);806    const STABILITY: AttributeStability = unstable!(rustc_attrs);807    const TEMPLATE: AttributeTemplate =808        template!(List: &[r#"cfg = "...", /*opt*/ label = "...", /*opt*/ except = "...""#]);809810    fn extend(811        cx: &mut AcceptContext<'_, '_>,812        args: &ArgParser,813    ) -> impl IntoIterator<Item = Self::Item> {814        if !cx.cx.sess.opts.unstable_opts.query_dep_graph {815            cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });816        }817        let list = cx.expect_list(args, cx.attr_span)?;818819        let mut except = None;820        let mut loaded_from_disk = None;821        let mut cfg = None;822823        for item in list.mixed() {824            let Some((ident, value)) = cx.expect_name_value(item, item.span(), None) else {825                continue;826            };827            let value_span = value.value_span;828            let Some(value) = cx.expect_string_literal(value) else {829                continue;830            };831            match ident.name {832                sym::cfg if cfg.is_some() => {833                    cx.adcx().duplicate_key(item.span(), sym::cfg);834                }835                sym::cfg => {836                    cfg = Some(value);837                }838                sym::except if except.is_some() => {839                    cx.adcx().duplicate_key(item.span(), sym::except);840                }841                sym::except => {842                    let entries =843                        value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();844                    except = Some(RustcCleanQueries { entries, span: value_span });845                }846                sym::loaded_from_disk if loaded_from_disk.is_some() => {847                    cx.adcx().duplicate_key(item.span(), sym::loaded_from_disk);848                }849                sym::loaded_from_disk => {850                    let entries =851                        value.as_str().split(',').map(|s| Symbol::intern(s.trim())).collect();852                    loaded_from_disk = Some(RustcCleanQueries { entries, span: value_span });853                }854                _ => {855                    cx.adcx().expected_specific_argument(856                        ident.span,857                        &[sym::cfg, sym::except, sym::loaded_from_disk],858                    );859                }860            }861        }862        let Some(cfg) = cfg else {863            cx.adcx().expected_specific_argument(list.span, &[sym::cfg]);864            return None;865        };866867        Some(RustcCleanAttribute { span: cx.attr_span, cfg, except, loaded_from_disk })868    }869}870871pub(crate) struct RustcIfThisChangedParser;872873impl SingleAttributeParser for RustcIfThisChangedParser {874    const PATH: &[Symbol] = &[sym::rustc_if_this_changed];875    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[876        // tidy-alphabetical-start877        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),878        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),879        Allow(Target::AssocConst(AssocCtxt::Trait)),880        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),881        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),882        Allow(Target::AssocTy(AssocCtxt::Trait)),883        Allow(Target::Const),884        Allow(Target::Enum),885        Allow(Target::Expression),886        Allow(Target::Field),887        Allow(Target::Fn),888        Allow(Target::ForeignMod),889        Allow(Target::Impl { of_trait: false }),890        Allow(Target::Impl { of_trait: true }),891        Allow(Target::Method(MethodKind::Inherent)),892        Allow(Target::Method(MethodKind::Trait { body: false })),893        Allow(Target::Method(MethodKind::Trait { body: true })),894        Allow(Target::Method(MethodKind::TraitImpl)),895        Allow(Target::Mod),896        Allow(Target::Static),897        Allow(Target::Struct),898        Allow(Target::Trait),899        Allow(Target::TyAlias),900        Allow(Target::Union),901        // tidy-alphabetical-end902    ]);903    const TEMPLATE: AttributeTemplate = template!(Word, List: &["DepNode"]);904    const STABILITY: AttributeStability = unstable!(rustc_attrs);905906    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {907        if !cx.cx.sess.opts.unstable_opts.query_dep_graph {908            cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });909        }910        match args {911            ArgParser::NoArgs => Some(AttributeKind::RustcIfThisChanged(cx.attr_span, None)),912            ArgParser::List(list) => {913                let item = cx.expect_single(list)?;914                let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {915                    cx.adcx().expected_identifier(item.span());916                    return None;917                };918                Some(AttributeKind::RustcIfThisChanged(cx.attr_span, Some(ident.name)))919            }920            ArgParser::NameValue(_) => {921                let inner_span = cx.inner_span;922                cx.adcx().expected_list_or_no_args(inner_span);923                None924            }925        }926    }927}928929pub(crate) struct RustcThenThisWouldNeedParser;930931impl CombineAttributeParser for RustcThenThisWouldNeedParser {932    const PATH: &[Symbol] = &[sym::rustc_then_this_would_need];933    type Item = Ident;934935    const CONVERT: ConvertFn<Self::Item> =936        |items, _span| AttributeKind::RustcThenThisWouldNeed(items);937    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[938        // tidy-alphabetical-start939        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),940        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),941        Allow(Target::AssocConst(AssocCtxt::Trait)),942        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),943        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),944        Allow(Target::AssocTy(AssocCtxt::Trait)),945        Allow(Target::Const),946        Allow(Target::Enum),947        Allow(Target::Expression),948        Allow(Target::Field),949        Allow(Target::Fn),950        Allow(Target::ForeignMod),951        Allow(Target::Impl { of_trait: false }),952        Allow(Target::Impl { of_trait: true }),953        Allow(Target::Method(MethodKind::Inherent)),954        Allow(Target::Method(MethodKind::Trait { body: false })),955        Allow(Target::Method(MethodKind::Trait { body: true })),956        Allow(Target::Method(MethodKind::TraitImpl)),957        Allow(Target::Mod),958        Allow(Target::Static),959        Allow(Target::Struct),960        Allow(Target::Trait),961        Allow(Target::TyAlias),962        Allow(Target::Union),963        // tidy-alphabetical-end964    ]);965    const TEMPLATE: AttributeTemplate = template!(List: &["DepNode"]);966    const STABILITY: AttributeStability = unstable!(rustc_attrs);967968    fn extend(969        cx: &mut AcceptContext<'_, '_>,970        args: &ArgParser,971    ) -> impl IntoIterator<Item = Self::Item> {972        if !cx.cx.sess.opts.unstable_opts.query_dep_graph {973            cx.emit_err(AttributeRequiresOpt { span: cx.attr_span, opt: "-Z query-dep-graph" });974        }975        let item = cx.expect_single_element_list(args, cx.attr_span)?;976        let Some(ident) = item.meta_item_no_args().and_then(|item| item.ident()) else {977            cx.adcx().expected_identifier(item.span());978            return None;979        };980        Some(ident)981    }982}983984pub(crate) struct RustcInsignificantDtorParser;985986impl NoArgsAttributeParser for RustcInsignificantDtorParser {987    const PATH: &[Symbol] = &[sym::rustc_insignificant_dtor];988    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[989        Allow(Target::Enum),990        Allow(Target::Struct),991        Allow(Target::ForeignTy),992    ]);993    const STABILITY: AttributeStability = unstable!(rustc_attrs);994    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcInsignificantDtor;995}996997pub(crate) struct RustcEffectiveVisibilityParser;998999impl NoArgsAttributeParser for RustcEffectiveVisibilityParser {1000    const PATH: &[Symbol] = &[sym::rustc_effective_visibility];1001    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[1002        Allow(Target::Use),1003        Allow(Target::Static),1004        Allow(Target::Const),1005        Allow(Target::Fn),1006        Allow(Target::Closure),1007        Allow(Target::Mod),1008        Allow(Target::ForeignMod),1009        Allow(Target::TyAlias),1010        Allow(Target::Enum),1011        Allow(Target::Variant),1012        Allow(Target::Struct),1013        Allow(Target::Field),1014        Allow(Target::Union),1015        Allow(Target::Trait),1016        Allow(Target::TraitAlias),1017        Allow(Target::Impl { of_trait: false }),1018        Allow(Target::Impl { of_trait: true }),1019        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),1020        Allow(Target::AssocConst(AssocCtxt::Trait)),1021        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),1022        Allow(Target::Method(MethodKind::Inherent)),1023        Allow(Target::Method(MethodKind::Trait { body: false })),1024        Allow(Target::Method(MethodKind::Trait { body: true })),1025        Allow(Target::Method(MethodKind::TraitImpl)),1026        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),1027        Allow(Target::AssocTy(AssocCtxt::Trait)),1028        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),1029        Allow(Target::ForeignFn),1030        Allow(Target::ForeignStatic),1031        Allow(Target::ForeignTy),1032        Allow(Target::MacroDef),1033        Allow(Target::PatField),1034        Allow(Target::Crate),1035    ]);1036    const STABILITY: AttributeStability = unstable!(rustc_attrs);1037    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcEffectiveVisibility;1038}10391040pub(crate) struct RustcDiagnosticItemParser;10411042impl SingleAttributeParser for RustcDiagnosticItemParser {1043    const PATH: &[Symbol] = &[sym::rustc_diagnostic_item];1044    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[1045        Allow(Target::Trait),1046        Allow(Target::Struct),1047        Allow(Target::Enum),1048        Allow(Target::MacroDef),1049        Allow(Target::TyAlias),1050        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: false })),1051        Allow(Target::AssocConst(AssocCtxt::Trait)),1052        Allow(Target::AssocConst(AssocCtxt::Impl { of_trait: true })),1053        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: false })),1054        Allow(Target::AssocTy(AssocCtxt::Trait)),1055        Allow(Target::AssocTy(AssocCtxt::Impl { of_trait: true })),1056        Allow(Target::Fn),1057        Allow(Target::Const),1058        Allow(Target::Mod),1059        Allow(Target::Impl { of_trait: false }),1060        Allow(Target::Method(MethodKind::Inherent)),1061        Allow(Target::Method(MethodKind::Trait { body: false })),1062        Allow(Target::Method(MethodKind::Trait { body: true })),1063        Allow(Target::Method(MethodKind::TraitImpl)),1064        Allow(Target::Crate),1065    ]);1066    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "name");1067    const STABILITY: AttributeStability = unstable!(1068        rustc_attrs,1069        "the `rustc_diagnostic_item` attribute allows the compiler to reference types from the standard library for diagnostic purposes"1070    );10711072    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {1073        let nv = cx.expect_name_value(args, cx.attr_span, None)?;1074        let value = cx.expect_string_literal(nv)?;1075        Some(AttributeKind::RustcDiagnosticItem(value))1076    }1077}10781079pub(crate) struct RustcDoNotConstCheckParser;10801081impl NoArgsAttributeParser for RustcDoNotConstCheckParser {1082    const PATH: &[Symbol] = &[sym::rustc_do_not_const_check];1083    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[1084        Allow(Target::Fn),1085        Allow(Target::Method(MethodKind::Inherent)),1086        Allow(Target::Method(MethodKind::TraitImpl)),1087        Allow(Target::Method(MethodKind::Trait { body: false })),1088        Allow(Target::Method(MethodKind::Trait { body: true })),1089    ]);1090    const STABILITY: AttributeStability = unstable!(1091        rustc_attrs,1092        "the `rustc_do_not_const_check` attribute skips const-check for this function's body"1093    );1094    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcDoNotConstCheck;1095}10961097pub(crate) struct RustcNonnullOptimizationGuaranteedParser;10981099impl NoArgsAttributeParser for RustcNonnullOptimizationGuaranteedParser {1100    const PATH: &[Symbol] = &[sym::rustc_nonnull_optimization_guaranteed];1101    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Struct)]);1102    const STABILITY: AttributeStability = unstable!(1103        rustc_attrs,1104        "the `rustc_nonnull_optimization_guaranteed` attribute is just used to document guaranteed niche optimizations in the standard library",1105        "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"1106    );1107    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcNonnullOptimizationGuaranteed;1108}11091110pub(crate) struct RustcStrictCoherenceParser;11111112impl NoArgsAttributeParser for RustcStrictCoherenceParser {1113    const PATH: &[Symbol] = &[sym::rustc_strict_coherence];1114    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[1115        Allow(Target::Trait),1116        Allow(Target::Struct),1117        Allow(Target::Enum),1118        Allow(Target::Union),1119        Allow(Target::ForeignTy),1120    ]);1121    const STABILITY: AttributeStability = unstable!(rustc_attrs);1122    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcStrictCoherence;1123}11241125pub(crate) struct RustcReservationImplParser;11261127impl SingleAttributeParser for RustcReservationImplParser {1128    const PATH: &[Symbol] = &[sym::rustc_reservation_impl];1129    const ALLOWED_TARGETS: AllowedTargets<'_> =1130        AllowedTargets::AllowList(&[Allow(Target::Impl { of_trait: true })]);1131    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "reservation message");1132    const STABILITY: AttributeStability = unstable!(rustc_attrs);11331134    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {1135        let nv = cx.expect_name_value(args, cx.attr_span, None)?;1136        let value_str = cx.expect_string_literal(nv)?;11371138        Some(AttributeKind::RustcReservationImpl(value_str))1139    }1140}11411142pub(crate) struct PreludeImportParser;11431144impl NoArgsAttributeParser for PreludeImportParser {1145    const PATH: &[Symbol] = &[sym::prelude_import];1146    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Use)]);1147    const STABILITY: AttributeStability = unstable!(prelude_import);1148    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::PreludeImport;1149}11501151pub(crate) struct RustcDocPrimitiveParser;11521153impl SingleAttributeParser for RustcDocPrimitiveParser {1154    const PATH: &[Symbol] = &[sym::rustc_doc_primitive];1155    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Const)]);1156    const TEMPLATE: AttributeTemplate = template!(NameValueStr: "primitive name");1157    const STABILITY: AttributeStability = unstable!(1158        rustc_attrs,1159        "the `rustc_doc_primitive` attribute is used by the standard library to provide a way to generate documentation for primitive types"1160    );11611162    fn convert(cx: &mut AcceptContext<'_, '_>, args: &ArgParser) -> Option<AttributeKind> {1163        let nv = cx.expect_name_value(args, cx.attr_span, None)?;1164        let value_str = cx.expect_string_literal(nv)?;11651166        Some(AttributeKind::RustcDocPrimitive(cx.attr_span, value_str))1167    }1168}11691170pub(crate) struct RustcIntrinsicParser;11711172impl NoArgsAttributeParser for RustcIntrinsicParser {1173    const PATH: &[Symbol] = &[sym::rustc_intrinsic];1174    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);1175    const STABILITY: AttributeStability = unstable!(intrinsics);1176    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsic;1177}11781179pub(crate) struct RustcIntrinsicConstStableIndirectParser;11801181impl NoArgsAttributeParser for RustcIntrinsicConstStableIndirectParser {1182    const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];1183    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Fn)]);1184    const STABILITY: AttributeStability = unstable!(rustc_attrs);1185    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcIntrinsicConstStableIndirect;1186}11871188pub(crate) struct RustcExhaustiveParser;11891190impl NoArgsAttributeParser for RustcExhaustiveParser {1191    const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively];1192    const ALLOWED_TARGETS: AllowedTargets<'_> = AllowedTargets::AllowList(&[Allow(Target::Enum)]);1193    const STABILITY: AttributeStability = unstable!(rustc_attrs);1194    const CREATE: fn(Span) -> AttributeKind = AttributeKind::RustcMustMatchExhaustively;1195}11961197pub(crate) struct RustcCanonicalSymbolParser;11981199impl NoArgsAttributeParser for RustcCanonicalSymbolParser {1200    const PATH: &[Symbol] = &[sym::rustc_canonical_symbol];1201    const ALLOWED_TARGETS: AllowedTargets<'_> =1202        AllowedTargets::AllowList(&[Allow(Target::ForeignFn)]);1203    const STABILITY: AttributeStability = unstable!(1204        rustc_attrs,1205        "the `rustc_canonical_symbol` attribute registers a function's symbol to be linted against \1206        by the `invalid_runtime_symbol_definitions` and `suspicious_runtime_symbol_definitions` \1207        lints"1208    );1209    const CREATE: fn(Span) -> AttributeKind = |_| AttributeKind::RustcCanonicalSymbol;1210}

Code quality findings 11

Warning: '.unwrap()' will panic on None/Err variants. Prefer using pattern matching (match, if let), combinators (map, and_then), or the '?' operator for robust error handling.
warning correctness unwrap-usage
(cx.attr_span, CguFields::ExpectedCguReuse { cfg, module, kind: kind.unwrap() })
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
if [Target::ForeignFn, Target::ForeignStatic, Target::ForeignMod].contains(&cx.target)
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
const PATH: &'static [Symbol] = &[sym::rustc_intrinsic_const_stable_indirect];
Warning: Direct indexing (e.g., `vec[i]`, `slice[i]`) panics on out-of-bounds access. Prefer using `.get(index)` or `.get_mut(index)` which return Option<&T>/Option<&mut T>.
warning correctness unchecked-indexing
const PATH: &'static [Symbol] = &[sym::rustc_must_match_exhaustively];
Info: Wildcard imports (`use some::path::*;`) can obscure the origin of names and lead to conflicts. Prefer importing specific items explicitly.
info maintainability wildcard-import
use super::prelude::*;
Performance Info: Calling .push() repeatedly inside a loop without prior capacity reservation can lead to multiple reallocations. Consider using `Vec::with_capacity(n)` or `vec.reserve(n)` if the approximate number of elements is known.
info performance push-without-reserve
fn_names.push(ident);
Performance Info: Calling .push() repeatedly inside a loop without prior capacity reservation can lead to multiple reallocations. Consider using `Vec::with_capacity(n)` or `vec.reserve(n)` if the approximate number of elements is known.
info performance push-without-reserve
parsed_indexes.push((index.0 as usize, possible_index.span()));
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let res = match ident.name {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
Some(match kind {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
let res = match ident.name {
Info: Ensure 'match' statements are exhaustive. If matching on enums, consider adding a wildcard arm `_ => {}` only if necessary and intentional, as it suppresses warnings about unhandled variants.
info correctness match-wildcard
match format.name {

Get this view in your editor

Same data, no extra tab — call code_get_file + code_get_findings over MCP from Claude/Cursor/Copilot.