compiler/rustc_resolve/src/diagnostics/impls.rs RUST 4,263 lines View on github.com → Search inside
File is large — showing lines 1–2,000 of 4,263.
1// ignore-tidy-file-filelength2use std::mem;3use std::ops::ControlFlow;45use itertools::Itertools as _;6use rustc_ast::visit::{self, Visitor};7use rustc_ast::{8    self as ast, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, ItemKind, ModKind, NodeId, Path,9    join_path_idents,10};11use rustc_ast_pretty::pprust;12use rustc_attr_parsing::AttributeParser;13use rustc_data_structures::fx::{FxHashMap, FxHashSet};14use rustc_data_structures::unord::{UnordMap, UnordSet};15use rustc_errors::codes::*;16use rustc_errors::{17    Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle,18    pluralize, struct_span_code_err,19};20use rustc_feature::BUILTIN_ATTRIBUTES;21use rustc_hir::attrs::diagnostic::{CustomDiagnostic, Directive, FormatArgs};22use rustc_hir::attrs::{AttributeKind, CfgEntry, StrippedCfgItem};23use rustc_hir::def::Namespace::{self, *};24use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS};25use rustc_hir::def_id::{CRATE_DEF_ID, DefId};26use rustc_hir::{Attribute, PrimTy, Stability, StabilityLevel, find_attr};27use rustc_lint_defs::builtin::{28    ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES,29    AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,30};31use rustc_middle::bug;32use rustc_middle::ty::{TyCtxt, Visibility};33use rustc_session::Session;34use rustc_session::utils::was_invoked_from_cargo;35use rustc_span::def_id::ModId;36use rustc_span::edit_distance::find_best_match_for_name;37use rustc_span::edition::Edition;38use rustc_span::hygiene::MacroKind;39use rustc_span::source_map::SourceMap;40use rustc_span::{41    BytePos, Ident, RemapPathScopeComponents, Span, Spanned, Symbol, SyntaxContext, kw, sym,42};43use thin_vec::{ThinVec, thin_vec};44use tracing::{debug, instrument};4546use crate::diagnostics::{47    self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,48    ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,49    MaybeMissingMacroRulesName,50};51use crate::hygiene::Macros20NormalizedSyntaxContext;52use crate::imports::{Import, ImportKind, UnresolvedImportError, import_path_to_string};53use crate::late::{DiagMetadata, PatternSource, Rib};54use crate::{55    AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind,56    DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey,57    LateDecl, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult,58    PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,59    VisResolutionError, path_names_to_string,60};6162/// A vector of spans and replacements, a message and applicability.63pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);6465/// Potential candidate for an undeclared or out-of-scope label - contains the ident of a66/// similarly named label and whether or not it is reachable.67pub(crate) type LabelSuggestion = (Ident, bool);6869#[derive(Clone)]70pub(crate) struct StructCtor {71    pub res: Res,72    pub vis: Visibility<ModId>,73    pub field_visibilities: Vec<Visibility<ModId>>,74}7576impl StructCtor {77    pub(crate) fn has_private_fields<'ra>(&self, m: Module<'ra>, r: &Resolver<'ra, '_>) -> bool {78        self.field_visibilities.iter().any(|&vis| !r.is_accessible_from(vis, m))79    }80}8182#[derive(Debug)]83pub(crate) enum SuggestionTarget {84    /// The target has a similar name as the name used by the programmer (probably a typo)85    SimilarlyNamed,86    /// The target is the only valid item that can be used in the corresponding context87    SingleItem,88}8990#[derive(Debug)]91pub(crate) struct TypoSuggestion {92    pub candidate: Symbol,93    /// The source location where the name is defined; None if the name is not defined94    /// in source e.g. primitives95    pub span: Option<Span>,96    pub res: Res,97    pub target: SuggestionTarget,98}99100impl TypoSuggestion {101    pub(crate) fn new(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {102        Self { candidate, span: Some(span), res, target: SuggestionTarget::SimilarlyNamed }103    }104    pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {105        Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }106    }107    pub(crate) fn single_item(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {108        Self { candidate, span: Some(span), res, target: SuggestionTarget::SingleItem }109    }110}111112/// A free importable items suggested in case of resolution failure.113#[derive(Debug)]114pub(crate) struct ImportSuggestion {115    pub did: Option<DefId>,116    pub descr: &'static str,117    pub path: Path,118    pub accessible: bool,119    // false if the path traverses a foreign `#[doc(hidden)]` item.120    pub doc_visible: bool,121    pub via_import: bool,122    /// An extra note that should be issued if this item is suggested123    pub note: Option<String>,124    pub is_stable: bool,125}126127/// Adjust the impl span so that just the `impl` keyword is taken by removing128/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and129/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).130///131/// *Attention*: the method used is very fragile since it essentially duplicates the work of the132/// parser. If you need to use this function or something similar, please consider updating the133/// `source_map` functions and this function to something more robust.134fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {135    let impl_span = sm.span_until_char(impl_span, '<');136    sm.span_until_whitespace(impl_span)137}138139impl<'ra, 'tcx> Resolver<'ra, 'tcx> {140    /// Reports unresolved imports.141    ///142    /// Multiple unresolved import errors within the same use tree are combined into a single143    /// diagnostic.144    pub(crate) fn throw_unresolved_import_error(145        &mut self,146        mut errors: Vec<(Import<'_>, UnresolvedImportError)>,147        glob_error: bool,148    ) {149        errors.retain(|(_import, err)| match err.module {150            // Skip `use` errors for `use foo::Bar;` if `foo.rs` has unrecovered parse errors.151            Some(def_id) if self.mods_with_parse_errors.contains(&def_id) => false,152            // If we've encountered something like `use _;`, we've already emitted an error stating153            // that `_` is not a valid identifier, so we ignore that resolve error.154            _ => err.segment.map(|s| s.name) != Some(kw::Underscore),155        });156        if errors.is_empty() {157            self.tcx.dcx().delayed_bug("expected a parse or \"`_` can't be an identifier\" error");158            return;159        }160161        let span = MultiSpan::from_spans(errors.iter().map(|(_, err)| err.span).collect());162163        let paths = errors164            .iter()165            .map(|(import, err)| {166                let path = import_path_to_string(167                    &import.module_path.iter().map(|seg| seg.ident).collect::<Vec<_>>(),168                    &import.kind,169                    err.span,170                );171                format!("`{path}`")172            })173            .collect::<Vec<_>>();174        let default_message =175            format!("unresolved import{} {}", pluralize!(paths.len()), paths.join(", "),);176177        // Process `import` use of  the `#[diagnostic::on_unknown]` attribute.178        //179        // We don't need to check feature gates here; that happens on initialization of the180        // `on_unknown_attr` fields.181        let (mut message, label, mut notes) =182            if let Some(directive) = errors[0].1.on_unknown_attr.as_ref().map(|a| &a.directive) {183                let this = errors184                    .iter()185                    .map(|(_import, err)| {186                        // Is this unwrap_or reachable?187                        err.segment.map(|s| s.name).unwrap_or(kw::Underscore)188                    })189                    .join(", ");190191                let args = FormatArgs { unresolved: this.clone(), this, .. };192193                let CustomDiagnostic { message, label, notes, parent_label: _dead } =194                    directive.eval(None, &args);195196                (message, label, notes)197            } else {198                (None, None, Vec::new())199            };200201        // `module` use of the `#[diagnostic::on_unknown]` attribute.202        // We assume that someone who put the attribute on the import has more information than203        // the person who put it on the module, so we choose to prioritize the import attribute.204        let mut mod_diagnostics: Vec<CustomDiagnostic> = errors205            .iter()206            .map(|(import, import_error)| {207                if let Some(ModuleOrUniformRoot::Module(module_data)) = import.imported_module.get()208                    && let ModuleKind::Def(DefKind::Mod, def_id, _, name) = module_data.kind209                {210                    let Some(directive) = self.on_unknown_data(def_id) else {211                        return CustomDiagnostic::default();212                    };213214                    let this = if let Some(name) = name {215                        name.to_string()216                    } else if let Some(crate_name) = &self.tcx.sess.opts.crate_name {217                        crate_name.to_string()218                    } else {219                        "<unnamed crate>".to_string()220                    };221                    let unresolved = import_error.segment.map(|s| s.name).unwrap_or(kw::Underscore);222                    let args = FormatArgs { this, unresolved: unresolved.to_string(), .. };223224                    directive.eval(None, &args)225                } else {226                    CustomDiagnostic::default()227                }228            })229            .collect();230231        // If there is no import attribute with a message,232        // but all mod messages are the same, use that.233        let mod_message =234            mod_diagnostics.iter_mut().flat_map(|d| d.message.take()).all_equal_value();235        if message.is_none()236            && let Ok(mod_msg) = mod_message237        {238            message = Some(mod_msg);239        }240241        let mut diag = if let Some(message) = message {242            struct_span_code_err!(self.dcx(), span, E0432, "{message}").with_note(default_message)243        } else {244            struct_span_code_err!(self.dcx(), span, E0432, "{default_message}")245        };246247        for mod_diag in mod_diagnostics.iter_mut() {248            for mod_note in mod_diag.notes.drain(..) {249                if !notes.contains(&mod_note) {250                    notes.push(mod_note);251                }252            }253        }254255        if !notes.is_empty() {256            for note in notes {257                diag.note(note);258            }259        } else if let Some((_, UnresolvedImportError { note: Some(note), .. })) = errors.last() {260            diag.note(note.clone());261        }262263        /// Upper limit on the number of `span_label` messages.264        const MAX_LABEL_COUNT: usize = 10;265        let mod_labels = mod_diagnostics.into_iter().map(|cd| cd.label);266267        for ((import, err), mod_label) in errors.into_iter().zip(mod_labels).take(MAX_LABEL_COUNT) {268            let label_span = match err.segment {269                Some(segment) => segment.span,270                None => err.span,271            };272            if let Some(label) = &label {273                diag.span_label(label_span, label.clone());274            } else if let Some(label) = mod_label {275                diag.span_label(label_span, label);276            } else if let Some(label) = &err.label {277                diag.span_label(label_span, label.clone());278            }279280            if let Some((suggestions, msg, applicability)) = err.suggestion {281                if suggestions.is_empty() {282                    diag.help(msg);283                    continue;284                }285                diag.multipart_suggestion(msg, suggestions, applicability);286            }287288            if let Some(candidates) = &err.candidates {289                match &import.kind {290                    ImportKind::Single { nested: false, source, target, .. } => import_candidates(291                        self.tcx,292                        &mut diag,293                        Some(err.span),294                        candidates,295                        DiagMode::Import { append: false, unresolved_import: true },296                        (source != target)297                            .then(|| format!(" as {target}"))298                            .as_deref()299                            .unwrap_or(""),300                    ),301                    ImportKind::Single { nested: true, source, target, .. } => {302                        import_candidates(303                            self.tcx,304                            &mut diag,305                            None,306                            candidates,307                            DiagMode::Normal,308                            (source != target)309                                .then(|| format!(" as {target}"))310                                .as_deref()311                                .unwrap_or(""),312                        );313                    }314                    _ => {}315                }316            }317318            if matches!(import.kind, ImportKind::Single { .. })319                && let Some(segment) = err.segment320                && let Some(module) = err.module321            {322                self.find_cfg_stripped(&mut diag, &segment.name, module)323            }324        }325326        let guar = diag.emit();327        if glob_error {328            self.glob_error = Some(guar);329        }330    }331332    pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {333        self.tcx.dcx()334    }335336    pub(crate) fn report_errors(&mut self, krate: &Crate, use_injections: Vec<UseError<'tcx>>) {337        self.report_delayed_vis_resolution_errors();338        self.report_with_use_injections(krate, use_injections);339340        for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {341            self.lint_buffer.buffer_lint(342                MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,343                CRATE_NODE_ID,344                span_use,345                diagnostics::MacroExpandedMacroExportsAccessedByAbsolutePaths {346                    definition: span_def,347                },348            );349        }350351        for ambiguity_error in &self.ambiguity_errors {352            let mut diag = self.ambiguity_diagnostic(ambiguity_error);353354            if let Some(ambiguity_warning) = ambiguity_error.warning {355                let node_id = match ambiguity_error.b1.0.kind {356                    DeclKind::Import { import, .. } => import.root_id,357                    DeclKind::Def(_) => CRATE_NODE_ID,358                };359360                let lint = match ambiguity_warning {361                    _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES,362                    AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,363                    AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,364                };365366                self.lint_buffer.buffer_lint(lint, node_id, diag.ident.span, diag);367            } else {368                diag.is_error = true;369                self.dcx().emit_err(diag);370            }371        }372373        let mut reported_spans = FxHashSet::default();374        for error in mem::take(&mut self.privacy_errors) {375            if reported_spans.insert(error.dedup_span) {376                self.report_privacy_error(&error);377            }378        }379    }380381    fn report_delayed_vis_resolution_errors(&mut self) {382        for DelayedVisResolutionError { vis, parent_scope, error } in383            mem::take(&mut self.delayed_vis_resolution_errors)384        {385            match self.try_resolve_visibility(&parent_scope, &vis, true) {386                Ok(_) => self.report_vis_error(error),387                Err(error) => self.report_vis_error(error),388            };389        }390    }391392    fn report_with_use_injections(&mut self, krate: &Crate, use_injections: Vec<UseError<'tcx>>) {393        for UseError { mut err, candidates, node_id, instead, suggestion, path, is_call } in394            use_injections395        {396            let (span, found_use) = if node_id != DUMMY_NODE_ID {397                UsePlacementFinder::check(krate, node_id)398            } else {399                (None, FoundUse::No)400            };401402            if !candidates.is_empty() {403                show_candidates(404                    self.tcx,405                    &mut err,406                    span,407                    &candidates,408                    if instead { Instead::Yes } else { Instead::No },409                    found_use,410                    DiagMode::Normal,411                    path,412                    "",413                );414                err.emit();415            } else if let Some((span, msg, sugg, appl)) = suggestion {416                err.span_suggestion_verbose(span, msg, sugg, appl);417                err.emit();418            } else if let [segment] = path.as_slice()419                && is_call420            {421                err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);422            } else {423                err.emit();424            }425        }426    }427428    pub(crate) fn report_conflict(429        &mut self,430        ident: IdentKey,431        ns: Namespace,432        old_binding: Decl<'ra>,433        new_binding: Decl<'ra>,434    ) {435        // Error on the second of two conflicting names436        if old_binding.span.lo() > new_binding.span.lo() {437            return self.report_conflict(ident, ns, new_binding, old_binding);438        }439440        let container = match old_binding.parent_module.unwrap().expect_local().kind {441            // Avoid using TyCtxt::def_kind_descr in the resolver, because it442            // indirectly *calls* the resolver, and would cause a query cycle.443            ModuleKind::Def(kind, def_id, _, _) => kind.descr(def_id),444            ModuleKind::Block => "block",445        };446447        let (name, span) =448            (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));449450        if self.name_already_seen.get(&name) == Some(&span) {451            return;452        }453454        let old_kind = match (ns, old_binding.res()) {455            (ValueNS, _) => "value",456            (MacroNS, _) => "macro",457            (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",458            (TypeNS, Res::Def(DefKind::Mod, _)) => "module",459            (TypeNS, Res::Def(DefKind::Trait, _)) => "trait",460            (TypeNS, _) => "type",461        };462463        let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {464            (true, true) => E0259,465            (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {466                true => E0254,467                false => E0260,468            },469            _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {470                (false, false) => E0428,471                (true, true) => E0252,472                _ => E0255,473            },474        };475476        let label = match new_binding.is_import_user_facing() {477            true => diagnostics::NameDefinedMultipleTimeLabel::Reimported { span, name },478            false => diagnostics::NameDefinedMultipleTimeLabel::Redefined { span, name },479        };480481        let old_binding_label =482            (!old_binding.span.is_dummy() && old_binding.span != span).then(|| {483                let span = self.tcx.sess.source_map().guess_head_span(old_binding.span);484                match old_binding.is_import_user_facing() {485                    true => diagnostics::NameDefinedMultipleTimeOldBindingLabel::Import {486                        span,487                        old_kind,488                        name,489                    },490                    false => diagnostics::NameDefinedMultipleTimeOldBindingLabel::Definition {491                        span,492                        old_kind,493                        name,494                    },495                }496            });497498        let mut err = self499            .dcx()500            .create_err(diagnostics::NameDefinedMultipleTime {501                span,502                name,503                descr: ns.descr(),504                container,505                label,506                old_binding_label,507            })508            .with_code(code);509510        // See https://github.com/rust-lang/rust/issues/32354511        use DeclKind::Import;512        let can_suggest = |binding: Decl<'_>, import: self::Import<'_>| {513            !binding.span.is_dummy()514                && !matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)515        };516        let import = match (&new_binding.kind, &old_binding.kind) {517            // If there are two imports where one or both have attributes then prefer removing the518            // import without attributes.519            (Import { import: new, .. }, Import { import: old, .. })520                if {521                    (new.has_attributes || old.has_attributes)522                        && can_suggest(old_binding, *old)523                        && can_suggest(new_binding, *new)524                } =>525            {526                if old.has_attributes {527                    Some((*new, new_binding.span, true))528                } else {529                    Some((*old, old_binding.span, true))530                }531            }532            // Otherwise prioritize the new binding.533            (Import { import, .. }, other) if can_suggest(new_binding, *import) => {534                Some((*import, new_binding.span, other.is_import()))535            }536            (other, Import { import, .. }) if can_suggest(old_binding, *import) => {537                Some((*import, old_binding.span, other.is_import()))538            }539            _ => None,540        };541542        // Check if the target of the use for both bindings is the same.543        let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();544        let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();545        let from_item =546            self.extern_prelude.get(&ident).is_none_or(|entry| entry.introduced_by_item());547        // Only suggest removing an import if both bindings are to the same def, if both spans548        // aren't dummy spans. Further, if both bindings are imports, then the ident must have549        // been introduced by an item.550        let should_remove_import = duplicate551            && !has_dummy_span552            && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);553554        match import {555            Some((import, span, true)) if should_remove_import && import.is_nested() => {556                self.add_suggestion_for_duplicate_nested_use(&mut err, import, span);557            }558            Some((import, _, true)) if should_remove_import && !import.is_glob() => {559                // Simple case - remove the entire import. Due to the above match arm, this can560                // only be a single use so just remove it entirely.561                err.subdiagnostic(diagnostics::ToolOnlyRemoveUnnecessaryImport {562                    span: import.use_span_with_attributes,563                });564            }565            Some((import, span, _)) => {566                self.add_suggestion_for_rename_of_use(&mut err, name, import, span);567            }568            _ => {}569        }570571        err.emit();572        self.name_already_seen.insert(name, span);573    }574575    /// This function adds a suggestion to change the binding name of a new import that conflicts576    /// with an existing import.577    ///578    /// ```text,ignore (diagnostic)579    /// help: you can use `as` to change the binding name of the import580    ///    |581    /// LL | use foo::bar as other_bar;582    ///    |     ^^^^^^^^^^^^^^^^^^^^^583    /// ```584    fn add_suggestion_for_rename_of_use(585        &self,586        err: &mut Diag<'_>,587        name: Symbol,588        import: Import<'_>,589        binding_span: Span,590    ) {591        let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {592            format!("Other{name}")593        } else {594            format!("other_{name}")595        };596597        let mut suggestion = None;598        let mut span = binding_span;599        match import.kind {600            ImportKind::Single { source, .. } => {601                if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)602                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)603                    && pos as usize <= snippet.len()604                {605                    span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi(606                        binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),607                    );608                    suggestion = Some(format!(" as {suggested_name}"));609                }610            }611            ImportKind::ExternCrate { source, target, .. } => {612                suggestion = Some(format!(613                    "extern crate {} as {};",614                    source.unwrap_or(target.name),615                    suggested_name,616                ))617            }618            _ => unreachable!(),619        }620621        if let Some(suggestion) = suggestion {622            err.subdiagnostic(ChangeImportBindingSuggestion { span, suggestion });623        } else {624            err.subdiagnostic(ChangeImportBinding { span });625        }626    }627628    /// This function adds a suggestion to remove an unnecessary binding from an import that is629    /// nested. In the following example, this function will be invoked to remove the `a` binding630    /// in the second use statement:631    ///632    /// ```ignore (diagnostic)633    /// use issue_52891::a;634    /// use issue_52891::{d, a, e};635    /// ```636    ///637    /// The following suggestion will be added:638    ///639    /// ```ignore (diagnostic)640    /// use issue_52891::{d, a, e};641    ///                      ^-- help: remove unnecessary import642    /// ```643    ///644    /// If the nested use contains only one import then the suggestion will remove the entire645    /// line.646    ///647    /// It is expected that the provided import is nested - this isn't checked by the648    /// function. If this invariant is not upheld, this function's behaviour will be unexpected649    /// as characters expected by span manipulations won't be present.650    fn add_suggestion_for_duplicate_nested_use(651        &self,652        err: &mut Diag<'_>,653        import: Import<'_>,654        binding_span: Span,655    ) {656        assert!(import.is_nested());657658        // Two examples will be used to illustrate the span manipulations we're doing:659        //660        // - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is661        //   `a` and `import.use_span` is `issue_52891::{d, a, e};`.662        // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is663        //   `a` and `import.use_span` is `issue_52891::{d, e, a};`.664665        let (found_closing_brace, span) =666            find_span_of_binding_until_next_binding(self.tcx.sess, binding_span, import.use_span);667668        // If there was a closing brace then identify the span to remove any trailing commas from669        // previous imports.670        if found_closing_brace {671            if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {672                err.subdiagnostic(diagnostics::ToolOnlyRemoveUnnecessaryImport { span });673            } else {674                // Remove the entire line if we cannot extend the span back, this indicates an675                // `issue_52891::{self}` case.676                err.subdiagnostic(diagnostics::RemoveUnnecessaryImport {677                    span: import.use_span_with_attributes,678                });679            }680681            return;682        }683684        err.subdiagnostic(diagnostics::RemoveUnnecessaryImport { span });685    }686687    pub(crate) fn lint_if_path_starts_with_module(688        &mut self,689        finalize: Finalize,690        path: &[Segment],691        second_binding: Option<Decl<'_>>,692    ) {693        let Finalize { node_id, root_span, .. } = finalize;694695        let first_name = match path.get(0) {696            // In the 2018 edition this lint is a hard error, so nothing to do697            Some(seg) if seg.ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015() => {698                seg.ident.name699            }700            _ => return,701        };702703        // We're only interested in `use` paths which should start with704        // `{{root}}` currently.705        if first_name != kw::PathRoot {706            return;707        }708709        match path.get(1) {710            // If this import looks like `crate::...` it's already good711            Some(Segment { ident, .. }) if ident.name == kw::Crate => return,712            // Otherwise go below to see if it's an extern crate713            Some(_) => {}714            // If the path has length one (and it's `PathRoot` most likely)715            // then we don't know whether we're gonna be importing a crate or an716            // item in our crate. Defer this lint to elsewhere717            None => return,718        }719720        // If the first element of our path was actually resolved to an721        // `ExternCrate` (also used for `crate::...`) then no need to issue a722        // warning, this looks all good!723        if let Some(binding) = second_binding724            && let DeclKind::Import { import, .. } = binding.kind725            // Careful: we still want to rewrite paths from renamed extern crates.726            && let ImportKind::ExternCrate { source: None, .. } = import.kind727        {728            return;729        }730731        self.lint_buffer.dyn_buffer_lint_any(732            ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,733            node_id,734            root_span,735            move |dcx, level, sess| {736                let (replacement, applicability) = match sess737                    .downcast_ref::<Session>()738                    .expect("expected a `Session`")739                    .source_map()740                    .span_to_snippet(root_span)741                {742                    Ok(ref s) => {743                        // FIXME(Manishearth) ideally the emitting code744                        // can tell us whether or not this is global745                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };746747                        (format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)748                    }749                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),750                };751                diagnostics::AbsPathWithModule {752                    sugg: diagnostics::AbsPathWithModuleSugg {753                        span: root_span,754                        applicability,755                        replacement,756                    },757                }758                .into_diag(dcx, level)759            },760        );761    }762763    pub(crate) fn add_module_candidates(764        &self,765        module: Module<'ra>,766        names: &mut Vec<TypoSuggestion>,767        filter_fn: &impl Fn(Res) -> bool,768        ctxt: Option<SyntaxContext>,769    ) {770        module.for_each_child(self, |_this, ident, orig_ident_span, _ns, binding| {771            let res = binding.res();772            if filter_fn(res) && ctxt.is_none_or(|ctxt| ctxt == *ident.ctxt) {773                names.push(TypoSuggestion::new(ident.name, orig_ident_span, res));774            }775        });776    }777778    /// Combines an error with provided span and emits it.779    ///780    /// This takes the error provided, combines it with the span and any additional spans inside the781    /// error and emits it.782    pub(crate) fn report_error(783        &self,784        span: Span,785        resolution_error: ResolutionError<'ra>,786    ) -> ErrorGuaranteed {787        self.into_struct_error(span, resolution_error).emit()788    }789790    pub(crate) fn into_struct_error(791        &self,792        span: Span,793        resolution_error: ResolutionError<'ra>,794    ) -> Diag<'_> {795        match resolution_error {796            ResolutionError::GenericParamsFromOuterItem {797                outer_res,798                has_generic_params,799                def_kind,800                inner_item,801                current_self_ty,802            } => {803                use diagnostics::GenericParamsFromOuterItemLabel as Label;804                let static_or_const = match def_kind {805                    DefKind::Static { .. } => {806                        Some(diagnostics::GenericParamsFromOuterItemStaticOrConst::Static)807                    }808                    DefKind::Const { .. } => {809                        Some(diagnostics::GenericParamsFromOuterItemStaticOrConst::Const)810                    }811                    _ => None,812                };813                let is_self =814                    matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });815                let mut err = diagnostics::GenericParamsFromOuterItem {816                    span,817                    label: None,818                    refer_to_type_directly: None,819                    use_let: None,820                    sugg: None,821                    static_or_const,822                    is_self,823                    item: inner_item.as_ref().map(|(label_span, _, kind)| {824                        diagnostics::GenericParamsFromOuterItemInnerItem {825                            span: *label_span,826                            descr: kind.descr().to_string(),827                            is_self,828                        }829                    }),830                };831832                let sm = self.tcx.sess.source_map();833                // Note: do not early return for missing def_id here,834                // we still want to provide suggestions for `Res::SelfTyParam` and `Res::SelfTyAlias`.835                let def_id = match outer_res {836                    Res::SelfTyParam { .. } => {837                        err.label = Some(Label::SelfTyParam(span));838                        None839                    }840                    Res::SelfTyAlias { alias_to: def_id, .. } => {841                        err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(842                            sm,843                            self.def_span(def_id),844                        )));845                        err.refer_to_type_directly = current_self_ty846                            .map(|snippet| diagnostics::UseTypeDirectly { span, snippet });847                        None848                    }849                    Res::Def(DefKind::TyParam, def_id) => {850                        err.label = Some(Label::TyParam(self.def_span(def_id)));851                        Some(def_id)852                    }853                    Res::Def(DefKind::ConstParam, def_id) => {854                        err.label = Some(Label::ConstParam(self.def_span(def_id)));855                        Some(def_id)856                    }857                    _ => {858                        bug!(859                            "GenericParamsFromOuterItem should only be used with \860                            Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \861                            DefKind::ConstParam"862                        );863                    }864                };865866                if let Some((_, item_span, ItemKind::Const(_))) = inner_item.as_ref() {867                    err.use_let = Some(diagnostics::GenericParamsFromOuterItemUseLet {868                        span: sm.span_until_whitespace(*item_span),869                    });870                }871872                if let Some(def_id) = def_id873                    && let HasGenericParams::Yes(span) = has_generic_params874                    && !matches!(inner_item, Some((_, _, ItemKind::Delegation(..))))875                {876                    let name = self.tcx.item_name(def_id);877                    let (span, snippet) = if span.is_empty() {878                        let snippet = format!("<{name}>");879                        (span, snippet)880                    } else {881                        let span = sm.span_through_char(span, '<').shrink_to_hi();882                        let snippet = format!("{name}, ");883                        (span, snippet)884                    };885                    err.sugg = Some(diagnostics::GenericParamsFromOuterItemSugg { span, snippet });886                }887888                self.dcx().create_err(err)889            }890            ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => {891                self.dcx().create_err(diagnostics::NameAlreadyUsedInParameterList {892                    span,893                    first_use_span,894                    name,895                })896            }897            ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {898                self.dcx().create_err(diagnostics::MethodNotMemberOfTrait {899                    span,900                    method,901                    trait_,902                    sub: candidate.map(|c| diagnostics::AssociatedFnWithSimilarNameExists {903                        span: method.span,904                        candidate: c,905                    }),906                })907            }908            ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {909                self.dcx().create_err(diagnostics::TypeNotMemberOfTrait {910                    span,911                    type_,912                    trait_,913                    sub: candidate.map(|c| diagnostics::AssociatedTypeWithSimilarNameExists {914                        span: type_.span,915                        candidate: c,916                    }),917                })918            }919            ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {920                self.dcx().create_err(diagnostics::ConstNotMemberOfTrait {921                    span,922                    const_,923                    trait_,924                    sub: candidate.map(|c| diagnostics::AssociatedConstWithSimilarNameExists {925                        span: const_.span,926                        candidate: c,927                    }),928                })929            }930            ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {931                let BindingError { name, target, origin, could_be_path } = binding_error;932933                let mut target_sp = target.iter().map(|pat| pat.span).collect::<Vec<_>>();934                target_sp.sort();935                target_sp.dedup();936                let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::<Vec<_>>();937                origin_sp.sort();938                origin_sp.dedup();939940                let msp = MultiSpan::from_spans(target_sp.clone());941                let mut err = self.dcx().create_err(diagnostics::VariableIsNotBoundInAllPatterns {942                    multispan: msp,943                    name,944                });945                for sp in target_sp {946                    err.subdiagnostic(diagnostics::PatternDoesntBindName { span: sp, name });947                }948                for sp in &origin_sp {949                    err.subdiagnostic(diagnostics::VariableNotInAllPatterns { span: *sp });950                }951                let mut suggested_typo = false;952                if !target.iter().all(|pat| matches!(pat.kind, ast::PatKind::Ident(..)))953                    && !origin.iter().all(|(_, pat)| matches!(pat.kind, ast::PatKind::Ident(..)))954                {955                    // The check above is so that when we encounter `match foo { (a | b) => {} }`,956                    // we don't suggest `(a | a) => {}`, which would never be what the user wants.957                    let mut target_visitor = BindingVisitor::default();958                    for pat in &target {959                        target_visitor.visit_pat(pat);960                    }961                    target_visitor.identifiers.sort();962                    target_visitor.identifiers.dedup();963                    let mut origin_visitor = BindingVisitor::default();964                    for (_, pat) in &origin {965                        origin_visitor.visit_pat(pat);966                    }967                    origin_visitor.identifiers.sort();968                    origin_visitor.identifiers.dedup();969                    // Find if the binding could have been a typo970                    if let Some(typo) =971                        find_best_match_for_name(&target_visitor.identifiers, name.name, None)972                        && !origin_visitor.identifiers.contains(&typo)973                    {974                        err.subdiagnostic(diagnostics::PatternBindingTypo {975                            spans: origin_sp,976                            typo,977                        });978                        suggested_typo = true;979                    }980                }981                if could_be_path {982                    let import_suggestions = self.lookup_import_candidates(983                        name,984                        Namespace::ValueNS,985                        &parent_scope,986                        &|res: Res| {987                            matches!(988                                res,989                                Res::Def(990                                    DefKind::Ctor(CtorOf::Variant, CtorKind::Const)991                                        | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)992                                        | DefKind::Const { .. }993                                        | DefKind::AssocConst { .. },994                                    _,995                                )996                            )997                        },998                    );9991000                    if import_suggestions.is_empty() && !suggested_typo {1001                        let kind_matches: [fn(DefKind) -> bool; 4] = [1002                            |kind| matches!(kind, DefKind::Ctor(CtorOf::Variant, CtorKind::Const)),1003                            |kind| matches!(kind, DefKind::Ctor(CtorOf::Struct, CtorKind::Const)),1004                            |kind| matches!(kind, DefKind::Const { .. }),1005                            |kind| matches!(kind, DefKind::AssocConst { .. }),1006                        ];1007                        let mut local_names = vec![];1008                        self.add_module_candidates(1009                            parent_scope.module,1010                            &mut local_names,1011                            &|res| matches!(res, Res::Def(_, _)),1012                            None,1013                        );1014                        let local_names: FxHashSet<_> = local_names1015                            .into_iter()1016                            .filter_map(|s| match s.res {1017                                Res::Def(_, def_id) => Some(def_id),1018                                _ => None,1019                            })1020                            .collect();10211022                        let mut local_suggestions = vec![];1023                        let mut suggestions = vec![];1024                        for matches_kind in kind_matches {1025                            if let Some(suggestion) = self.early_lookup_typo_candidate(1026                                ScopeSet::All(Namespace::ValueNS),1027                                &parent_scope,1028                                name,1029                                &|res: Res| match res {1030                                    Res::Def(k, _) => matches_kind(k),1031                                    _ => false,1032                                },1033                            ) && let Res::Def(kind, mut def_id) = suggestion.res1034                            {1035                                if let DefKind::Ctor(_, _) = kind {1036                                    def_id = self.tcx.parent(def_id);1037                                }1038                                let kind = kind.descr(def_id);1039                                if local_names.contains(&def_id) {1040                                    // The item is available in the current scope. Very likely to1041                                    // be a typo. Don't use the full path.1042                                    local_suggestions.push((1043                                        suggestion.candidate,1044                                        suggestion.candidate.to_string(),1045                                        kind,1046                                    ));1047                                } else {1048                                    suggestions.push((1049                                        suggestion.candidate,1050                                        self.def_path_str(def_id),1051                                        kind,1052                                    ));1053                                }1054                            }1055                        }1056                        let suggestions = if !local_suggestions.is_empty() {1057                            // There is at least one item available in the current scope that is a1058                            // likely typo. We only show those.1059                            local_suggestions1060                        } else {1061                            suggestions1062                        };1063                        for (name, sugg, kind) in suggestions {1064                            err.span_suggestion_verbose(1065                                span,1066                                format!(1067                                    "you might have meant to use the similarly named {kind} `{name}`",1068                                ),1069                                sugg,1070                                Applicability::MaybeIncorrect,1071                            );1072                            suggested_typo = true;1073                        }1074                    }1075                    if import_suggestions.is_empty() && !suggested_typo {1076                        let help_msg = format!(1077                            "if you meant to match on a unit struct, unit variant or a `const` \1078                             item, consider making the path in the pattern qualified: \1079                             `path::to::ModOrType::{name}`",1080                        );1081                        err.span_help(span, help_msg);1082                    }1083                    show_candidates(1084                        self.tcx,1085                        &mut err,1086                        Some(span),1087                        &import_suggestions,1088                        Instead::No,1089                        FoundUse::Yes,1090                        DiagMode::Pattern,1091                        vec![],1092                        "",1093                    );1094                }1095                err1096            }1097            ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {1098                self.dcx().create_err(diagnostics::VariableBoundWithDifferentMode {1099                    span,1100                    first_binding_span,1101                    variable_name,1102                })1103            }1104            ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => {1105                self.dcx().create_err(diagnostics::IdentifierBoundMoreThanOnceInParameterList {1106                    span,1107                    identifier,1108                })1109            }1110            ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => {1111                self.dcx().create_err(diagnostics::IdentifierBoundMoreThanOnceInSamePattern {1112                    span,1113                    identifier,1114                })1115            }1116            ResolutionError::UndeclaredLabel { name, suggestion } => {1117                let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion1118                {1119                    // A reachable label with a similar name exists.1120                    Some((ident, true)) => (1121                        (1122                            Some(diagnostics::LabelWithSimilarNameReachable(ident.span)),1123                            Some(diagnostics::TryUsingSimilarlyNamedLabel {1124                                span,1125                                ident_name: ident.name,1126                            }),1127                        ),1128                        None,1129                    ),1130                    // An unreachable label with a similar name exists.1131                    Some((ident, false)) => (1132                        (None, None),1133                        Some(diagnostics::UnreachableLabelWithSimilarNameExists {1134                            ident_span: ident.span,1135                        }),1136                    ),1137                    // No similarly-named labels exist.1138                    None => ((None, None), None),1139                };1140                self.dcx().create_err(diagnostics::UndeclaredLabel {1141                    span,1142                    name,1143                    sub_reachable,1144                    sub_reachable_suggestion,1145                    sub_unreachable,1146                })1147            }1148            ResolutionError::FailedToResolve { segment, label, suggestion, module, message } => {1149                let mut err = struct_span_code_err!(self.dcx(), span, E0433, "{message}");1150                err.span_label(span, label);11511152                if let Some((suggestions, msg, applicability)) = suggestion {1153                    if suggestions.is_empty() {1154                        err.help(msg);1155                        return err;1156                    }1157                    err.multipart_suggestion(msg, suggestions, applicability);1158                }11591160                let module = match module {1161                    Some(ModuleOrUniformRoot::Module(m)) if let Some(id) = m.opt_def_id() => id,1162                    _ => CRATE_DEF_ID.to_def_id(),1163                };1164                self.find_cfg_stripped(&mut err, &segment, module);11651166                err1167            }1168            ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {1169                self.dcx().create_err(diagnostics::CannotCaptureDynamicEnvironmentInFnItem { span })1170            }1171            ResolutionError::AttemptToUseNonConstantValueInConstant {1172                ident,1173                suggestion,1174                current,1175                type_span,1176            } => {1177                // let foo =...1178                //     ^^^ given this Span1179                // ------- get this Span to have an applicable suggestion11801181                // edit:1182                // only do this if the const and usage of the non-constant value are on the same line1183                // the further the two are apart, the higher the chance of the suggestion being wrong11841185                let sp = self1186                    .tcx1187                    .sess1188                    .source_map()1189                    .span_extend_to_prev_str(ident.span, current, true, false);11901191                let (with, with_label, without) = match sp {1192                    Some(sp) if !self.tcx.sess.source_map().is_multiline(sp) => {1193                        let sp = sp1194                            .with_lo(BytePos(sp.lo().0 - (current.len() as u32)))1195                            .until(ident.span);11961197                        // Only suggest replacing the binding keyword if this is a simple1198                        // binding.1199                        //1200                        // Note: this approach still incorrectly suggests for irrefutable1201                        // patterns like `if let x = 1 { const { x } }`, since the text1202                        // between `let` and the identifier is just whitespace.1203                        // See tests/ui/consts/non-const-value-in-const-irrefutable-pat-binding.rs1204                        let is_simple_binding =1205                            self.tcx.sess.source_map().span_to_snippet(sp).is_ok_and(|snippet| {1206                                let after_keyword = snippet[current.len()..].trim();1207                                after_keyword.is_empty() || after_keyword == "mut"1208                            });12091210                        if is_simple_binding {1211                            (1212                                Some(diagnostics::AttemptToUseNonConstantValueInConstantWithSuggestion {1213                                    span: sp,1214                                    suggestion,1215                                    current,1216                                    type_span,1217                                }),1218                                Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),1219                                None,1220                            )1221                        } else {1222                            (1223                                None,1224                                Some(diagnostics::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),1225                                None,1226                            )1227                        }1228                    }1229                    _ => (1230                        None,1231                        None,1232                        Some(1233                            diagnostics::AttemptToUseNonConstantValueInConstantWithoutSuggestion {1234                                ident_span: ident.span,1235                                suggestion,1236                            },1237                        ),1238                    ),1239                };12401241                self.dcx().create_err(diagnostics::AttemptToUseNonConstantValueInConstant {1242                    span,1243                    with,1244                    with_label,1245                    without,1246                })1247            }1248            ResolutionError::BindingShadowsSomethingUnacceptable {1249                shadowing_binding,1250                name,1251                participle,1252                article,1253                shadowed_binding,1254                shadowed_binding_span,1255            } => self.dcx().create_err(diagnostics::BindingShadowsSomethingUnacceptable {1256                span,1257                shadowing_binding,1258                shadowed_binding,1259                article,1260                sub_suggestion: match (shadowing_binding, shadowed_binding) {1261                    (1262                        PatternSource::Match,1263                        Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),1264                    ) => Some(diagnostics::BindingShadowsSomethingUnacceptableSuggestion {1265                        span,1266                        name,1267                    }),1268                    _ => None,1269                },1270                shadowed_binding_span,1271                participle,1272                name,1273            }),1274            ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {1275                ForwardGenericParamBanReason::Default => {1276                    self.dcx().create_err(diagnostics::ForwardDeclaredGenericParam { param, span })1277                }1278                ForwardGenericParamBanReason::ConstParamTy => self1279                    .dcx()1280                    .create_err(diagnostics::ForwardDeclaredGenericInConstParamTy { param, span }),1281            },1282            ResolutionError::ParamInTyOfConstParam { name } => {1283                self.dcx().create_err(diagnostics::ParamInTyOfConstParam { span, name })1284            }1285            ResolutionError::SelfInConstParam => {1286                self.dcx().create_err(diagnostics::SelfInConstGenericTy {1287                    span,1288                    enable_feature: self.tcx().sess.is_nightly_build(),1289                })1290            }1291            ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => {1292                self.dcx().create_err(diagnostics::ParamInNonTrivialAnonConst {1293                    span,1294                    name,1295                    param_kind: is_type,1296                    help: self.tcx.sess.is_nightly_build()1297                        && !self.tcx.features().min_generic_const_args(),1298                    is_gca,1299                    help_gca: is_gca,1300                    help_suggest_gca: self.tcx.sess.is_nightly_build() && !is_gca,1301                })1302            }1303            ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => {1304                self.dcx().create_err(diagnostics::ParamInEnumDiscriminant {1305                    span,1306                    name,1307                    param_kind: is_type,1308                })1309            }1310            ResolutionError::ForwardDeclaredSelf(reason) => match reason {1311                ForwardGenericParamBanReason::Default => {1312                    self.dcx().create_err(diagnostics::SelfInGenericParamDefault { span })1313                }1314                ForwardGenericParamBanReason::ConstParamTy => self1315                    .dcx()1316                    .create_err(diagnostics::SelfInConstGenericTy { span, enable_feature: false }),1317            },1318            ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {1319                let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =1320                    match suggestion {1321                        // A reachable label with a similar name exists.1322                        Some((ident, true)) => (1323                            (1324                                Some(diagnostics::UnreachableLabelSubLabel {1325                                    ident_span: ident.span,1326                                }),1327                                Some(diagnostics::UnreachableLabelSubSuggestion {1328                                    span,1329                                    // intentionally taking 'ident.name' instead of 'ident' itself, as this1330                                    // could be used in suggestion context1331                                    ident_name: ident.name,1332                                }),1333                            ),1334                            None,1335                        ),1336                        // An unreachable label with a similar name exists.1337                        Some((ident, false)) => (1338                            (None, None),1339                            Some(diagnostics::UnreachableLabelSubLabelUnreachable {1340                                ident_span: ident.span,1341                            }),1342                        ),1343                        // No similarly-named labels exist.1344                        None => ((None, None), None),1345                    };1346                self.dcx().create_err(diagnostics::UnreachableLabel {1347                    span,1348                    name,1349                    definition_span,1350                    sub_suggestion,1351                    sub_suggestion_label,1352                    sub_unreachable_label,1353                })1354            }1355            ResolutionError::TraitImplMismatch {1356                name,1357                kind,1358                code,1359                trait_item_span,1360                trait_path,1361            } => self1362                .dcx()1363                .create_err(diagnostics::TraitImplMismatch {1364                    span,1365                    name,1366                    kind,1367                    trait_path,1368                    trait_item_span,1369                })1370                .with_code(code),1371            ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => {1372                self.dcx().create_err(diagnostics::TraitImplDuplicate {1373                    span,1374                    name,1375                    trait_item_span,1376                    old_span,1377                })1378            }1379            ResolutionError::InvalidAsmSym => {1380                self.dcx().create_err(diagnostics::InvalidAsmSym { span })1381            }1382            ResolutionError::LowercaseSelf => {1383                self.dcx().create_err(diagnostics::LowercaseSelf { span })1384            }1385            ResolutionError::BindingInNeverPattern => {1386                self.dcx().create_err(diagnostics::BindingInNeverPattern { span })1387            }1388        }1389    }13901391    pub(crate) fn report_vis_error(1392        &mut self,1393        vis_resolution_error: VisResolutionError,1394    ) -> ErrorGuaranteed {1395        match vis_resolution_error {1396            VisResolutionError::Relative2018(span, path) => {1397                self.dcx().create_err(diagnostics::Relative2018 {1398                    span,1399                    path_span: path.span,1400                    // intentionally converting to String, as the text would also be used as1401                    // in suggestion context1402                    path_str: pprust::path_to_string(&path),1403                })1404            }1405            VisResolutionError::AncestorOnly(span) => {1406                self.dcx().create_err(diagnostics::AncestorOnly(span))1407            }1408            VisResolutionError::FailedToResolve(span, segment, label, suggestion, message) => self1409                .into_struct_error(1410                    span,1411                    ResolutionError::FailedToResolve {1412                        segment,1413                        label,1414                        suggestion,1415                        module: None,1416                        message,1417                    },1418                ),1419            VisResolutionError::ExpectedFound(span, path_str, res) => {1420                self.dcx().create_err(diagnostics::ExpectedModuleFound { span, res, path_str })1421            }1422            VisResolutionError::Indeterminate(span) => {1423                self.dcx().create_err(diagnostics::Indeterminate(span))1424            }1425            VisResolutionError::ModuleOnly(span) => {1426                self.dcx().create_err(diagnostics::ModuleOnly(span))1427            }1428        }1429        .emit()1430    }14311432    pub(crate) fn def_path_str(&self, mut def_id: DefId) -> String {1433        // We can't use `def_path_str` in resolve.1434        let mut path = vec![def_id];1435        while let Some(parent) = self.tcx.opt_parent(def_id) {1436            def_id = parent;1437            path.push(def_id);1438            if def_id.is_top_level_module() {1439                break;1440            }1441        }1442        // We will only suggest importing directly if it is accessible through that path.1443        path.into_iter()1444            .rev()1445            .map(|def_id| {1446                self.tcx1447                    .opt_item_name(def_id)1448                    .map(|name| {1449                        match (1450                            def_id.is_top_level_module(),1451                            def_id.is_local(),1452                            self.tcx.sess.edition(),1453                        ) {1454                            (true, true, Edition::Edition2015) => String::new(),1455                            (true, true, _) => kw::Crate.to_string(),1456                            (true, false, _) | (false, _, _) => name.to_string(),1457                        }1458                    })1459                    .unwrap_or_else(|| "_".to_string())1460            })1461            .collect::<Vec<String>>()1462            .join("::")1463    }14641465    pub(crate) fn add_scope_set_candidates(1466        &self,1467        suggestions: &mut Vec<TypoSuggestion>,1468        scope_set: ScopeSet<'ra>,1469        ps: &ParentScope<'ra>,1470        sp: Span,1471        filter_fn: &impl Fn(Res) -> bool,1472    ) {1473        let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt());1474        self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| {1475            match scope {1476                Scope::DeriveHelpers(expn_id) => {1477                    let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);1478                    if filter_fn(res) {1479                        suggestions.extend(this.helper_attrs.get(&expn_id).into_flat_iter().map(1480                            |&(ident, orig_ident_span, _)| {1481                                TypoSuggestion::new(ident.name, orig_ident_span, res)1482                            },1483                        ));1484                    }1485                }1486                Scope::DeriveHelpersCompat => {1487                    // Never recommend deprecated helper attributes.1488                }1489                Scope::MacroRules(macro_rules_scope) => {1490                    if let MacroRulesScope::Def(macro_rules_def) = macro_rules_scope.get() {1491                        let res = macro_rules_def.decl.res();1492                        if filter_fn(res) {1493                            suggestions.push(TypoSuggestion::new(1494                                macro_rules_def.ident.name,1495                                macro_rules_def.orig_ident_span,1496                                res,1497                            ))1498                        }1499                    }1500                }1501                Scope::ModuleNonGlobs(module, _) => {1502                    this.add_module_candidates(module, suggestions, filter_fn, None);1503                }1504                Scope::ModuleGlobs(..) => {1505                    // Already handled in `ModuleNonGlobs`.1506                }1507                Scope::MacroUsePrelude => {1508                    suggestions.extend(this.macro_use_prelude.iter().filter_map(1509                        |(name, binding)| {1510                            let res = binding.res();1511                            filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))1512                        },1513                    ));1514                }1515                Scope::BuiltinAttrs => {1516                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));1517                    if filter_fn(res) {1518                        suggestions.extend(1519                            BUILTIN_ATTRIBUTES1520                                .iter()1521                                .map(|attr| TypoSuggestion::typo_from_name(*attr, res)),1522                        );1523                    }1524                }1525                Scope::ExternPreludeItems => {1526                    // Add idents from both item and flag scopes.1527                    suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, entry)| {1528                        let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());1529                        filter_fn(res).then_some(TypoSuggestion::new(ident.name, entry.span(), res))1530                    }));1531                }1532                Scope::ExternPreludeFlags => {}1533                Scope::ToolAttributePrelude => {1534                    let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);1535                    suggestions.extend(1536                        this.registered_attr_tools1537                            .iter()1538                            .map(|ident| TypoSuggestion::new(ident.name, ident.span, res)),1539                    );1540                }1541                Scope::StdLibPrelude => {1542                    if let Some(prelude) = this.prelude {1543                        let mut tmp_suggestions = Vec::new();1544                        this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);1545                        suggestions.extend(1546                            tmp_suggestions1547                                .into_iter()1548                                .filter(|s| use_prelude.into() || this.is_builtin_macro(s.res)),1549                        );1550                    }1551                }1552                Scope::BuiltinTypes => {1553                    suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {1554                        let res = Res::PrimTy(*prim_ty);1555                        filter_fn(res)1556                            .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))1557                    }))1558                }1559            }15601561            ControlFlow::<()>::Continue(())1562        });1563    }15641565    /// Lookup typo candidate in scope for a macro or import.1566    fn early_lookup_typo_candidate(1567        &self,1568        scope_set: ScopeSet<'ra>,1569        parent_scope: &ParentScope<'ra>,1570        ident: Ident,1571        filter_fn: &impl Fn(Res) -> bool,1572    ) -> Option<TypoSuggestion> {1573        let mut suggestions = Vec::new();1574        self.add_scope_set_candidates(1575            &mut suggestions,1576            scope_set,1577            parent_scope,1578            ident.span,1579            filter_fn,1580        );15811582        // Make sure error reporting is deterministic.1583        suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));15841585        match find_best_match_for_name(1586            &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),1587            ident.name,1588            None,1589        ) {1590            Some(found) if found != ident.name => {1591                suggestions.into_iter().find(|suggestion| suggestion.candidate == found)1592            }1593            _ => None,1594        }1595    }15961597    fn lookup_import_candidates_from_module<FilterFn>(1598        &self,1599        lookup_ident: Ident,1600        namespace: Namespace,1601        parent_scope: &ParentScope<'ra>,1602        start_module: Module<'ra>,1603        crate_path: ThinVec<ast::PathSegment>,1604        filter_fn: FilterFn,1605    ) -> Vec<ImportSuggestion>1606    where1607        FilterFn: Fn(Res) -> bool,1608    {1609        let mut candidates = Vec::new();1610        let mut seen_modules = FxHashSet::default();1611        let start_did = start_module.def_id();1612        let mut worklist = vec![(1613            start_module,1614            ThinVec::<ast::PathSegment>::new(),1615            true,1616            start_did.is_local() || !self.tcx.is_doc_hidden(start_did),1617            true,1618        )];1619        let mut worklist_via_import = vec![];16201621        while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) =1622            match worklist.pop() {1623                None => worklist_via_import.pop(),1624                Some(x) => Some(x),1625            }1626        {1627            let in_module_is_extern = !in_module.def_id().is_local();1628            in_module.for_each_child(self, |this, ident, orig_ident_span, ns, name_binding| {1629                // Avoid non-importable candidates.1630                if name_binding.is_assoc_item()1631                    && !this.features.import_trait_associated_functions()1632                {1633                    return;1634                }16351636                if ident.name == kw::Underscore {1637                    return;1638                }16391640                let child_accessible =1641                    accessible && this.is_accessible_from(name_binding.vis(), parent_scope.module);16421643                // do not venture inside inaccessible items of other crates1644                if in_module_is_extern && !child_accessible {1645                    return;1646                }16471648                let via_import = name_binding.is_import() && !name_binding.is_extern_crate();16491650                // There is an assumption elsewhere that paths of variants are in the enum's1651                // declaration and not imported. With this assumption, the variant component is1652                // chopped and the rest of the path is assumed to be the enum's own path. For1653                // errors where a variant is used as the type instead of the enum, this causes1654                // funny looking invalid suggestions, i.e `foo` instead of `foo::MyEnum`.1655                if via_import && name_binding.is_possibly_imported_variant() {1656                    return;1657                }16581659                // #90113: Do not count an inaccessible reexported item as a candidate.1660                if let DeclKind::Import { source_decl, .. } = name_binding.kind1661                    && this.is_accessible_from(source_decl.vis(), parent_scope.module)1662                    && !this.is_accessible_from(name_binding.vis(), parent_scope.module)1663                {1664                    return;1665                }16661667                let res = name_binding.res();1668                let did = match res {1669                    Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did),1670                    _ => res.opt_def_id(),1671                };1672                let child_doc_visible = doc_visible1673                    && did.is_none_or(|did| did.is_local() || !this.tcx.is_doc_hidden(did));16741675                // collect results based on the filter function1676                // avoid suggesting anything from the same module in which we are resolving1677                // avoid suggesting anything with a hygienic name1678                if ident.name == lookup_ident.name1679                    && ns == namespace1680                    && in_module != parent_scope.module1681                    && ident.ctxt.is_root()1682                    && filter_fn(res)1683                {1684                    // create the path1685                    let mut segms = if lookup_ident.span.at_least_rust_2018() {1686                        // crate-local absolute paths start with `crate::` in edition 20181687                        // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)1688                        crate_path.clone()1689                    } else {1690                        ThinVec::new()1691                    };1692                    segms.append(&mut path_segments.clone());16931694                    segms.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));1695                    let path = Path { span: name_binding.span, segments: segms };16961697                    if child_accessible1698                        // Remove invisible match if exists1699                        && let Some(idx) = candidates1700                            .iter()1701                            .position(|v: &ImportSuggestion| v.did == did && !v.accessible)1702                    {1703                        candidates.remove(idx);1704                    }17051706                    let is_stable = if is_stable1707                        && let Some(did) = did1708                        && this.is_stable(did, path.span)1709                    {1710                        true1711                    } else {1712                        false1713                    };17141715                    // Rreplace unstable suggestions if we meet a new stable one,1716                    // and do nothing if any other situation. For example, if we1717                    // meet `std::ops::Range` after `std::range::legacy::Range`,1718                    // we will remove the latter and then insert the former.1719                    if is_stable1720                        && let Some(idx) = candidates1721                            .iter()1722                            .position(|v: &ImportSuggestion| v.did == did && !v.is_stable)1723                    {1724                        candidates.remove(idx);1725                    }17261727                    if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {1728                        // See if we're recommending TryFrom, TryInto, or FromIterator and add1729                        // a note about editions1730                        let note = if let Some(did) = did {1731                            let requires_note = !did.is_local()1732                                && find_attr!(1733                                    this.tcx,1734                                    did,1735                                    RustcDiagnosticItem(1736                                        sym::TryInto | sym::TryFrom | sym::FromIterator1737                                    )1738                                );1739                            requires_note.then(|| {1740                                format!(1741                                    "'{}' is included in the prelude starting in Edition 2021",1742                                    path_names_to_string(&path)1743                                )1744                            })1745                        } else {1746                            None1747                        };17481749                        candidates.push(ImportSuggestion {1750                            did,1751                            descr: res.descr(),1752                            path,1753                            accessible: child_accessible,1754                            doc_visible: child_doc_visible,1755                            note,1756                            via_import,1757                            is_stable,1758                        });1759                    }1760                }17611762                // collect submodules to explore1763                if let Some(def_id) = name_binding.res().module_like_def_id() {1764                    // form the path1765                    let mut path_segments = path_segments.clone();1766                    path_segments.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));17671768                    let alias_import = if let DeclKind::Import { import, .. } = name_binding.kind1769                        && let ImportKind::ExternCrate { source: Some(_), .. } = import.kind1770                        && import.parent_scope.expansion == parent_scope.expansion1771                    {1772                        true1773                    } else {1774                        false1775                    };17761777                    let is_extern_crate_that_also_appears_in_prelude =1778                        name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();17791780                    if !is_extern_crate_that_also_appears_in_prelude || alias_import {1781                        // add the module to the lookup1782                        if seen_modules.insert(def_id) {1783                            if via_import { &mut worklist_via_import } else { &mut worklist }.push(1784                                (1785                                    this.expect_module(def_id),1786                                    path_segments,1787                                    child_accessible,1788                                    child_doc_visible,1789                                    is_stable && this.is_stable(def_id, name_binding.span),1790                                ),1791                            );1792                        }1793                    }1794                }1795            })1796        }17971798        candidates1799    }18001801    fn is_stable(&self, did: DefId, span: Span) -> bool {1802        if did.is_local() {1803            return true;1804        }18051806        match self.tcx.lookup_stability(did) {1807            Some(Stability {1808                level: StabilityLevel::Unstable { implied_by, .. }, feature, ..1809            }) => {1810                if span.allows_unstable(feature) {1811                    true1812                } else if self.features.enabled(feature) {1813                    true1814                } else if let Some(implied_by) = implied_by1815                    && self.features.enabled(implied_by)1816                {1817                    true1818                } else {1819                    false1820                }1821            }1822            Some(_) => true,1823            None => false,1824        }1825    }18261827    /// When name resolution fails, this method can be used to look up candidate1828    /// entities with the expected name. It allows filtering them using the1829    /// supplied predicate (which should be used to only accept the types of1830    /// definitions expected, e.g., traits). The lookup spans across all crates.1831    ///1832    /// N.B., the method does not look into imports, but this is not a problem,1833    /// since we report the definitions (thus, the de-aliased imports).1834    pub(crate) fn lookup_import_candidates<FilterFn>(1835        &self,1836        lookup_ident: Ident,1837        namespace: Namespace,1838        parent_scope: &ParentScope<'ra>,1839        filter_fn: FilterFn,1840    ) -> Vec<ImportSuggestion>1841    where1842        FilterFn: Fn(Res) -> bool,1843    {1844        let crate_path = thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate))];1845        let mut suggestions = self.lookup_import_candidates_from_module(1846            lookup_ident,1847            namespace,1848            parent_scope,1849            self.graph_root.to_module(),1850            crate_path,1851            &filter_fn,1852        );18531854        if lookup_ident.span.at_least_rust_2018() {1855            for (ident, entry) in &self.extern_prelude {1856                if entry.span().from_expansion() {1857                    // Idents are adjusted to the root context before being1858                    // resolved in the extern prelude, so reporting this to the1859                    // user is no help. This skips the injected1860                    // `extern crate std` in the 2018 edition, which would1861                    // otherwise cause duplicate suggestions.1862                    continue;1863                }1864                let Some(crate_id) =1865                    self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)1866                else {1867                    continue;1868                };18691870                let crate_def_id = crate_id.as_def_id();1871                let crate_root = self.expect_module(crate_def_id);18721873                // Check if there's already an item in scope with the same name as the crate.1874                // If so, we have to disambiguate the potential import suggestions by making1875                // the paths *global* (i.e., by prefixing them with `::`).1876                let needs_disambiguation =1877                    self.resolutions(parent_scope.module).iter().any(|(key, name_resolution)| {1878                        if key.ns == TypeNS1879                            && key.ident == *ident1880                            && let Some(decl) = name_resolution.borrow_checked(self).best_decl()1881                        {1882                            match decl.res() {1883                                // No disambiguation needed if the identically named item we1884                                // found in scope actually refers to the crate in question.1885                                Res::Def(_, def_id) => def_id != crate_def_id,1886                                Res::PrimTy(_) => true,1887                                _ => false,1888                            }1889                        } else {1890                            false1891                        }1892                    });1893                let mut crate_path = ThinVec::new();1894                if needs_disambiguation {1895                    crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));1896                }1897                crate_path.push(ast::PathSegment::from_ident(ident.orig(entry.span())));18981899                suggestions.extend(self.lookup_import_candidates_from_module(1900                    lookup_ident,1901                    namespace,1902                    parent_scope,1903                    crate_root,1904                    crate_path,1905                    &filter_fn,1906                ));1907            }1908        }19091910        suggestions.retain(|suggestion| suggestion.is_stable || self.tcx.sess.is_nightly_build());1911        suggestions1912    }19131914    pub(crate) fn unresolved_macro_suggestions(1915        &mut self,1916        err: &mut Diag<'_>,1917        macro_kind: MacroKind,1918        parent_scope: &ParentScope<'ra>,1919        ident: Ident,1920        krate: &Crate,1921        sugg_span: Option<Span>,1922    ) {1923        // Bring all unused `derive` macros into `macro_map` so we ensure they can be used for1924        // suggestions.1925        self.register_macros_for_all_crates();19261927        let is_expected =1928            &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));1929        let suggestion = self.early_lookup_typo_candidate(1930            ScopeSet::Macro(macro_kind),1931            parent_scope,1932            ident,1933            is_expected,1934        );1935        self.add_typo_suggestion(err, suggestion, ident.span);1936        self.detect_derive_attribute(err, ident, parent_scope, sugg_span);19371938        let import_suggestions =1939            self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);1940        let (span, found_use) = match parent_scope.module.nearest_parent_mod_node_id() {1941            DUMMY_NODE_ID => (None, FoundUse::No),1942            node_id => UsePlacementFinder::check(krate, node_id),1943        };1944        show_candidates(1945            self.tcx,1946            err,1947            span,1948            &import_suggestions,1949            Instead::No,1950            found_use,1951            DiagMode::Normal,1952            vec![],1953            "",1954        );19551956        if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {1957            let label_span = ident.span.shrink_to_hi();1958            let mut spans = MultiSpan::from_span(label_span);1959            spans.push_span_label(label_span, "put a macro name here");1960            err.subdiagnostic(MaybeMissingMacroRulesName { spans });1961            return;1962        }19631964        if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {1965            err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });1966            return;1967        }19681969        let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {1970            if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }1971        });19721973        if let Some((def_id, unused_ident)) = unused_macro {1974            let scope = self.local_macro_def_scopes[&def_id];1975            let parent_nearest = parent_scope.module.nearest_parent_mod();1976            let unused_macro_kinds = self.local_macro_map[def_id].macro_kinds();1977            if !unused_macro_kinds.contains(macro_kind.into()) {1978                match macro_kind {1979                    MacroKind::Bang => {1980                        err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });1981                    }1982                    MacroKind::Attr => {1983                        err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });1984                    }1985                    MacroKind::Derive => {1986                        err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });1987                    }1988                }1989                return;1990            }1991            if Some(parent_nearest.to_def_id()) == scope.opt_def_id() {1992                err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });1993                err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });1994                return;1995            }1996        }19971998        if ident.name == kw::Default1999            && let ModuleKind::Def(DefKind::Enum, def_id, _, _) = parent_scope.module.kind2000        {

Findings

✓ No findings reported for this file.

Get this view in your editor

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