compiler/rustc_attr_parsing/src/context.rs RUST 1,053 lines View on github.com → Search inside
1use std::cell::RefCell;2use std::collections::BTreeMap;3use std::collections::btree_map::Entry;4use std::mem;5use std::ops::{Deref, DerefMut};6use std::sync::LazyLock;78use rustc_ast::{AttrStyle, MetaItemLit};9use rustc_data_structures::sync::{DynSend, DynSync};10use rustc_errors::{Diag, DiagCtxtHandle, Diagnostic, Level, MultiSpan};11use rustc_feature::{AttrSuggestionStyle, AttributeTemplate};12use rustc_hir::AttrPath;13use rustc_hir::attrs::AttributeKind;14use rustc_parse::parser::Recovery;15use rustc_session::Session;16use rustc_session::lint::{Lint, LintId};17use rustc_span::{ErrorGuaranteed, Ident, Span, Symbol};1819// Glob imports to avoid big, bitrotty import lists20use crate::attributes::allow_unstable::*;21use crate::attributes::autodiff::*;22use crate::attributes::body::*;23use crate::attributes::cfi_encoding::*;24use crate::attributes::codegen_attrs::*;25use crate::attributes::confusables::*;26use crate::attributes::crate_level::*;27use crate::attributes::debugger::*;28use crate::attributes::deprecation::*;29use crate::attributes::diagnostic::do_not_recommend::*;30use crate::attributes::diagnostic::on_const::*;31use crate::attributes::diagnostic::on_move::*;32use crate::attributes::diagnostic::on_unimplemented::*;33use crate::attributes::diagnostic::on_unknown::*;34use crate::attributes::diagnostic::on_unmatch_args::*;35use crate::attributes::doc::*;36use crate::attributes::dummy::*;37use crate::attributes::inline::*;38use crate::attributes::instruction_set::*;39use crate::attributes::link_attrs::*;40use crate::attributes::lint_helpers::*;41use crate::attributes::loop_match::*;42use crate::attributes::macro_attrs::*;43use crate::attributes::must_not_suspend::*;44use crate::attributes::must_use::*;45use crate::attributes::no_implicit_prelude::*;46use crate::attributes::no_link::*;47use crate::attributes::non_exhaustive::*;48use crate::attributes::path::PathParser as PathAttributeParser;49use crate::attributes::pin_v2::*;50use crate::attributes::proc_macro_attrs::*;51use crate::attributes::prototype::*;52use crate::attributes::repr::*;53use crate::attributes::rustc_allocator::*;54use crate::attributes::rustc_dump::*;55use crate::attributes::rustc_internal::*;56use crate::attributes::semantics::*;57use crate::attributes::stability::*;58use crate::attributes::test_attrs::*;59use crate::attributes::traits::*;60use crate::attributes::transparency::*;61use crate::attributes::{AttributeParser as _, AttributeSafety, Combine, Single, WithoutArgs};62use crate::parser::{63    ArgParser, MetaItemListParser, MetaItemOrLitParser, MetaItemParser, NameValueParser,64    RefPathParser,65};66use crate::session_diagnostics::{67    AttributeParseError, AttributeParseErrorReason, AttributeParseErrorSuggestions,68    ParsedDescription,69};70use crate::target_checking::AllowedTargets;71use crate::{AttributeParser, EmitAttribute};7273type GroupType = LazyLock<GroupTypeInner>;7475pub(super) struct GroupTypeInner {76    pub(super) accepters: BTreeMap<&'static [Symbol], GroupTypeInnerAccept>,77}7879pub(super) struct GroupTypeInnerAccept {80    pub(super) template: AttributeTemplate,81    pub(super) accept_fn: AcceptFn,82    pub(super) allowed_targets: AllowedTargets,83    pub(super) safety: AttributeSafety,84    pub(super) finalizer: FinalizeFn,85}8687pub(crate) type AcceptFn =88    Box<dyn for<'sess, 'a> Fn(&mut AcceptContext<'_, 'sess>, &ArgParser) + Send + Sync>;89pub(crate) type FinalizeFn = fn(&mut FinalizeContext<'_, '_>) -> Option<AttributeKind>;9091macro_rules! attribute_parsers {92    (93        pub(crate) static $name: ident = [$($names: ty),* $(,)?];94    ) => {95        pub(crate) static $name: GroupType = LazyLock::new(|| {96            let mut accepters = BTreeMap::<_, GroupTypeInnerAccept>::new();97            $(98                {99                    thread_local! {100                        static STATE_OBJECT: RefCell<$names> = RefCell::new(<$names>::default());101                    };102103                    for (path, template, accept_fn) in <$names>::ATTRIBUTES {104                        match accepters.entry(*path) {105                            Entry::Vacant(e) => {106                                e.insert(GroupTypeInnerAccept {107                                    template: *template,108                                    accept_fn: Box::new(|cx, args| {109                                        STATE_OBJECT.with_borrow_mut(|s| {110                                            accept_fn(s, cx, args)111                                        })112                                    }),113                                    safety: <$names as crate::attributes::AttributeParser>::SAFETY,114                                    allowed_targets: <$names as crate::attributes::AttributeParser>::ALLOWED_TARGETS,115                                    finalizer: |cx| {116                                        let state = STATE_OBJECT.take();117                                        state.finalize(cx)118                                    }119                                });120                            }121                            Entry::Occupied(_) => panic!("Attribute {path:?} has multiple accepters"),122                        }123                    }124                }125            )*126127            GroupTypeInner { accepters }128        });129    };130}131attribute_parsers!(132    pub(crate) static ATTRIBUTE_PARSERS = [133        // tidy-alphabetical-start134        BodyStabilityParser,135        ConfusablesParser,136        ConstStabilityParser,137        DocParser,138        MacroUseParser,139        NakedParser,140        OnConstParser,141        OnMoveParser,142        OnUnimplementedParser,143        OnUnknownParser,144        OnUnmatchArgsParser,145        RustcAlignParser,146        RustcAlignStaticParser,147        RustcCguTestAttributeParser,148        StabilityParser,149        UsedParser,150        // tidy-alphabetical-end151152        // tidy-alphabetical-start153        Combine<AllowInternalUnstableParser>,154        Combine<CrateTypeParser>,155        Combine<DebuggerViualizerParser>,156        Combine<FeatureParser>,157        Combine<ForceTargetFeatureParser>,158        Combine<LinkParser>,159        Combine<RegisterToolParser>,160        Combine<ReprParser>,161        Combine<RustcAllowConstFnUnstableParser>,162        Combine<RustcCleanParser>,163        Combine<RustcDumpLayoutParser>,164        Combine<RustcMirParser>,165        Combine<RustcThenThisWouldNeedParser>,166        Combine<TargetFeatureParser>,167        Combine<UnstableFeatureBoundParser>,168        Combine<UnstableRemovedParser>,169        // tidy-alphabetical-end170171        // tidy-alphabetical-start172        Single<CfiEncodingParser>,173        Single<CollapseDebugInfoParser>,174        Single<CoverageParser>,175        Single<CrateNameParser>,176        Single<CustomMirParser>,177        Single<DeprecatedParser>,178        Single<DoNotRecommendParser>,179        Single<ExportNameParser>,180        Single<IgnoreParser>,181        Single<InlineParser>,182        Single<InstructionSetParser>,183        Single<LangParser>,184        Single<LinkNameParser>,185        Single<LinkOrdinalParser>,186        Single<LinkSectionParser>,187        Single<LinkageParser>,188        Single<MacroExportParser>,189        Single<MoveSizeLimitParser>,190        Single<MustNotSuspendParser>,191        Single<MustUseParser>,192        Single<OptimizeParser>,193        Single<PatchableFunctionEntryParser>,194        Single<PathAttributeParser>,195        Single<PatternComplexityLimitParser>,196        Single<ProcMacroDeriveParser>,197        Single<RecursionLimitParser>,198        Single<ReexportTestHarnessMainParser>,199        Single<RustcAbiParser>,200        Single<RustcAllocatorZeroedVariantParser>,201        Single<RustcAutodiffParser>,202        Single<RustcBuiltinMacroParser>,203        Single<RustcDeprecatedSafe2024Parser>,204        Single<RustcDiagnosticItemParser>,205        Single<RustcDocPrimitiveParser>,206        Single<RustcDummyParser>,207        Single<RustcDumpDefPathParser>,208        Single<RustcDumpSymbolNameParser>,209        Single<RustcForceInlineParser>,210        Single<RustcIfThisChangedParser>,211        Single<RustcLegacyConstGenericsParser>,212        Single<RustcLintOptDenyFieldAccessParser>,213        Single<RustcMacroTransparencyParser>,214        Single<RustcMustImplementOneOfParser>,215        Single<RustcNeverTypeOptionsParser>,216        Single<RustcObjcClassParser>,217        Single<RustcObjcSelectorParser>,218        Single<RustcReservationImplParser>,219        Single<RustcScalableVectorParser>,220        Single<RustcSimdMonomorphizeLaneLimitParser>,221        Single<RustcSkipDuringMethodDispatchParser>,222        Single<RustcTestMarkerParser>,223        Single<SanitizeParser>,224        Single<ShouldPanicParser>,225        Single<TestRunnerParser>,226        Single<TypeLengthLimitParser>,227        Single<WindowsSubsystemParser>,228        Single<WithoutArgs<AllowInternalUnsafeParser>>,229        Single<WithoutArgs<AutomaticallyDerivedParser>>,230        Single<WithoutArgs<ColdParser>>,231        Single<WithoutArgs<CompilerBuiltinsParser>>,232        Single<WithoutArgs<ConstContinueParser>>,233        Single<WithoutArgs<CoroutineParser>>,234        Single<WithoutArgs<DefaultLibAllocatorParser>>,235        Single<WithoutArgs<ExportStableParser>>,236        Single<WithoutArgs<FfiConstParser>>,237        Single<WithoutArgs<FfiPureParser>>,238        Single<WithoutArgs<FundamentalParser>>,239        Single<WithoutArgs<LoopMatchParser>>,240        Single<WithoutArgs<MacroEscapeParser>>,241        Single<WithoutArgs<MarkerParser>>,242        Single<WithoutArgs<MayDangleParser>>,243        Single<WithoutArgs<NeedsAllocatorParser>>,244        Single<WithoutArgs<NeedsPanicRuntimeParser>>,245        Single<WithoutArgs<NoBuiltinsParser>>,246        Single<WithoutArgs<NoCoreParser>>,247        Single<WithoutArgs<NoImplicitPreludeParser>>,248        Single<WithoutArgs<NoLinkParser>>,249        Single<WithoutArgs<NoMainParser>>,250        Single<WithoutArgs<NoMangleParser>>,251        Single<WithoutArgs<NoStdParser>>,252        Single<WithoutArgs<NonExhaustiveParser>>,253        Single<WithoutArgs<PanicHandlerParser>>,254        Single<WithoutArgs<PanicRuntimeParser>>,255        Single<WithoutArgs<PinV2Parser>>,256        Single<WithoutArgs<PreludeImportParser>>,257        Single<WithoutArgs<ProcMacroAttributeParser>>,258        Single<WithoutArgs<ProcMacroParser>>,259        Single<WithoutArgs<ProfilerRuntimeParser>>,260        Single<WithoutArgs<RustcAllocatorParser>>,261        Single<WithoutArgs<RustcAllocatorZeroedParser>>,262        Single<WithoutArgs<RustcAllowIncoherentImplParser>>,263        Single<WithoutArgs<RustcAsPtrParser>>,264        Single<WithoutArgs<RustcCaptureAnalysisParser>>,265        Single<WithoutArgs<RustcCoherenceIsCoreParser>>,266        Single<WithoutArgs<RustcCoinductiveParser>>,267        Single<WithoutArgs<RustcConstStableIndirectParser>>,268        Single<WithoutArgs<RustcConversionSuggestionParser>>,269        Single<WithoutArgs<RustcDeallocatorParser>>,270        Single<WithoutArgs<RustcDelayedBugFromInsideQueryParser>>,271        Single<WithoutArgs<RustcDenyExplicitImplParser>>,272        Single<WithoutArgs<RustcDoNotConstCheckParser>>,273        Single<WithoutArgs<RustcDumpDefParentsParser>>,274        Single<WithoutArgs<RustcDumpHiddenTypeOfOpaquesParser>>,275        Single<WithoutArgs<RustcDumpInferredOutlivesParser>>,276        Single<WithoutArgs<RustcDumpItemBoundsParser>>,277        Single<WithoutArgs<RustcDumpObjectLifetimeDefaultsParser>>,278        Single<WithoutArgs<RustcDumpPredicatesParser>>,279        Single<WithoutArgs<RustcDumpUserArgsParser>>,280        Single<WithoutArgs<RustcDumpVariancesOfOpaquesParser>>,281        Single<WithoutArgs<RustcDumpVariancesParser>>,282        Single<WithoutArgs<RustcDumpVtableParser>>,283        Single<WithoutArgs<RustcDynIncompatibleTraitParser>>,284        Single<WithoutArgs<RustcEffectiveVisibilityParser>>,285        Single<WithoutArgs<RustcEiiForeignItemParser>>,286        Single<WithoutArgs<RustcEvaluateWhereClausesParser>>,287        Single<WithoutArgs<RustcExhaustiveParser>>,288        Single<WithoutArgs<RustcHasIncoherentInherentImplsParser>>,289        Single<WithoutArgs<RustcInheritOverflowChecksParser>>,290        Single<WithoutArgs<RustcInsignificantDtorParser>>,291        Single<WithoutArgs<RustcIntrinsicConstStableIndirectParser>>,292        Single<WithoutArgs<RustcIntrinsicParser>>,293        Single<WithoutArgs<RustcLintOptTyParser>>,294        Single<WithoutArgs<RustcLintQueryInstabilityParser>>,295        Single<WithoutArgs<RustcLintUntrackedQueryInformationParser>>,296        Single<WithoutArgs<RustcMainParser>>,297        Single<WithoutArgs<RustcNeverReturnsNullPtrParser>>,298        Single<WithoutArgs<RustcNoImplicitAutorefsParser>>,299        Single<WithoutArgs<RustcNoImplicitBoundsParser>>,300        Single<WithoutArgs<RustcNoMirInlineParser>>,301        Single<WithoutArgs<RustcNoWritableParser>>,302        Single<WithoutArgs<RustcNonConstTraitMethodParser>>,303        Single<WithoutArgs<RustcNonnullOptimizationGuaranteedParser>>,304        Single<WithoutArgs<RustcNounwindParser>>,305        Single<WithoutArgs<RustcOffloadKernelParser>>,306        Single<WithoutArgs<RustcParenSugarParser>>,307        Single<WithoutArgs<RustcPassByValueParser>>,308        Single<WithoutArgs<RustcPassIndirectlyInNonRusticAbisParser>>,309        Single<WithoutArgs<RustcPreserveUbChecksParser>>,310        Single<WithoutArgs<RustcProcMacroDeclsParser>>,311        Single<WithoutArgs<RustcPubTransparentParser>>,312        Single<WithoutArgs<RustcReallocatorParser>>,313        Single<WithoutArgs<RustcRegionsParser>>,314        Single<WithoutArgs<RustcShouldNotBeCalledOnConstItemsParser>>,315        Single<WithoutArgs<RustcSpecializationTraitParser>>,316        Single<WithoutArgs<RustcStdInternalSymbolParser>>,317        Single<WithoutArgs<RustcStrictCoherenceParser>>,318        Single<WithoutArgs<RustcTrivialFieldReadsParser>>,319        Single<WithoutArgs<RustcUnsafeSpecializationMarkerParser>>,320        Single<WithoutArgs<ThreadLocalParser>>,321        Single<WithoutArgs<TrackCallerParser>>,322        // tidy-alphabetical-end323    ];324);325326/// Context given to every attribute parser when accepting327///328/// Gives [`AttributeParser`]s enough information to create errors, for example.329pub struct AcceptContext<'f, 'sess> {330    pub(crate) shared: SharedContext<'f, 'sess>,331332    /// The outer span of the attribute currently being parsed333    ///334    /// ```none335    /// #[attribute(...)]336    /// ^^^^^^^^^^^^^^^^^ outer span337    /// ```338    /// For attributes in `cfg_attr`, the outer span and inner spans are equal.339    pub(crate) attr_span: Span,340    /// The inner span of the attribute currently being parsed.341    ///342    /// ```none343    /// #[attribute(...)]344    ///   ^^^^^^^^^^^^^^  inner span345    /// ```346    pub(crate) inner_span: Span,347348    /// Whether it is an inner or outer attribute.349    pub(crate) attr_style: AttrStyle,350351    /// A description of the thing we are parsing using this attribute parser.352    /// We are not only using these parsers for attributes, but also for macros such as the `cfg!()` macro.353    pub(crate) parsed_description: ParsedDescription,354355    /// The expected structure of the attribute.356    ///357    /// Used in reporting errors to give a hint to users what the attribute *should* look like.358    pub(crate) template: &'f AttributeTemplate,359360    /// The name of the attribute we're currently accepting.361    pub(crate) attr_path: AttrPath,362}363364impl<'f, 'sess: 'f> SharedContext<'f, 'sess> {365    pub(crate) fn emit_err(&self, diag: impl for<'x> Diagnostic<'x>) -> ErrorGuaranteed {366        self.cx.emit_err(diag)367    }368369    /// Emit a lint. This method is somewhat special, since lints emitted during attribute parsing370    /// must be delayed until after HIR is built. This method will take care of the details of371    /// that.372    pub(crate) fn emit_lint(373        &mut self,374        lint: &'static Lint,375        diagnostic: impl for<'x> Diagnostic<'x, ()> + DynSend + DynSync + 'static,376        span: impl Into<MultiSpan>,377    ) {378        self.emit_lint_inner(379            lint,380            EmitAttribute(Box::new(move |dcx, level, _| diagnostic.into_diag(dcx, level))),381            span,382        );383    }384385    pub(crate) fn emit_lint_with_sess<386        F: for<'a> FnOnce(DiagCtxtHandle<'a>, Level, &Session) -> Diag<'a, ()>387            + DynSend388            + DynSync389            + 'static,390    >(391        &mut self,392        lint: &'static Lint,393        callback: F,394        span: impl Into<MultiSpan>,395    ) {396        self.emit_lint_inner(lint, EmitAttribute(Box::new(callback)), span);397    }398399    fn emit_lint_inner(400        &mut self,401        lint: &'static Lint,402        kind: EmitAttribute,403        span: impl Into<MultiSpan>,404    ) {405        if !matches!(406            self.should_emit,407            ShouldEmit::ErrorsAndLints { .. } | ShouldEmit::EarlyFatal { also_emit_lints: true }408        ) {409            return;410        }411        (self.emit_lint)(LintId::of(lint), span.into(), kind);412    }413414    pub(crate) fn warn_unused_duplicate(&mut self, used_span: Span, unused_span: Span) {415        self.emit_lint(416            rustc_session::lint::builtin::UNUSED_ATTRIBUTES,417            rustc_errors::lints::UnusedDuplicate {418                this: unused_span,419                other: used_span,420                warning: false,421            },422            unused_span,423        )424    }425426    pub(crate) fn warn_unused_duplicate_future_error(427        &mut self,428        used_span: Span,429        unused_span: Span,430    ) {431        self.emit_lint(432            rustc_session::lint::builtin::UNUSED_ATTRIBUTES,433            rustc_errors::lints::UnusedDuplicate {434                this: unused_span,435                other: used_span,436                warning: true,437            },438            unused_span,439        )440    }441}442443impl<'f, 'sess: 'f> AcceptContext<'f, 'sess> {444    pub(crate) fn adcx(&mut self) -> AttributeDiagnosticContext<'_, 'f, 'sess> {445        AttributeDiagnosticContext { ctx: self, custom_suggestions: Vec::new() }446    }447448    /// Asserts that this MetaItem is a list that contains a single element. Emits an error and449    /// returns `None` if it is not the case.450    ///451    /// Some examples:452    ///453    /// - In `#[allow(warnings)]`, `warnings` is returned454    /// - In `#[cfg_attr(docsrs, doc = "foo")]`, `None` is returned, "expected a single argument455    ///   here" is emitted.456    /// - In `#[cfg()]`, `None` is returned, "expected an argument here" is emitted.457    ///458    /// The provided span is used as a fallback for diagnostic generation in case `arg` does not459    /// contain any. It should be the span of the node that contains `arg`.460    pub(crate) fn expect_single_element_list<'arg>(461        &mut self,462        arg: &'arg ArgParser,463        span: Span,464    ) -> Option<&'arg MetaItemOrLitParser> {465        let ArgParser::List(l) = arg else {466            self.adcx().expected_list(span, arg);467            return None;468        };469470        let Some(single) = l.as_single() else {471            self.adcx().expected_single_argument(l.span, l.len());472            return None;473        };474475        Some(single)476    }477478    /// Asserts that an [`ArgParser`] is a list and returns it, or emits an error and returns479    /// `None`.480    ///481    /// Some examples:482    ///483    /// - `#[allow(clippy::complexity)]`: `(clippy::complexity)` is a list484    /// - `#[rustfmt::skip::macros(target_macro_name)]`: `(target_macro_name)` is a list485    ///486    /// This is a higher-level (and harder to misuse) wrapper over [`ArgParser::as_list`] that487    /// allows using `?` when the attribute parsing function allows it. You may still want to use488    /// [`ArgParser::as_list`] for the following reasons:489    ///490    /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).491    /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error.492    pub(crate) fn expect_list<'arg>(493        &mut self,494        args: &'arg ArgParser,495        span: Span,496    ) -> Option<&'arg MetaItemListParser> {497        let list = args.as_list();498        if list.is_none() {499            self.adcx().expected_list(span, args);500        }501        list502    }503504    /// Asserts that a [`MetaItemListParser`] contains a single element and returns it, or emits an505    /// error and returns `None`.506    ///507    /// This is a higher-level (and harder to misuse) wrapper over [`MetaItemListParser::as_single`],508    /// that allows using `?` to early return. You may still want to use509    /// [`MetaItemListParser::as_single`] for the following reasons:510    ///511    /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).512    /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error.513    pub(crate) fn expect_single<'arg>(514        &mut self,515        list: &'arg MetaItemListParser,516    ) -> Option<&'arg MetaItemOrLitParser> {517        let single = list.as_single();518        if single.is_none() {519            self.adcx().expected_single_argument(list.span, list.len());520        }521        single522    }523524    /// Asserts that a node is a name-value pair.525    ///526    /// Some examples:527    ///528    /// - `#[clippy::cyclomatic_complexity = "100"]`: `clippy::cyclomatic_complexity = "100"` is a529    ///   name-value pair, where the name is a path (`clippy::cyclomatic_complexity`). You already530    ///   checked the path to get an `ArgParser`, so this method will effectively only assert that531    ///   the `= "100"` is there and returns it.532    /// - `#[doc = "hello"]`: `doc = "hello`  is also a name value pair. `= "hello"` is returned.533    /// - `#[serde(rename_all = "lowercase")]`: `rename_all = "lowercase"` is a name value pair,534    ///   where the name is an identifier (`rename_all`) and the value is a literal (`"lowercase"`).535    ///   This returns both the path and the value.536    ///537    /// `arg` must be a reference to any node that may contain a name-value pair, that is:538    ///539    /// - [`MetaItemOrLitParser`],540    /// - [`MetaItemParser`],541    /// - [`ArgParser`].542    ///543    /// `name` can be set to `Some` for a nicer error message talking about the specific name that544    /// was found lacking a value.545    ///546    /// This is a higher-level (and harder to misuse) wrapper over multiple `as_` methods in the547    /// [`parser`][crate::parser] module. You may still want to use the lower-level methods for the548    /// following reasons:549    ///550    /// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).551    /// - The attribute can be parsed in multiple ways and it does not make sense to emit an error.552    pub(crate) fn expect_name_value<'arg, Arg>(553        &mut self,554        arg: &'arg Arg,555        span: Span,556        name: Option<Symbol>,557    ) -> Option<Arg::Output<'arg>>558    where559        Arg: ExpectNameValue,560    {561        arg.expect_name_value(self, span, name)562    }563564    /// Assert that an [`ArgParser`] has no args, or emits an error and return `None`.565    pub(crate) fn expect_no_args<'arg>(&mut self, arg: &'arg ArgParser) -> Option<()> {566        if let Err(span) = arg.as_no_args() {567            self.adcx().expected_no_args(span);568            return None;569        }570571        Some(())572    }573}574575pub(crate) trait ExpectNameValue {576    type Output<'a>577    where578        Self: 'a;579580    fn expect_name_value<'a, 'f, 'sess>(581        &'a self,582        cx: &mut AcceptContext<'f, 'sess>,583        span: Span,584        name: Option<Symbol>,585    ) -> Option<Self::Output<'a>>;586}587588impl ExpectNameValue for MetaItemOrLitParser {589    type Output<'a> = (Ident, &'a NameValueParser);590591    fn expect_name_value<'a, 'f, 'sess>(592        &'a self,593        cx: &mut AcceptContext<'f, 'sess>,594        span: Span,595        name: Option<Symbol>,596    ) -> Option<Self::Output<'a>> {597        let Some(meta_item) = self.meta_item() else {598            cx.adcx().expected_name_value(self.span(), name);599            return None;600        };601602        meta_item.expect_name_value(cx, span, name)603    }604}605606impl ExpectNameValue for MetaItemParser {607    type Output<'a> = (Ident, &'a NameValueParser);608609    fn expect_name_value<'a, 'f, 'sess>(610        &'a self,611        cx: &mut AcceptContext<'f, 'sess>,612        _span: Span, // Not needed: `MetaItemOrLitParser` carry its own span.613        name: Option<Symbol>,614    ) -> Option<Self::Output<'a>> {615        let word = self.path().word();616        let arg = self.args().as_name_value();617618        if word.is_none() {619            cx.adcx().expected_identifier(self.path().span());620        }621622        if arg.is_none() {623            cx.adcx().expected_name_value(self.span(), name);624        }625626        let Some((word, arg)) = word.zip(arg) else {627            return None;628        };629630        Some((word, arg))631    }632}633634impl ExpectNameValue for ArgParser {635    type Output<'a> = &'a NameValueParser;636637    fn expect_name_value<'a, 'f, 'sess>(638        &'a self,639        cx: &mut AcceptContext<'f, 'sess>,640        span: Span,641        name: Option<Symbol>,642    ) -> Option<Self::Output<'a>> {643        let Some(nv) = self.as_name_value() else {644            cx.adcx().expected_name_value(span, name);645            return None;646        };647648        Some(nv)649    }650}651652impl<'f, 'sess> Deref for AcceptContext<'f, 'sess> {653    type Target = SharedContext<'f, 'sess>;654655    fn deref(&self) -> &Self::Target {656        &self.shared657    }658}659660impl<'f, 'sess> DerefMut for AcceptContext<'f, 'sess> {661    fn deref_mut(&mut self) -> &mut Self::Target {662        &mut self.shared663    }664}665666/// Context given to every attribute parser during finalization.667///668/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create669/// errors, for example.670pub struct SharedContext<'p, 'sess> {671    /// The parse context, gives access to the session and the672    /// diagnostics context.673    pub(crate) cx: &'p mut AttributeParser<'sess>,674    /// The span of the syntactical component this attribute was applied to675    pub(crate) target_span: Span,676    pub(crate) target: rustc_hir::Target,677678    pub(crate) emit_lint: &'p mut dyn FnMut(LintId, MultiSpan, EmitAttribute),679}680681/// Context given to every attribute parser during finalization.682///683/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create684/// errors, for example.685pub(crate) struct FinalizeContext<'p, 'sess> {686    pub(crate) shared: SharedContext<'p, 'sess>,687688    /// A list of all attribute on this syntax node.689    ///690    /// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)691    ///692    /// Usually, you should use normal attribute parsing logic instead,693    /// especially when making a *denylist* of other attributes.694    pub(crate) all_attrs: &'p [RefPathParser<'p>],695}696697impl<'p, 'sess: 'p> Deref for FinalizeContext<'p, 'sess> {698    type Target = SharedContext<'p, 'sess>;699700    fn deref(&self) -> &Self::Target {701        &self.shared702    }703}704705impl<'p, 'sess: 'p> DerefMut for FinalizeContext<'p, 'sess> {706    fn deref_mut(&mut self) -> &mut Self::Target {707        &mut self.shared708    }709}710711impl<'p, 'sess: 'p> Deref for SharedContext<'p, 'sess> {712    type Target = AttributeParser<'sess>;713714    fn deref(&self) -> &Self::Target {715        self.cx716    }717}718719impl<'p, 'sess: 'p> DerefMut for SharedContext<'p, 'sess> {720    fn deref_mut(&mut self) -> &mut Self::Target {721        self.cx722    }723}724725#[derive(PartialEq, Clone, Copy, Debug)]726pub enum OmitDoc {727    Lower,728    Skip,729}730731#[derive(Copy, Clone, Debug)]732pub enum ShouldEmit {733    /// The operations will emit errors, and lints, and errors are fatal.734    ///735    /// Only relevant when early parsing, in late parsing equivalent to `ErrorsAndLints`.736    /// Late parsing is never fatal, and instead tries to emit as many diagnostics as possible.737    EarlyFatal { also_emit_lints: bool },738    /// The operation will emit errors and lints.739    /// This is usually what you need.740    ErrorsAndLints {741        /// Whether [`ArgParser`] will attempt to recover from errors.742        ///743        /// Whether it is allowed to recover from bad input (like an invalid literal). Setting744        /// this to `Forbidden` will instead return early, and not raise errors except at the top745        /// level (in [`ArgParser::from_attr_args`]).746        recovery: Recovery,747    },748    /// The operation will *not* emit errors and lints.749    ///750    /// The parser can still call `delay_bug`, so you *must* ensure that this operation will also be751    /// called with `ShouldEmit::ErrorsAndLints`.752    Nothing,753}754755impl ShouldEmit {756    pub(crate) fn emit_err(&self, diag: Diag<'_>) -> ErrorGuaranteed {757        match self {758            ShouldEmit::EarlyFatal { .. } if diag.level() == Level::DelayedBug => diag.emit(),759            ShouldEmit::EarlyFatal { .. } => diag.upgrade_to_fatal().emit(),760            ShouldEmit::ErrorsAndLints { .. } => diag.emit(),761            ShouldEmit::Nothing => diag.delay_as_bug(),762        }763    }764}765766pub(crate) struct AttributeDiagnosticContext<'a, 'f, 'sess> {767    ctx: &'a mut AcceptContext<'f, 'sess>,768    custom_suggestions: Vec<Suggestion>,769}770771impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {772    fn emit_parse_error(773        &mut self,774        span: Span,775        reason: AttributeParseErrorReason<'_>,776    ) -> ErrorGuaranteed {777        let suggestions = if !self.custom_suggestions.is_empty() {778            AttributeParseErrorSuggestions::CreatedByParser(mem::take(&mut self.custom_suggestions))779        } else {780            AttributeParseErrorSuggestions::CreatedByTemplate(self.template_suggestions())781        };782783        self.emit_err(AttributeParseError {784            span,785            attr_span: self.attr_span,786            template: self.template.clone(),787            path: self.attr_path.clone(),788            description: self.parsed_description,789            reason,790            suggestions,791        })792    }793794    /// Adds a custom suggestion to the diagnostic. This also prevents the default (template-based)795    /// suggestion to be emitted.796    pub(crate) fn push_suggestion(&mut self, msg: String, span: Span, code: String) -> &mut Self {797        self.custom_suggestions.push(Suggestion { msg, sp: span, code });798        self799    }800801    pub(crate) fn template_suggestions(&self) -> Vec<String> {802        let style = match self.parsed_description {803            // If the outer and inner spans are equal, we are parsing an embedded attribute804            ParsedDescription::Attribute if self.attr_span == self.inner_span => {805                AttrSuggestionStyle::EmbeddedAttribute806            }807            ParsedDescription::Attribute => AttrSuggestionStyle::Attribute(self.attr_style),808            ParsedDescription::Macro => AttrSuggestionStyle::Macro,809        };810811        self.template.suggestions(style, &self.attr_path)812    }813}814815/// Helpers that can be used to generate errors during attribute parsing.816impl<'a, 'f, 'sess: 'f> AttributeDiagnosticContext<'a, 'f, 'sess> {817    pub(crate) fn expected_integer_literal_in_range(818        &mut self,819        span: Span,820        lower_bound: isize,821        upper_bound: isize,822    ) -> ErrorGuaranteed {823        self.emit_parse_error(824            span,825            AttributeParseErrorReason::ExpectedIntegerLiteralInRange { lower_bound, upper_bound },826        )827    }828829    /// The provided span is used as a fallback in case `args` does not contain any. It should be830    /// the span of the node that contains `args`.831    pub(crate) fn expected_list(&mut self, span: Span, args: &ArgParser) -> ErrorGuaranteed {832        let span = match args {833            ArgParser::NoArgs => span,834            ArgParser::List(list) => list.span,835            ArgParser::NameValue(nv) => nv.args_span(),836        };837        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedList)838    }839840    pub(crate) fn expected_list_with_num_args_or_more(841        &mut self,842        args: usize,843        span: Span,844    ) -> ErrorGuaranteed {845        self.emit_parse_error(846            span,847            AttributeParseErrorReason::ExpectedListWithNumArgsOrMore { args },848        )849    }850851    pub(crate) fn expected_list_or_no_args(&mut self, span: Span) -> ErrorGuaranteed {852        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedListOrNoArgs)853    }854855    pub(crate) fn expected_nv_or_no_args(&mut self, span: Span) -> ErrorGuaranteed {856        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValueOrNoArgs)857    }858859    pub(crate) fn expected_non_empty_string_literal(&mut self, span: Span) -> ErrorGuaranteed {860        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNonEmptyStringLiteral)861    }862863    pub(crate) fn expected_no_args(&mut self, span: Span) -> ErrorGuaranteed {864        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNoArgs)865    }866867    /// Emit an error that a `name` was expected here868    pub(crate) fn expected_identifier(&mut self, span: Span) -> ErrorGuaranteed {869        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIdentifier)870    }871872    /// Emit an error that a `name = value` pair was expected at this span. The symbol can be given for873    /// a nicer error message talking about the specific name that was found lacking a value.874    fn expected_name_value(&mut self, span: Span, name: Option<Symbol>) -> ErrorGuaranteed {875        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNameValue(name))876    }877878    /// Emit an error that a `name = value` argument is missing in a list of name-value pairs.879    pub(crate) fn missing_name_value(&mut self, span: Span, name: Symbol) -> ErrorGuaranteed {880        self.emit_parse_error(span, AttributeParseErrorReason::MissingNameValue(name))881    }882883    /// Emit an error that a `name = value` pair was found where that name was already seen.884    pub(crate) fn duplicate_key(&mut self, span: Span, key: Symbol) -> ErrorGuaranteed {885        self.emit_parse_error(span, AttributeParseErrorReason::DuplicateKey(key))886    }887888    /// An error that should be emitted when a [`MetaItemOrLitParser`]889    /// was expected *not* to be a literal, but instead a meta item.890    pub(crate) fn expected_not_literal(&mut self, span: Span) -> ErrorGuaranteed {891        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedNotLiteral)892    }893894    /// Signals that we expected exactly one argument and that we got either zero or two or more.895    /// The `provided_arguments` argument allows distinguishing between "expected an argument here"896    /// (when zero arguments are provided) and "expect a single argument here" (when two or more897    /// arguments are provided).898    pub(crate) fn expected_single_argument(899        &mut self,900        span: Span,901        provided_arguments: usize,902    ) -> ErrorGuaranteed {903        let reason = if provided_arguments == 0 {904            AttributeParseErrorReason::ExpectedArgument905        } else {906            AttributeParseErrorReason::ExpectedSingleArgument907        };908909        self.emit_parse_error(span, reason)910    }911912    pub(crate) fn expected_at_least_one_argument(&mut self, span: Span) -> ErrorGuaranteed {913        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedAtLeastOneArgument)914    }915916    /// Produces an error along the lines of `expected one of [foo, meow]`917    pub(crate) fn expected_specific_argument(918        &mut self,919        span: Span,920        possibilities: &[Symbol],921    ) -> ErrorGuaranteed {922        self.emit_parse_error(923            span,924            AttributeParseErrorReason::ExpectedSpecificArgument {925                possibilities,926                strings: false,927                list: false,928            },929        )930    }931932    /// Produces an error along the lines of `expected one of [foo, meow] as an argument`.933    /// i.e. slightly different wording to [`expected_specific_argument`](Self::expected_specific_argument).934    pub(crate) fn expected_specific_argument_and_list(935        &mut self,936        span: Span,937        possibilities: &[Symbol],938    ) -> ErrorGuaranteed {939        self.emit_parse_error(940            span,941            AttributeParseErrorReason::ExpectedSpecificArgument {942                possibilities,943                strings: false,944                list: true,945            },946        )947    }948949    /// produces an error along the lines of `expected one of ["foo", "meow"]`950    pub(crate) fn expected_specific_argument_strings(951        &mut self,952        span: Span,953        possibilities: &[Symbol],954    ) -> ErrorGuaranteed {955        self.emit_parse_error(956            span,957            AttributeParseErrorReason::ExpectedSpecificArgument {958                possibilities,959                strings: true,960                list: false,961            },962        )963    }964965    pub(crate) fn warn_empty_attribute(&mut self, span: Span) {966        let attr_path = self.attr_path.to_string();967        let valid_without_list = self.template.word;968        self.emit_lint(969            rustc_session::lint::builtin::UNUSED_ATTRIBUTES,970            crate::errors::EmptyAttributeList { attr_span: span, attr_path, valid_without_list },971            span,972        );973    }974975    pub(crate) fn warn_ill_formed_attribute_input(&mut self, lint: &'static Lint) {976        self.warn_ill_formed_attribute_input_with_help(lint, None)977    }978    pub(crate) fn warn_ill_formed_attribute_input_with_help(979        &mut self,980        lint: &'static Lint,981        help: Option<String>,982    ) {983        let suggestions = self.suggestions();984        let span = self.attr_span;985        self.emit_lint(986            lint,987            crate::errors::IllFormedAttributeInput::new(&suggestions, None, help.as_deref()),988            span,989        );990    }991992    pub(crate) fn suggestions(&self) -> Vec<String> {993        let style = match self.parsed_description {994            // If the outer and inner spans are equal, we are parsing an embedded attribute995            ParsedDescription::Attribute if self.attr_span == self.inner_span => {996                AttrSuggestionStyle::EmbeddedAttribute997            }998            ParsedDescription::Attribute => AttrSuggestionStyle::Attribute(self.attr_style),999            ParsedDescription::Macro => AttrSuggestionStyle::Macro,1000        };10011002        self.template.suggestions(style, &self.attr_path)1003    }1004    /// Error that a string literal was expected.1005    /// You can optionally give the literal you did find (which you found not to be a string literal)1006    /// which can make better errors. For example, if the literal was a byte string it will suggest1007    /// removing the `b` prefix.1008    pub(crate) fn expected_string_literal(1009        &mut self,1010        span: Span,1011        actual_literal: Option<&MetaItemLit>,1012    ) -> ErrorGuaranteed {1013        self.emit_parse_error(1014            span,1015            AttributeParseErrorReason::ExpectedStringLiteral {1016                byte_string: actual_literal.and_then(|i| {1017                    i.kind.is_bytestr().then(|| self.sess().source_map().start_point(i.span))1018                }),1019            },1020        )1021    }10221023    /// Error that a filename string literal was expected.1024    pub(crate) fn expected_filename_literal(&mut self, span: Span) {1025        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedFilenameLiteral);1026    }10271028    pub(crate) fn expected_integer_literal(&mut self, span: Span) -> ErrorGuaranteed {1029        self.emit_parse_error(span, AttributeParseErrorReason::ExpectedIntegerLiteral)1030    }1031}10321033impl<'a, 'f, 'sess: 'f> Deref for AttributeDiagnosticContext<'a, 'f, 'sess> {1034    type Target = AcceptContext<'f, 'sess>;10351036    fn deref(&self) -> &Self::Target {1037        self.ctx1038    }1039}10401041impl<'a, 'f, 'sess: 'f> DerefMut for AttributeDiagnosticContext<'a, 'f, 'sess> {1042    fn deref_mut(&mut self) -> &mut Self::Target {1043        self.ctx1044    }1045}10461047/// Represents a custom suggestion that an attribute parser can emit.1048pub(crate) struct Suggestion {1049    pub(crate) msg: String,1050    pub(crate) sp: Span,1051    pub(crate) code: String,1052}

Code quality findings 64

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
pub(super) accepters: BTreeMap<&'static [Symbol], GroupTypeInnerAccept>,
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
/// Gives [`AttributeParser`]s enough information to create errors, for example.
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
/// Asserts that an [`ArgParser`] is a list and returns it, or emits an error and returns
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
/// This is a higher-level (and harder to misuse) wrapper over [`ArgParser::as_list`] that
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
/// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).
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
/// Asserts that a [`MetaItemListParser`] contains a single element and returns it, or emits an
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
/// This is a higher-level (and harder to misuse) wrapper over [`MetaItemListParser::as_single`],
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
/// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).
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
/// [`parser`][crate::parser] module. You may still want to use the lower-level methods for the
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
/// - You want to emit your own diagnostics (for instance, with [`SharedContext::emit_err`]).
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
/// Assert that an [`ArgParser`] has no args, or emits an error and return `None`.
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
/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
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
/// Gives [`AttributeParser`](crate::attributes::AttributeParser)s enough information to create
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
/// Useful for compatibility checks with other attributes in [`finalize`](crate::attributes::AttributeParser::finalize)
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
pub(crate) all_attrs: &'p [RefPathParser<'p>],
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
/// Whether [`ArgParser`] will attempt to recover from errors.
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
/// level (in [`ArgParser::from_attr_args`]).
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
/// An error that should be emitted when a [`MetaItemOrLitParser`]
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
/// Produces an error along the lines of `expected one of [foo, meow]`
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
/// Produces an error along the lines of `expected one of [foo, meow] as an argument`.
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
/// i.e. slightly different wording to [`expected_specific_argument`](Self::expected_specific_argument).
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
/// produces an error along the lines of `expected one of ["foo", "meow"]`
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 crate::attributes::allow_unstable::*;
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 crate::attributes::autodiff::*;
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 crate::attributes::body::*;
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 crate::attributes::cfi_encoding::*;
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 crate::attributes::codegen_attrs::*;
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 crate::attributes::confusables::*;
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 crate::attributes::crate_level::*;
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 crate::attributes::debugger::*;
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 crate::attributes::deprecation::*;
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 crate::attributes::diagnostic::do_not_recommend::*;
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 crate::attributes::diagnostic::on_const::*;
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 crate::attributes::diagnostic::on_move::*;
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 crate::attributes::diagnostic::on_unimplemented::*;
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 crate::attributes::diagnostic::on_unknown::*;
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 crate::attributes::diagnostic::on_unmatch_args::*;
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 crate::attributes::doc::*;
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 crate::attributes::dummy::*;
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 crate::attributes::inline::*;
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 crate::attributes::instruction_set::*;
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 crate::attributes::link_attrs::*;
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 crate::attributes::lint_helpers::*;
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 crate::attributes::loop_match::*;
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 crate::attributes::macro_attrs::*;
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 crate::attributes::must_not_suspend::*;
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 crate::attributes::must_use::*;
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 crate::attributes::no_implicit_prelude::*;
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 crate::attributes::no_link::*;
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 crate::attributes::non_exhaustive::*;
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 crate::attributes::pin_v2::*;
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 crate::attributes::proc_macro_attrs::*;
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 crate::attributes::prototype::*;
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 crate::attributes::repr::*;
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 crate::attributes::rustc_allocator::*;
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 crate::attributes::rustc_dump::*;
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 crate::attributes::rustc_internal::*;
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 crate::attributes::semantics::*;
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 crate::attributes::stability::*;
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 crate::attributes::test_attrs::*;
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 crate::attributes::traits::*;
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 crate::attributes::transparency::*;
Info: Usage of `#[allow(...)]` suppresses compiler lints. Ensure the allowance is justified, well-scoped, and ideally temporary. Overuse can hide potential issues.
info maintainability allow-lint
/// - In `#[allow(warnings)]`, `warnings` is returned
Info: Usage of `#[allow(...)]` suppresses compiler lints. Ensure the allowance is justified, well-scoped, and ideally temporary. Overuse can hide potential issues.
info maintainability allow-lint
/// - `#[allow(clippy::complexity)]`: `(clippy::complexity)` is a list

Get this view in your editor

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