// ignore-tidy-filelength
use std::mem;
use std::ops::ControlFlow;

use itertools::Itertools as _;
use rustc_ast::visit::{self, Visitor};
use rustc_ast::{
    self as ast, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, ItemKind, ModKind, NodeId, Path,
    join_path_idents,
};
use rustc_ast_pretty::pprust;
use rustc_data_structures::fx::{FxHashMap, FxHashSet};
use rustc_data_structures::unord::{UnordMap, UnordSet};
use rustc_errors::codes::*;
use rustc_errors::{
    Applicability, Diag, DiagCtxtHandle, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle,
    struct_span_code_err,
};
use rustc_feature::BUILTIN_ATTRIBUTES;
use rustc_hir::attrs::{CfgEntry, StrippedCfgItem};
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{CtorKind, CtorOf, DefKind, MacroKinds, NonMacroAttrKind, PerNS};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::{PrimTy, Stability, StabilityLevel, find_attr};
use rustc_middle::bug;
use rustc_middle::ty::{TyCtxt, Visibility};
use rustc_session::Session;
use rustc_session::lint::builtin::{
    ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE, AMBIGUOUS_GLOB_IMPORTS, AMBIGUOUS_IMPORT_VISIBILITIES,
    AMBIGUOUS_PANIC_IMPORTS, MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
};
use rustc_session::utils::was_invoked_from_cargo;
use rustc_span::edit_distance::find_best_match_for_name;
use rustc_span::edition::Edition;
use rustc_span::hygiene::MacroKind;
use rustc_span::source_map::SourceMap;
use rustc_span::{
    BytePos, Ident, RemapPathScopeComponents, Span, Spanned, Symbol, SyntaxContext, kw, sym,
};
use thin_vec::{ThinVec, thin_vec};
use tracing::{debug, instrument};

use crate::errors::{
    self, AddedMacroUse, ChangeImportBinding, ChangeImportBindingSuggestion, ConsiderAddingADerive,
    ExplicitUnsafeTraits, MacroDefinedLater, MacroRulesNot, MacroSuggMovePosition,
    MaybeMissingMacroRulesName,
};
use crate::hygiene::Macros20NormalizedSyntaxContext;
use crate::imports::{Import, ImportKind};
use crate::late::{DiagMetadata, PatternSource, Rib};
use crate::{
    AmbiguityError, AmbiguityKind, AmbiguityWarning, BindingError, BindingKey, Decl, DeclKind,
    DelayedVisResolutionError, Finalize, ForwardGenericParamBanReason, HasGenericParams, IdentKey,
    LateDecl, MacroRulesScope, Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult,
    PrivacyError, Res, ResolutionError, Resolver, Scope, ScopeSet, Segment, UseError, Used,
    VisResolutionError, errors as errs, path_names_to_string,
};

/// A vector of spans and replacements, a message and applicability.
pub(crate) type Suggestion = (Vec<(Span, String)>, String, Applicability);

/// Potential candidate for an undeclared or out-of-scope label - contains the ident of a
/// similarly named label and whether or not it is reachable.
pub(crate) type LabelSuggestion = (Ident, bool);

#[derive(Clone)]
pub(crate) struct StructCtor {
    pub res: Res,
    pub vis: Visibility<DefId>,
    pub field_visibilities: Vec<Visibility<DefId>>,
}

impl StructCtor {
    pub(crate) fn has_private_fields<'ra>(&self, m: Module<'ra>, r: &Resolver<'ra, '_>) -> bool {
        self.field_visibilities.iter().any(|&vis| !r.is_accessible_from(vis, m))
    }
}

#[derive(Debug)]
pub(crate) enum SuggestionTarget {
    /// The target has a similar name as the name used by the programmer (probably a typo)
    SimilarlyNamed,
    /// The target is the only valid item that can be used in the corresponding context
    SingleItem,
}

#[derive(Debug)]
pub(crate) struct TypoSuggestion {
    pub candidate: Symbol,
    /// The source location where the name is defined; None if the name is not defined
    /// in source e.g. primitives
    pub span: Option<Span>,
    pub res: Res,
    pub target: SuggestionTarget,
}

impl TypoSuggestion {
    pub(crate) fn new(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
        Self { candidate, span: Some(span), res, target: SuggestionTarget::SimilarlyNamed }
    }
    pub(crate) fn typo_from_name(candidate: Symbol, res: Res) -> TypoSuggestion {
        Self { candidate, span: None, res, target: SuggestionTarget::SimilarlyNamed }
    }
    pub(crate) fn single_item(candidate: Symbol, span: Span, res: Res) -> TypoSuggestion {
        Self { candidate, span: Some(span), res, target: SuggestionTarget::SingleItem }
    }
}

/// A free importable items suggested in case of resolution failure.
#[derive(Debug, Clone)]
pub(crate) struct ImportSuggestion {
    pub did: Option<DefId>,
    pub descr: &'static str,
    pub path: Path,
    pub accessible: bool,
    // false if the path traverses a foreign `#[doc(hidden)]` item.
    pub doc_visible: bool,
    pub via_import: bool,
    /// An extra note that should be issued if this item is suggested
    pub note: Option<String>,
    pub is_stable: bool,
}

/// Adjust the impl span so that just the `impl` keyword is taken by removing
/// everything after `<` (`"impl<T> Iterator for A<T> {}" -> "impl"`) and
/// everything after the first whitespace (`"impl Iterator for A" -> "impl"`).
///
/// *Attention*: the method used is very fragile since it essentially duplicates the work of the
/// parser. If you need to use this function or something similar, please consider updating the
/// `source_map` functions and this function to something more robust.
fn reduce_impl_span_to_impl_keyword(sm: &SourceMap, impl_span: Span) -> Span {
    let impl_span = sm.span_until_char(impl_span, '<');
    sm.span_until_whitespace(impl_span)
}

impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
    pub(crate) fn dcx(&self) -> DiagCtxtHandle<'tcx> {
        self.tcx.dcx()
    }

    pub(crate) fn report_errors(&mut self, krate: &Crate) {
        self.report_delayed_vis_resolution_errors();
        self.report_with_use_injections(krate);

        for &(span_use, span_def) in &self.macro_expanded_macro_export_errors {
            self.lint_buffer.buffer_lint(
                MACRO_EXPANDED_MACRO_EXPORTS_ACCESSED_BY_ABSOLUTE_PATHS,
                CRATE_NODE_ID,
                span_use,
                errors::MacroExpandedMacroExportsAccessedByAbsolutePaths { definition: span_def },
            );
        }

        for ambiguity_error in &self.ambiguity_errors {
            let mut diag = self.ambiguity_diagnostic(ambiguity_error);

            if let Some(ambiguity_warning) = ambiguity_error.warning {
                let node_id = match ambiguity_error.b1.0.kind {
                    DeclKind::Import { import, .. } => import.root_id,
                    DeclKind::Def(_) => CRATE_NODE_ID,
                };

                let lint = match ambiguity_warning {
                    _ if ambiguity_error.ambig_vis.is_some() => AMBIGUOUS_IMPORT_VISIBILITIES,
                    AmbiguityWarning::GlobImport => AMBIGUOUS_GLOB_IMPORTS,
                    AmbiguityWarning::PanicImport => AMBIGUOUS_PANIC_IMPORTS,
                };

                self.lint_buffer.buffer_lint(lint, node_id, diag.ident.span, diag);
            } else {
                diag.is_error = true;
                self.dcx().emit_err(diag);
            }
        }

        let mut reported_spans = FxHashSet::default();
        for error in mem::take(&mut self.privacy_errors) {
            if reported_spans.insert(error.dedup_span) {
                self.report_privacy_error(&error);
            }
        }
    }

    fn report_delayed_vis_resolution_errors(&mut self) {
        for DelayedVisResolutionError { vis, parent_scope, error } in
            mem::take(&mut self.delayed_vis_resolution_errors)
        {
            match self.try_resolve_visibility(&parent_scope, &vis, true) {
                Ok(_) => self.report_vis_error(error),
                Err(error) => self.report_vis_error(error),
            };
        }
    }

    fn report_with_use_injections(&mut self, krate: &Crate) {
        for UseError { mut err, candidates, node_id, instead, suggestion, path, is_call } in
            mem::take(&mut self.use_injections)
        {
            let (span, found_use) = if node_id != DUMMY_NODE_ID {
                UsePlacementFinder::check(krate, node_id)
            } else {
                (None, FoundUse::No)
            };

            if !candidates.is_empty() {
                show_candidates(
                    self.tcx,
                    &mut err,
                    span,
                    &candidates,
                    if instead { Instead::Yes } else { Instead::No },
                    found_use,
                    DiagMode::Normal,
                    path,
                    "",
                );
                err.emit();
            } else if let Some((span, msg, sugg, appl)) = suggestion {
                err.span_suggestion_verbose(span, msg, sugg, appl);
                err.emit();
            } else if let [segment] = path.as_slice()
                && is_call
            {
                err.stash(segment.ident.span, rustc_errors::StashKey::CallIntoMethod);
            } else {
                err.emit();
            }
        }
    }

    pub(crate) fn report_conflict(
        &mut self,
        ident: IdentKey,
        ns: Namespace,
        old_binding: Decl<'ra>,
        new_binding: Decl<'ra>,
    ) {
        // Error on the second of two conflicting names
        if old_binding.span.lo() > new_binding.span.lo() {
            return self.report_conflict(ident, ns, new_binding, old_binding);
        }

        let container = match old_binding.parent_module.unwrap().expect_local().kind {
            // Avoid using TyCtxt::def_kind_descr in the resolver, because it
            // indirectly *calls* the resolver, and would cause a query cycle.
            ModuleKind::Def(kind, def_id, _, _) => kind.descr(def_id),
            ModuleKind::Block => "block",
        };

        let (name, span) =
            (ident.name, self.tcx.sess.source_map().guess_head_span(new_binding.span));

        if self.name_already_seen.get(&name) == Some(&span) {
            return;
        }

        let old_kind = match (ns, old_binding.res()) {
            (ValueNS, _) => "value",
            (MacroNS, _) => "macro",
            (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
            (TypeNS, Res::Def(DefKind::Mod, _)) => "module",
            (TypeNS, Res::Def(DefKind::Trait, _)) => "trait",
            (TypeNS, _) => "type",
        };

        let code = match (old_binding.is_extern_crate(), new_binding.is_extern_crate()) {
            (true, true) => E0259,
            (true, _) | (_, true) => match new_binding.is_import() && old_binding.is_import() {
                true => E0254,
                false => E0260,
            },
            _ => match (old_binding.is_import_user_facing(), new_binding.is_import_user_facing()) {
                (false, false) => E0428,
                (true, true) => E0252,
                _ => E0255,
            },
        };

        let label = match new_binding.is_import_user_facing() {
            true => errors::NameDefinedMultipleTimeLabel::Reimported { span, name },
            false => errors::NameDefinedMultipleTimeLabel::Redefined { span, name },
        };

        let old_binding_label =
            (!old_binding.span.is_dummy() && old_binding.span != span).then(|| {
                let span = self.tcx.sess.source_map().guess_head_span(old_binding.span);
                match old_binding.is_import_user_facing() {
                    true => errors::NameDefinedMultipleTimeOldBindingLabel::Import {
                        span,
                        old_kind,
                        name,
                    },
                    false => errors::NameDefinedMultipleTimeOldBindingLabel::Definition {
                        span,
                        old_kind,
                        name,
                    },
                }
            });

        let mut err = self
            .dcx()
            .create_err(errors::NameDefinedMultipleTime {
                span,
                name,
                descr: ns.descr(),
                container,
                label,
                old_binding_label,
            })
            .with_code(code);

        // See https://github.com/rust-lang/rust/issues/32354
        use DeclKind::Import;
        let can_suggest = |binding: Decl<'_>, import: self::Import<'_>| {
            !binding.span.is_dummy()
                && !matches!(import.kind, ImportKind::MacroUse { .. } | ImportKind::MacroExport)
        };
        let import = match (&new_binding.kind, &old_binding.kind) {
            // If there are two imports where one or both have attributes then prefer removing the
            // import without attributes.
            (Import { import: new, .. }, Import { import: old, .. })
                if {
                    (new.has_attributes || old.has_attributes)
                        && can_suggest(old_binding, *old)
                        && can_suggest(new_binding, *new)
                } =>
            {
                if old.has_attributes {
                    Some((*new, new_binding.span, true))
                } else {
                    Some((*old, old_binding.span, true))
                }
            }
            // Otherwise prioritize the new binding.
            (Import { import, .. }, other) if can_suggest(new_binding, *import) => {
                Some((*import, new_binding.span, other.is_import()))
            }
            (other, Import { import, .. }) if can_suggest(old_binding, *import) => {
                Some((*import, old_binding.span, other.is_import()))
            }
            _ => None,
        };

        // Check if the target of the use for both bindings is the same.
        let duplicate = new_binding.res().opt_def_id() == old_binding.res().opt_def_id();
        let has_dummy_span = new_binding.span.is_dummy() || old_binding.span.is_dummy();
        let from_item =
            self.extern_prelude.get(&ident).is_none_or(|entry| entry.introduced_by_item());
        // Only suggest removing an import if both bindings are to the same def, if both spans
        // aren't dummy spans. Further, if both bindings are imports, then the ident must have
        // been introduced by an item.
        let should_remove_import = duplicate
            && !has_dummy_span
            && ((new_binding.is_extern_crate() || old_binding.is_extern_crate()) || from_item);

        match import {
            Some((import, span, true)) if should_remove_import && import.is_nested() => {
                self.add_suggestion_for_duplicate_nested_use(&mut err, import, span);
            }
            Some((import, _, true)) if should_remove_import && !import.is_glob() => {
                // Simple case - remove the entire import. Due to the above match arm, this can
                // only be a single use so just remove it entirely.
                err.subdiagnostic(errors::ToolOnlyRemoveUnnecessaryImport {
                    span: import.use_span_with_attributes,
                });
            }
            Some((import, span, _)) => {
                self.add_suggestion_for_rename_of_use(&mut err, name, import, span);
            }
            _ => {}
        }

        err.emit();
        self.name_already_seen.insert(name, span);
    }

    /// This function adds a suggestion to change the binding name of a new import that conflicts
    /// with an existing import.
    ///
    /// ```text,ignore (diagnostic)
    /// help: you can use `as` to change the binding name of the import
    ///    |
    /// LL | use foo::bar as other_bar;
    ///    |     ^^^^^^^^^^^^^^^^^^^^^
    /// ```
    fn add_suggestion_for_rename_of_use(
        &self,
        err: &mut Diag<'_>,
        name: Symbol,
        import: Import<'_>,
        binding_span: Span,
    ) {
        let suggested_name = if name.as_str().chars().next().unwrap().is_uppercase() {
            format!("Other{name}")
        } else {
            format!("other_{name}")
        };

        let mut suggestion = None;
        let mut span = binding_span;
        match import.kind {
            ImportKind::Single { source, .. } => {
                if let Some(pos) = source.span.hi().0.checked_sub(binding_span.lo().0)
                    && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(binding_span)
                    && pos as usize <= snippet.len()
                {
                    span = binding_span.with_lo(binding_span.lo() + BytePos(pos)).with_hi(
                        binding_span.hi() - BytePos(if snippet.ends_with(';') { 1 } else { 0 }),
                    );
                    suggestion = Some(format!(" as {suggested_name}"));
                }
            }
            ImportKind::ExternCrate { source, target, .. } => {
                suggestion = Some(format!(
                    "extern crate {} as {};",
                    source.unwrap_or(target.name),
                    suggested_name,
                ))
            }
            _ => unreachable!(),
        }

        if let Some(suggestion) = suggestion {
            err.subdiagnostic(ChangeImportBindingSuggestion { span, suggestion });
        } else {
            err.subdiagnostic(ChangeImportBinding { span });
        }
    }

    /// This function adds a suggestion to remove an unnecessary binding from an import that is
    /// nested. In the following example, this function will be invoked to remove the `a` binding
    /// in the second use statement:
    ///
    /// ```ignore (diagnostic)
    /// use issue_52891::a;
    /// use issue_52891::{d, a, e};
    /// ```
    ///
    /// The following suggestion will be added:
    ///
    /// ```ignore (diagnostic)
    /// use issue_52891::{d, a, e};
    ///                      ^-- help: remove unnecessary import
    /// ```
    ///
    /// If the nested use contains only one import then the suggestion will remove the entire
    /// line.
    ///
    /// It is expected that the provided import is nested - this isn't checked by the
    /// function. If this invariant is not upheld, this function's behaviour will be unexpected
    /// as characters expected by span manipulations won't be present.
    fn add_suggestion_for_duplicate_nested_use(
        &self,
        err: &mut Diag<'_>,
        import: Import<'_>,
        binding_span: Span,
    ) {
        assert!(import.is_nested());

        // Two examples will be used to illustrate the span manipulations we're doing:
        //
        // - Given `use issue_52891::{d, a, e};` where `a` is a duplicate then `binding_span` is
        //   `a` and `import.use_span` is `issue_52891::{d, a, e};`.
        // - Given `use issue_52891::{d, e, a};` where `a` is a duplicate then `binding_span` is
        //   `a` and `import.use_span` is `issue_52891::{d, e, a};`.

        let (found_closing_brace, span) =
            find_span_of_binding_until_next_binding(self.tcx.sess, binding_span, import.use_span);

        // If there was a closing brace then identify the span to remove any trailing commas from
        // previous imports.
        if found_closing_brace {
            if let Some(span) = extend_span_to_previous_binding(self.tcx.sess, span) {
                err.subdiagnostic(errors::ToolOnlyRemoveUnnecessaryImport { span });
            } else {
                // Remove the entire line if we cannot extend the span back, this indicates an
                // `issue_52891::{self}` case.
                err.subdiagnostic(errors::RemoveUnnecessaryImport {
                    span: import.use_span_with_attributes,
                });
            }

            return;
        }

        err.subdiagnostic(errors::RemoveUnnecessaryImport { span });
    }

    pub(crate) fn lint_if_path_starts_with_module(
        &mut self,
        finalize: Finalize,
        path: &[Segment],
        second_binding: Option<Decl<'_>>,
    ) {
        let Finalize { node_id, root_span, .. } = finalize;

        let first_name = match path.get(0) {
            // In the 2018 edition this lint is a hard error, so nothing to do
            Some(seg) if seg.ident.span.is_rust_2015() && self.tcx.sess.is_rust_2015() => {
                seg.ident.name
            }
            _ => return,
        };

        // We're only interested in `use` paths which should start with
        // `{{root}}` currently.
        if first_name != kw::PathRoot {
            return;
        }

        match path.get(1) {
            // If this import looks like `crate::...` it's already good
            Some(Segment { ident, .. }) if ident.name == kw::Crate => return,
            // Otherwise go below to see if it's an extern crate
            Some(_) => {}
            // If the path has length one (and it's `PathRoot` most likely)
            // then we don't know whether we're gonna be importing a crate or an
            // item in our crate. Defer this lint to elsewhere
            None => return,
        }

        // If the first element of our path was actually resolved to an
        // `ExternCrate` (also used for `crate::...`) then no need to issue a
        // warning, this looks all good!
        if let Some(binding) = second_binding
            && let DeclKind::Import { import, .. } = binding.kind
            // Careful: we still want to rewrite paths from renamed extern crates.
            && let ImportKind::ExternCrate { source: None, .. } = import.kind
        {
            return;
        }

        self.lint_buffer.dyn_buffer_lint_any(
            ABSOLUTE_PATHS_NOT_STARTING_WITH_CRATE,
            node_id,
            root_span,
            move |dcx, level, sess| {
                let (replacement, applicability) = match sess
                    .downcast_ref::<Session>()
                    .expect("expected a `Session`")
                    .source_map()
                    .span_to_snippet(root_span)
                {
                    Ok(ref s) => {
                        // FIXME(Manishearth) ideally the emitting code
                        // can tell us whether or not this is global
                        let opt_colon = if s.trim_start().starts_with("::") { "" } else { "::" };

                        (format!("crate{opt_colon}{s}"), Applicability::MachineApplicable)
                    }
                    Err(_) => ("crate::<path>".to_string(), Applicability::HasPlaceholders),
                };
                errors::AbsPathWithModule {
                    sugg: errors::AbsPathWithModuleSugg {
                        span: root_span,
                        applicability,
                        replacement,
                    },
                }
                .into_diag(dcx, level)
            },
        );
    }

    pub(crate) fn add_module_candidates(
        &self,
        module: Module<'ra>,
        names: &mut Vec<TypoSuggestion>,
        filter_fn: &impl Fn(Res) -> bool,
        ctxt: Option<SyntaxContext>,
    ) {
        module.for_each_child(self, |_this, ident, orig_ident_span, _ns, binding| {
            let res = binding.res();
            if filter_fn(res) && ctxt.is_none_or(|ctxt| ctxt == *ident.ctxt) {
                names.push(TypoSuggestion::new(ident.name, orig_ident_span, res));
            }
        });
    }

    /// Combines an error with provided span and emits it.
    ///
    /// This takes the error provided, combines it with the span and any additional spans inside the
    /// error and emits it.
    pub(crate) fn report_error(
        &mut self,
        span: Span,
        resolution_error: ResolutionError<'ra>,
    ) -> ErrorGuaranteed {
        self.into_struct_error(span, resolution_error).emit()
    }

    pub(crate) fn into_struct_error(
        &mut self,
        span: Span,
        resolution_error: ResolutionError<'ra>,
    ) -> Diag<'_> {
        match resolution_error {
            ResolutionError::GenericParamsFromOuterItem {
                outer_res,
                has_generic_params,
                def_kind,
                inner_item,
                current_self_ty,
            } => {
                use errs::GenericParamsFromOuterItemLabel as Label;
                let static_or_const = match def_kind {
                    DefKind::Static { .. } => {
                        Some(errs::GenericParamsFromOuterItemStaticOrConst::Static)
                    }
                    DefKind::Const { .. } => {
                        Some(errs::GenericParamsFromOuterItemStaticOrConst::Const)
                    }
                    _ => None,
                };
                let is_self =
                    matches!(outer_res, Res::SelfTyParam { .. } | Res::SelfTyAlias { .. });
                let mut err = errs::GenericParamsFromOuterItem {
                    span,
                    label: None,
                    refer_to_type_directly: None,
                    use_let: None,
                    sugg: None,
                    static_or_const,
                    is_self,
                    item: inner_item.as_ref().map(|(label_span, _, kind)| {
                        errs::GenericParamsFromOuterItemInnerItem {
                            span: *label_span,
                            descr: kind.descr().to_string(),
                            is_self,
                        }
                    }),
                };

                let sm = self.tcx.sess.source_map();
                // Note: do not early return for missing def_id here,
                // we still want to provide suggestions for `Res::SelfTyParam` and `Res::SelfTyAlias`.
                let def_id = match outer_res {
                    Res::SelfTyParam { .. } => {
                        err.label = Some(Label::SelfTyParam(span));
                        None
                    }
                    Res::SelfTyAlias { alias_to: def_id, .. } => {
                        err.label = Some(Label::SelfTyAlias(reduce_impl_span_to_impl_keyword(
                            sm,
                            self.def_span(def_id),
                        )));
                        err.refer_to_type_directly =
                            current_self_ty.map(|snippet| errs::UseTypeDirectly { span, snippet });
                        None
                    }
                    Res::Def(DefKind::TyParam, def_id) => {
                        err.label = Some(Label::TyParam(self.def_span(def_id)));
                        Some(def_id)
                    }
                    Res::Def(DefKind::ConstParam, def_id) => {
                        err.label = Some(Label::ConstParam(self.def_span(def_id)));
                        Some(def_id)
                    }
                    _ => {
                        bug!(
                            "GenericParamsFromOuterItem should only be used with \
                            Res::SelfTyParam, Res::SelfTyAlias, DefKind::TyParam or \
                            DefKind::ConstParam"
                        );
                    }
                };

                if let Some((_, item_span, ItemKind::Const(_))) = inner_item.as_ref() {
                    err.use_let = Some(errs::GenericParamsFromOuterItemUseLet {
                        span: sm.span_until_whitespace(*item_span),
                    });
                }

                if let Some(def_id) = def_id
                    && let HasGenericParams::Yes(span) = has_generic_params
                    && !matches!(inner_item, Some((_, _, ItemKind::Delegation(..))))
                {
                    let name = self.tcx.item_name(def_id);
                    let (span, snippet) = if span.is_empty() {
                        let snippet = format!("<{name}>");
                        (span, snippet)
                    } else {
                        let span = sm.span_through_char(span, '<').shrink_to_hi();
                        let snippet = format!("{name}, ");
                        (span, snippet)
                    };
                    err.sugg = Some(errs::GenericParamsFromOuterItemSugg { span, snippet });
                }

                self.dcx().create_err(err)
            }
            ResolutionError::NameAlreadyUsedInParameterList(name, first_use_span) => self
                .dcx()
                .create_err(errs::NameAlreadyUsedInParameterList { span, first_use_span, name }),
            ResolutionError::MethodNotMemberOfTrait(method, trait_, candidate) => {
                self.dcx().create_err(errs::MethodNotMemberOfTrait {
                    span,
                    method,
                    trait_,
                    sub: candidate.map(|c| errs::AssociatedFnWithSimilarNameExists {
                        span: method.span,
                        candidate: c,
                    }),
                })
            }
            ResolutionError::TypeNotMemberOfTrait(type_, trait_, candidate) => {
                self.dcx().create_err(errs::TypeNotMemberOfTrait {
                    span,
                    type_,
                    trait_,
                    sub: candidate.map(|c| errs::AssociatedTypeWithSimilarNameExists {
                        span: type_.span,
                        candidate: c,
                    }),
                })
            }
            ResolutionError::ConstNotMemberOfTrait(const_, trait_, candidate) => {
                self.dcx().create_err(errs::ConstNotMemberOfTrait {
                    span,
                    const_,
                    trait_,
                    sub: candidate.map(|c| errs::AssociatedConstWithSimilarNameExists {
                        span: const_.span,
                        candidate: c,
                    }),
                })
            }
            ResolutionError::VariableNotBoundInPattern(binding_error, parent_scope) => {
                let BindingError { name, target, origin, could_be_path } = binding_error;

                let mut target_sp = target.iter().map(|pat| pat.span).collect::<Vec<_>>();
                target_sp.sort();
                target_sp.dedup();
                let mut origin_sp = origin.iter().map(|(span, _)| *span).collect::<Vec<_>>();
                origin_sp.sort();
                origin_sp.dedup();

                let msp = MultiSpan::from_spans(target_sp.clone());
                let mut err = self
                    .dcx()
                    .create_err(errors::VariableIsNotBoundInAllPatterns { multispan: msp, name });
                for sp in target_sp {
                    err.subdiagnostic(errors::PatternDoesntBindName { span: sp, name });
                }
                for sp in &origin_sp {
                    err.subdiagnostic(errors::VariableNotInAllPatterns { span: *sp });
                }
                let mut suggested_typo = false;
                if !target.iter().all(|pat| matches!(pat.kind, ast::PatKind::Ident(..)))
                    && !origin.iter().all(|(_, pat)| matches!(pat.kind, ast::PatKind::Ident(..)))
                {
                    // The check above is so that when we encounter `match foo { (a | b) => {} }`,
                    // we don't suggest `(a | a) => {}`, which would never be what the user wants.
                    let mut target_visitor = BindingVisitor::default();
                    for pat in &target {
                        target_visitor.visit_pat(pat);
                    }
                    target_visitor.identifiers.sort();
                    target_visitor.identifiers.dedup();
                    let mut origin_visitor = BindingVisitor::default();
                    for (_, pat) in &origin {
                        origin_visitor.visit_pat(pat);
                    }
                    origin_visitor.identifiers.sort();
                    origin_visitor.identifiers.dedup();
                    // Find if the binding could have been a typo
                    if let Some(typo) =
                        find_best_match_for_name(&target_visitor.identifiers, name.name, None)
                        && !origin_visitor.identifiers.contains(&typo)
                    {
                        err.subdiagnostic(errors::PatternBindingTypo { spans: origin_sp, typo });
                        suggested_typo = true;
                    }
                }
                if could_be_path {
                    let import_suggestions = self.lookup_import_candidates(
                        name,
                        Namespace::ValueNS,
                        &parent_scope,
                        &|res: Res| {
                            matches!(
                                res,
                                Res::Def(
                                    DefKind::Ctor(CtorOf::Variant, CtorKind::Const)
                                        | DefKind::Ctor(CtorOf::Struct, CtorKind::Const)
                                        | DefKind::Const { .. }
                                        | DefKind::AssocConst { .. },
                                    _,
                                )
                            )
                        },
                    );

                    if import_suggestions.is_empty() && !suggested_typo {
                        let kind_matches: [fn(DefKind) -> bool; 4] = [
                            |kind| matches!(kind, DefKind::Ctor(CtorOf::Variant, CtorKind::Const)),
                            |kind| matches!(kind, DefKind::Ctor(CtorOf::Struct, CtorKind::Const)),
                            |kind| matches!(kind, DefKind::Const { .. }),
                            |kind| matches!(kind, DefKind::AssocConst { .. }),
                        ];
                        let mut local_names = vec![];
                        self.add_module_candidates(
                            parent_scope.module,
                            &mut local_names,
                            &|res| matches!(res, Res::Def(_, _)),
                            None,
                        );
                        let local_names: FxHashSet<_> = local_names
                            .into_iter()
                            .filter_map(|s| match s.res {
                                Res::Def(_, def_id) => Some(def_id),
                                _ => None,
                            })
                            .collect();

                        let mut local_suggestions = vec![];
                        let mut suggestions = vec![];
                        for matches_kind in kind_matches {
                            if let Some(suggestion) = self.early_lookup_typo_candidate(
                                ScopeSet::All(Namespace::ValueNS),
                                &parent_scope,
                                name,
                                &|res: Res| match res {
                                    Res::Def(k, _) => matches_kind(k),
                                    _ => false,
                                },
                            ) && let Res::Def(kind, mut def_id) = suggestion.res
                            {
                                if let DefKind::Ctor(_, _) = kind {
                                    def_id = self.tcx.parent(def_id);
                                }
                                let kind = kind.descr(def_id);
                                if local_names.contains(&def_id) {
                                    // The item is available in the current scope. Very likely to
                                    // be a typo. Don't use the full path.
                                    local_suggestions.push((
                                        suggestion.candidate,
                                        suggestion.candidate.to_string(),
                                        kind,
                                    ));
                                } else {
                                    suggestions.push((
                                        suggestion.candidate,
                                        self.def_path_str(def_id),
                                        kind,
                                    ));
                                }
                            }
                        }
                        let suggestions = if !local_suggestions.is_empty() {
                            // There is at least one item available in the current scope that is a
                            // likely typo. We only show those.
                            local_suggestions
                        } else {
                            suggestions
                        };
                        for (name, sugg, kind) in suggestions {
                            err.span_suggestion_verbose(
                                span,
                                format!(
                                    "you might have meant to use the similarly named {kind} `{name}`",
                                ),
                                sugg,
                                Applicability::MaybeIncorrect,
                            );
                            suggested_typo = true;
                        }
                    }
                    if import_suggestions.is_empty() && !suggested_typo {
                        let help_msg = format!(
                            "if you meant to match on a unit struct, unit variant or a `const` \
                             item, consider making the path in the pattern qualified: \
                             `path::to::ModOrType::{name}`",
                        );
                        err.span_help(span, help_msg);
                    }
                    show_candidates(
                        self.tcx,
                        &mut err,
                        Some(span),
                        &import_suggestions,
                        Instead::No,
                        FoundUse::Yes,
                        DiagMode::Pattern,
                        vec![],
                        "",
                    );
                }
                err
            }
            ResolutionError::VariableBoundWithDifferentMode(variable_name, first_binding_span) => {
                self.dcx().create_err(errs::VariableBoundWithDifferentMode {
                    span,
                    first_binding_span,
                    variable_name,
                })
            }
            ResolutionError::IdentifierBoundMoreThanOnceInParameterList(identifier) => self
                .dcx()
                .create_err(errs::IdentifierBoundMoreThanOnceInParameterList { span, identifier }),
            ResolutionError::IdentifierBoundMoreThanOnceInSamePattern(identifier) => self
                .dcx()
                .create_err(errs::IdentifierBoundMoreThanOnceInSamePattern { span, identifier }),
            ResolutionError::UndeclaredLabel { name, suggestion } => {
                let ((sub_reachable, sub_reachable_suggestion), sub_unreachable) = match suggestion
                {
                    // A reachable label with a similar name exists.
                    Some((ident, true)) => (
                        (
                            Some(errs::LabelWithSimilarNameReachable(ident.span)),
                            Some(errs::TryUsingSimilarlyNamedLabel {
                                span,
                                ident_name: ident.name,
                            }),
                        ),
                        None,
                    ),
                    // An unreachable label with a similar name exists.
                    Some((ident, false)) => (
                        (None, None),
                        Some(errs::UnreachableLabelWithSimilarNameExists {
                            ident_span: ident.span,
                        }),
                    ),
                    // No similarly-named labels exist.
                    None => ((None, None), None),
                };
                self.dcx().create_err(errs::UndeclaredLabel {
                    span,
                    name,
                    sub_reachable,
                    sub_reachable_suggestion,
                    sub_unreachable,
                })
            }
            ResolutionError::FailedToResolve { segment, label, suggestion, module, message } => {
                let mut err = struct_span_code_err!(self.dcx(), span, E0433, "{message}");
                err.span_label(span, label);

                if let Some((suggestions, msg, applicability)) = suggestion {
                    if suggestions.is_empty() {
                        err.help(msg);
                        return err;
                    }
                    err.multipart_suggestion(msg, suggestions, applicability);
                }

                let module = match module {
                    Some(ModuleOrUniformRoot::Module(m)) if let Some(id) = m.opt_def_id() => id,
                    _ => CRATE_DEF_ID.to_def_id(),
                };
                self.find_cfg_stripped(&mut err, &segment, module);

                err
            }
            ResolutionError::CannotCaptureDynamicEnvironmentInFnItem => {
                self.dcx().create_err(errs::CannotCaptureDynamicEnvironmentInFnItem { span })
            }
            ResolutionError::AttemptToUseNonConstantValueInConstant {
                ident,
                suggestion,
                current,
                type_span,
            } => {
                // let foo =...
                //     ^^^ given this Span
                // ------- get this Span to have an applicable suggestion

                // edit:
                // only do this if the const and usage of the non-constant value are on the same line
                // the further the two are apart, the higher the chance of the suggestion being wrong

                let sp = self
                    .tcx
                    .sess
                    .source_map()
                    .span_extend_to_prev_str(ident.span, current, true, false);

                let (with, with_label, without) = match sp {
                    Some(sp) if !self.tcx.sess.source_map().is_multiline(sp) => {
                        let sp = sp
                            .with_lo(BytePos(sp.lo().0 - (current.len() as u32)))
                            .until(ident.span);

                        // Only suggest replacing the binding keyword if this is a simple
                        // binding.
                        //
                        // Note: this approach still incorrectly suggests for irrefutable
                        // patterns like `if let x = 1 { const { x } }`, since the text
                        // between `let` and the identifier is just whitespace.
                        // See tests/ui/consts/non-const-value-in-const-irrefutable-pat-binding.rs
                        let is_simple_binding =
                            self.tcx.sess.source_map().span_to_snippet(sp).is_ok_and(|snippet| {
                                let after_keyword = snippet[current.len()..].trim();
                                after_keyword.is_empty() || after_keyword == "mut"
                            });

                        if is_simple_binding {
                            (
                                Some(errs::AttemptToUseNonConstantValueInConstantWithSuggestion {
                                    span: sp,
                                    suggestion,
                                    current,
                                    type_span,
                                }),
                                Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
                                None,
                            )
                        } else {
                            (
                                None,
                                Some(errs::AttemptToUseNonConstantValueInConstantLabelWithSuggestion { span }),
                                None,
                            )
                        }
                    }
                    _ => (
                        None,
                        None,
                        Some(errs::AttemptToUseNonConstantValueInConstantWithoutSuggestion {
                            ident_span: ident.span,
                            suggestion,
                        }),
                    ),
                };

                self.dcx().create_err(errs::AttemptToUseNonConstantValueInConstant {
                    span,
                    with,
                    with_label,
                    without,
                })
            }
            ResolutionError::BindingShadowsSomethingUnacceptable {
                shadowing_binding,
                name,
                participle,
                article,
                shadowed_binding,
                shadowed_binding_span,
            } => self.dcx().create_err(errs::BindingShadowsSomethingUnacceptable {
                span,
                shadowing_binding,
                shadowed_binding,
                article,
                sub_suggestion: match (shadowing_binding, shadowed_binding) {
                    (
                        PatternSource::Match,
                        Res::Def(DefKind::Ctor(CtorOf::Variant | CtorOf::Struct, CtorKind::Fn), _),
                    ) => Some(errs::BindingShadowsSomethingUnacceptableSuggestion { span, name }),
                    _ => None,
                },
                shadowed_binding_span,
                participle,
                name,
            }),
            ResolutionError::ForwardDeclaredGenericParam(param, reason) => match reason {
                ForwardGenericParamBanReason::Default => {
                    self.dcx().create_err(errs::ForwardDeclaredGenericParam { param, span })
                }
                ForwardGenericParamBanReason::ConstParamTy => self
                    .dcx()
                    .create_err(errs::ForwardDeclaredGenericInConstParamTy { param, span }),
            },
            ResolutionError::ParamInTyOfConstParam { name } => {
                self.dcx().create_err(errs::ParamInTyOfConstParam { span, name })
            }
            ResolutionError::ParamInNonTrivialAnonConst { is_gca, name, param_kind: is_type } => {
                self.dcx().create_err(errs::ParamInNonTrivialAnonConst {
                    span,
                    name,
                    param_kind: is_type,
                    help: self.tcx.sess.is_nightly_build(),
                    is_gca,
                    help_gca: is_gca,
                })
            }
            ResolutionError::ParamInEnumDiscriminant { name, param_kind: is_type } => self
                .dcx()
                .create_err(errs::ParamInEnumDiscriminant { span, name, param_kind: is_type }),
            ResolutionError::ForwardDeclaredSelf(reason) => match reason {
                ForwardGenericParamBanReason::Default => {
                    self.dcx().create_err(errs::SelfInGenericParamDefault { span })
                }
                ForwardGenericParamBanReason::ConstParamTy => {
                    self.dcx().create_err(errs::SelfInConstGenericTy { span })
                }
            },
            ResolutionError::UnreachableLabel { name, definition_span, suggestion } => {
                let ((sub_suggestion_label, sub_suggestion), sub_unreachable_label) =
                    match suggestion {
                        // A reachable label with a similar name exists.
                        Some((ident, true)) => (
                            (
                                Some(errs::UnreachableLabelSubLabel { ident_span: ident.span }),
                                Some(errs::UnreachableLabelSubSuggestion {
                                    span,
                                    // intentionally taking 'ident.name' instead of 'ident' itself, as this
                                    // could be used in suggestion context
                                    ident_name: ident.name,
                                }),
                            ),
                            None,
                        ),
                        // An unreachable label with a similar name exists.
                        Some((ident, false)) => (
                            (None, None),
                            Some(errs::UnreachableLabelSubLabelUnreachable {
                                ident_span: ident.span,
                            }),
                        ),
                        // No similarly-named labels exist.
                        None => ((None, None), None),
                    };
                self.dcx().create_err(errs::UnreachableLabel {
                    span,
                    name,
                    definition_span,
                    sub_suggestion,
                    sub_suggestion_label,
                    sub_unreachable_label,
                })
            }
            ResolutionError::TraitImplMismatch {
                name,
                kind,
                code,
                trait_item_span,
                trait_path,
            } => self
                .dcx()
                .create_err(errors::TraitImplMismatch {
                    span,
                    name,
                    kind,
                    trait_path,
                    trait_item_span,
                })
                .with_code(code),
            ResolutionError::TraitImplDuplicate { name, trait_item_span, old_span } => self
                .dcx()
                .create_err(errs::TraitImplDuplicate { span, name, trait_item_span, old_span }),
            ResolutionError::InvalidAsmSym => self.dcx().create_err(errs::InvalidAsmSym { span }),
            ResolutionError::LowercaseSelf => self.dcx().create_err(errs::LowercaseSelf { span }),
            ResolutionError::BindingInNeverPattern => {
                self.dcx().create_err(errs::BindingInNeverPattern { span })
            }
        }
    }

    pub(crate) fn report_vis_error(
        &mut self,
        vis_resolution_error: VisResolutionError,
    ) -> ErrorGuaranteed {
        match vis_resolution_error {
            VisResolutionError::Relative2018(span, path) => {
                self.dcx().create_err(errs::Relative2018 {
                    span,
                    path_span: path.span,
                    // intentionally converting to String, as the text would also be used as
                    // in suggestion context
                    path_str: pprust::path_to_string(&path),
                })
            }
            VisResolutionError::AncestorOnly(span) => {
                self.dcx().create_err(errs::AncestorOnly(span))
            }
            VisResolutionError::FailedToResolve(span, segment, label, suggestion, message) => self
                .into_struct_error(
                    span,
                    ResolutionError::FailedToResolve {
                        segment,
                        label,
                        suggestion,
                        module: None,
                        message,
                    },
                ),
            VisResolutionError::ExpectedFound(span, path_str, res) => {
                self.dcx().create_err(errs::ExpectedModuleFound { span, res, path_str })
            }
            VisResolutionError::Indeterminate(span) => {
                self.dcx().create_err(errs::Indeterminate(span))
            }
            VisResolutionError::ModuleOnly(span) => self.dcx().create_err(errs::ModuleOnly(span)),
        }
        .emit()
    }

    fn def_path_str(&self, mut def_id: DefId) -> String {
        // We can't use `def_path_str` in resolve.
        let mut path = vec![def_id];
        while let Some(parent) = self.tcx.opt_parent(def_id) {
            def_id = parent;
            path.push(def_id);
            if def_id.is_top_level_module() {
                break;
            }
        }
        // We will only suggest importing directly if it is accessible through that path.
        path.into_iter()
            .rev()
            .map(|def_id| {
                self.tcx
                    .opt_item_name(def_id)
                    .map(|name| {
                        match (
                            def_id.is_top_level_module(),
                            def_id.is_local(),
                            self.tcx.sess.edition(),
                        ) {
                            (true, true, Edition::Edition2015) => String::new(),
                            (true, true, _) => kw::Crate.to_string(),
                            (true, false, _) | (false, _, _) => name.to_string(),
                        }
                    })
                    .unwrap_or_else(|| "_".to_string())
            })
            .collect::<Vec<String>>()
            .join("::")
    }

    pub(crate) fn add_scope_set_candidates(
        &mut self,
        suggestions: &mut Vec<TypoSuggestion>,
        scope_set: ScopeSet<'ra>,
        ps: &ParentScope<'ra>,
        sp: Span,
        filter_fn: &impl Fn(Res) -> bool,
    ) {
        let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt());
        self.cm().visit_scopes(scope_set, ps, ctxt, sp, None, |this, scope, use_prelude, _| {
            match scope {
                Scope::DeriveHelpers(expn_id) => {
                    let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
                    if filter_fn(res) {
                        suggestions.extend(
                            this.helper_attrs.get(&expn_id).into_iter().flatten().map(
                                |&(ident, orig_ident_span, _)| {
                                    TypoSuggestion::new(ident.name, orig_ident_span, res)
                                },
                            ),
                        );
                    }
                }
                Scope::DeriveHelpersCompat => {
                    // Never recommend deprecated helper attributes.
                }
                Scope::MacroRules(macro_rules_scope) => {
                    if let MacroRulesScope::Def(macro_rules_def) = macro_rules_scope.get() {
                        let res = macro_rules_def.decl.res();
                        if filter_fn(res) {
                            suggestions.push(TypoSuggestion::new(
                                macro_rules_def.ident.name,
                                macro_rules_def.orig_ident_span,
                                res,
                            ))
                        }
                    }
                }
                Scope::ModuleNonGlobs(module, _) => {
                    this.add_module_candidates(module, suggestions, filter_fn, None);
                }
                Scope::ModuleGlobs(..) => {
                    // Already handled in `ModuleNonGlobs`.
                }
                Scope::MacroUsePrelude => {
                    suggestions.extend(this.macro_use_prelude.iter().filter_map(
                        |(name, binding)| {
                            let res = binding.res();
                            filter_fn(res).then_some(TypoSuggestion::typo_from_name(*name, res))
                        },
                    ));
                }
                Scope::BuiltinAttrs => {
                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(sym::dummy));
                    if filter_fn(res) {
                        suggestions.extend(
                            BUILTIN_ATTRIBUTES
                                .iter()
                                // These trace attributes are compiler-generated and have
                                // deliberately invalid names.
                                .filter(|attr| {
                                    !matches!(attr.name, sym::cfg_trace | sym::cfg_attr_trace)
                                })
                                .map(|attr| TypoSuggestion::typo_from_name(attr.name, res)),
                        );
                    }
                }
                Scope::ExternPreludeItems => {
                    // Add idents from both item and flag scopes.
                    suggestions.extend(this.extern_prelude.iter().filter_map(|(ident, entry)| {
                        let res = Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id());
                        filter_fn(res).then_some(TypoSuggestion::new(ident.name, entry.span(), res))
                    }));
                }
                Scope::ExternPreludeFlags => {}
                Scope::ToolPrelude => {
                    let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
                    suggestions.extend(
                        this.registered_tools
                            .iter()
                            .map(|ident| TypoSuggestion::new(ident.name, ident.span, res)),
                    );
                }
                Scope::StdLibPrelude => {
                    if let Some(prelude) = this.prelude {
                        let mut tmp_suggestions = Vec::new();
                        this.add_module_candidates(prelude, &mut tmp_suggestions, filter_fn, None);
                        suggestions.extend(
                            tmp_suggestions
                                .into_iter()
                                .filter(|s| use_prelude.into() || this.is_builtin_macro(s.res)),
                        );
                    }
                }
                Scope::BuiltinTypes => {
                    suggestions.extend(PrimTy::ALL.iter().filter_map(|prim_ty| {
                        let res = Res::PrimTy(*prim_ty);
                        filter_fn(res)
                            .then_some(TypoSuggestion::typo_from_name(prim_ty.name(), res))
                    }))
                }
            }

            ControlFlow::<()>::Continue(())
        });
    }

    /// Lookup typo candidate in scope for a macro or import.
    fn early_lookup_typo_candidate(
        &mut self,
        scope_set: ScopeSet<'ra>,
        parent_scope: &ParentScope<'ra>,
        ident: Ident,
        filter_fn: &impl Fn(Res) -> bool,
    ) -> Option<TypoSuggestion> {
        let mut suggestions = Vec::new();
        self.add_scope_set_candidates(
            &mut suggestions,
            scope_set,
            parent_scope,
            ident.span,
            filter_fn,
        );

        // Make sure error reporting is deterministic.
        suggestions.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));

        match find_best_match_for_name(
            &suggestions.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
            ident.name,
            None,
        ) {
            Some(found) if found != ident.name => {
                suggestions.into_iter().find(|suggestion| suggestion.candidate == found)
            }
            _ => None,
        }
    }

    fn lookup_import_candidates_from_module<FilterFn>(
        &self,
        lookup_ident: Ident,
        namespace: Namespace,
        parent_scope: &ParentScope<'ra>,
        start_module: Module<'ra>,
        crate_path: ThinVec<ast::PathSegment>,
        filter_fn: FilterFn,
    ) -> Vec<ImportSuggestion>
    where
        FilterFn: Fn(Res) -> bool,
    {
        let mut candidates = Vec::new();
        let mut seen_modules = FxHashSet::default();
        let start_did = start_module.def_id();
        let mut worklist = vec![(
            start_module,
            ThinVec::<ast::PathSegment>::new(),
            true,
            start_did.is_local() || !self.tcx.is_doc_hidden(start_did),
            true,
        )];
        let mut worklist_via_import = vec![];

        while let Some((in_module, path_segments, accessible, doc_visible, is_stable)) =
            match worklist.pop() {
                None => worklist_via_import.pop(),
                Some(x) => Some(x),
            }
        {
            let in_module_is_extern = !in_module.def_id().is_local();
            in_module.for_each_child(self, |this, ident, orig_ident_span, ns, name_binding| {
                // Avoid non-importable candidates.
                if name_binding.is_assoc_item()
                    && !this.tcx.features().import_trait_associated_functions()
                {
                    return;
                }

                if ident.name == kw::Underscore {
                    return;
                }

                let child_accessible =
                    accessible && this.is_accessible_from(name_binding.vis(), parent_scope.module);

                // do not venture inside inaccessible items of other crates
                if in_module_is_extern && !child_accessible {
                    return;
                }

                let via_import = name_binding.is_import() && !name_binding.is_extern_crate();

                // There is an assumption elsewhere that paths of variants are in the enum's
                // declaration and not imported. With this assumption, the variant component is
                // chopped and the rest of the path is assumed to be the enum's own path. For
                // errors where a variant is used as the type instead of the enum, this causes
                // funny looking invalid suggestions, i.e `foo` instead of `foo::MyEnum`.
                if via_import && name_binding.is_possibly_imported_variant() {
                    return;
                }

                // #90113: Do not count an inaccessible reexported item as a candidate.
                if let DeclKind::Import { source_decl, .. } = name_binding.kind
                    && this.is_accessible_from(source_decl.vis(), parent_scope.module)
                    && !this.is_accessible_from(name_binding.vis(), parent_scope.module)
                {
                    return;
                }

                let res = name_binding.res();
                let did = match res {
                    Res::Def(DefKind::Ctor(..), did) => this.tcx.opt_parent(did),
                    _ => res.opt_def_id(),
                };
                let child_doc_visible = doc_visible
                    && did.is_none_or(|did| did.is_local() || !this.tcx.is_doc_hidden(did));

                // collect results based on the filter function
                // avoid suggesting anything from the same module in which we are resolving
                // avoid suggesting anything with a hygienic name
                if ident.name == lookup_ident.name
                    && ns == namespace
                    && in_module != parent_scope.module
                    && ident.ctxt.is_root()
                    && filter_fn(res)
                {
                    // create the path
                    let mut segms = if lookup_ident.span.at_least_rust_2018() {
                        // crate-local absolute paths start with `crate::` in edition 2018
                        // FIXME: may also be stabilized for Rust 2015 (Issues #45477, #44660)
                        crate_path.clone()
                    } else {
                        ThinVec::new()
                    };
                    segms.append(&mut path_segments.clone());

                    segms.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));
                    let path = Path { span: name_binding.span, segments: segms, tokens: None };

                    if child_accessible
                        // Remove invisible match if exists
                        && let Some(idx) = candidates
                            .iter()
                            .position(|v: &ImportSuggestion| v.did == did && !v.accessible)
                    {
                        candidates.remove(idx);
                    }

                    let is_stable = if is_stable
                        && let Some(did) = did
                        && this.is_stable(did, path.span)
                    {
                        true
                    } else {
                        false
                    };

                    // Rreplace unstable suggestions if we meet a new stable one,
                    // and do nothing if any other situation. For example, if we
                    // meet `std::ops::Range` after `std::range::legacy::Range`,
                    // we will remove the latter and then insert the former.
                    if is_stable
                        && let Some(idx) = candidates
                            .iter()
                            .position(|v: &ImportSuggestion| v.did == did && !v.is_stable)
                    {
                        candidates.remove(idx);
                    }

                    if candidates.iter().all(|v: &ImportSuggestion| v.did != did) {
                        // See if we're recommending TryFrom, TryInto, or FromIterator and add
                        // a note about editions
                        let note = if let Some(did) = did {
                            let requires_note = !did.is_local()
                                && find_attr!(
                                    this.tcx,
                                    did,
                                    RustcDiagnosticItem(
                                        sym::TryInto | sym::TryFrom | sym::FromIterator
                                    )
                                );
                            requires_note.then(|| {
                                format!(
                                    "'{}' is included in the prelude starting in Edition 2021",
                                    path_names_to_string(&path)
                                )
                            })
                        } else {
                            None
                        };

                        candidates.push(ImportSuggestion {
                            did,
                            descr: res.descr(),
                            path,
                            accessible: child_accessible,
                            doc_visible: child_doc_visible,
                            note,
                            via_import,
                            is_stable,
                        });
                    }
                }

                // collect submodules to explore
                if let Some(def_id) = name_binding.res().module_like_def_id() {
                    // form the path
                    let mut path_segments = path_segments.clone();
                    path_segments.push(ast::PathSegment::from_ident(ident.orig(orig_ident_span)));

                    let alias_import = if let DeclKind::Import { import, .. } = name_binding.kind
                        && let ImportKind::ExternCrate { source: Some(_), .. } = import.kind
                        && import.parent_scope.expansion == parent_scope.expansion
                    {
                        true
                    } else {
                        false
                    };

                    let is_extern_crate_that_also_appears_in_prelude =
                        name_binding.is_extern_crate() && lookup_ident.span.at_least_rust_2018();

                    if !is_extern_crate_that_also_appears_in_prelude || alias_import {
                        // add the module to the lookup
                        if seen_modules.insert(def_id) {
                            if via_import { &mut worklist_via_import } else { &mut worklist }.push(
                                (
                                    this.expect_module(def_id),
                                    path_segments,
                                    child_accessible,
                                    child_doc_visible,
                                    is_stable && this.is_stable(def_id, name_binding.span),
                                ),
                            );
                        }
                    }
                }
            })
        }

        candidates
    }

    fn is_stable(&self, did: DefId, span: Span) -> bool {
        if did.is_local() {
            return true;
        }

        match self.tcx.lookup_stability(did) {
            Some(Stability {
                level: StabilityLevel::Unstable { implied_by, .. }, feature, ..
            }) => {
                if span.allows_unstable(feature) {
                    true
                } else if self.tcx.features().enabled(feature) {
                    true
                } else if let Some(implied_by) = implied_by
                    && self.tcx.features().enabled(implied_by)
                {
                    true
                } else {
                    false
                }
            }
            Some(_) => true,
            None => false,
        }
    }

    /// When name resolution fails, this method can be used to look up candidate
    /// entities with the expected name. It allows filtering them using the
    /// supplied predicate (which should be used to only accept the types of
    /// definitions expected, e.g., traits). The lookup spans across all crates.
    ///
    /// N.B., the method does not look into imports, but this is not a problem,
    /// since we report the definitions (thus, the de-aliased imports).
    pub(crate) fn lookup_import_candidates<FilterFn>(
        &mut self,
        lookup_ident: Ident,
        namespace: Namespace,
        parent_scope: &ParentScope<'ra>,
        filter_fn: FilterFn,
    ) -> Vec<ImportSuggestion>
    where
        FilterFn: Fn(Res) -> bool,
    {
        let crate_path = thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(kw::Crate))];
        let mut suggestions = self.lookup_import_candidates_from_module(
            lookup_ident,
            namespace,
            parent_scope,
            self.graph_root.to_module(),
            crate_path,
            &filter_fn,
        );

        if lookup_ident.span.at_least_rust_2018() {
            for (ident, entry) in &self.extern_prelude {
                if entry.span().from_expansion() {
                    // Idents are adjusted to the root context before being
                    // resolved in the extern prelude, so reporting this to the
                    // user is no help. This skips the injected
                    // `extern crate std` in the 2018 edition, which would
                    // otherwise cause duplicate suggestions.
                    continue;
                }
                let Some(crate_id) =
                    self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
                else {
                    continue;
                };

                let crate_def_id = crate_id.as_def_id();
                let crate_root = self.expect_module(crate_def_id);

                // Check if there's already an item in scope with the same name as the crate.
                // If so, we have to disambiguate the potential import suggestions by making
                // the paths *global* (i.e., by prefixing them with `::`).
                let needs_disambiguation =
                    self.resolutions(parent_scope.module).borrow().iter().any(
                        |(key, name_resolution)| {
                            if key.ns == TypeNS
                                && key.ident == *ident
                                && let Some(decl) = name_resolution.borrow().best_decl()
                            {
                                match decl.res() {
                                    // No disambiguation needed if the identically named item we
                                    // found in scope actually refers to the crate in question.
                                    Res::Def(_, def_id) => def_id != crate_def_id,
                                    Res::PrimTy(_) => true,
                                    _ => false,
                                }
                            } else {
                                false
                            }
                        },
                    );
                let mut crate_path = ThinVec::new();
                if needs_disambiguation {
                    crate_path.push(ast::PathSegment::path_root(rustc_span::DUMMY_SP));
                }
                crate_path.push(ast::PathSegment::from_ident(ident.orig(entry.span())));

                suggestions.extend(self.lookup_import_candidates_from_module(
                    lookup_ident,
                    namespace,
                    parent_scope,
                    crate_root,
                    crate_path,
                    &filter_fn,
                ));
            }
        }

        suggestions.retain(|suggestion| suggestion.is_stable || self.tcx.sess.is_nightly_build());
        suggestions
    }

    pub(crate) fn unresolved_macro_suggestions(
        &mut self,
        err: &mut Diag<'_>,
        macro_kind: MacroKind,
        parent_scope: &ParentScope<'ra>,
        ident: Ident,
        krate: &Crate,
        sugg_span: Option<Span>,
    ) {
        // Bring all unused `derive` macros into `macro_map` so we ensure they can be used for
        // suggestions.
        self.register_macros_for_all_crates();

        let is_expected =
            &|res: Res| res.macro_kinds().is_some_and(|k| k.contains(macro_kind.into()));
        let suggestion = self.early_lookup_typo_candidate(
            ScopeSet::Macro(macro_kind),
            parent_scope,
            ident,
            is_expected,
        );
        if !self.add_typo_suggestion(err, suggestion, ident.span) {
            self.detect_derive_attribute(err, ident, parent_scope, sugg_span);
        }

        let import_suggestions =
            self.lookup_import_candidates(ident, Namespace::MacroNS, parent_scope, is_expected);
        let (span, found_use) = match parent_scope.module.nearest_parent_mod_node_id() {
            DUMMY_NODE_ID => (None, FoundUse::No),
            node_id => UsePlacementFinder::check(krate, node_id),
        };
        show_candidates(
            self.tcx,
            err,
            span,
            &import_suggestions,
            Instead::No,
            found_use,
            DiagMode::Normal,
            vec![],
            "",
        );

        if macro_kind == MacroKind::Bang && ident.name == sym::macro_rules {
            let label_span = ident.span.shrink_to_hi();
            let mut spans = MultiSpan::from_span(label_span);
            spans.push_span_label(label_span, "put a macro name here");
            err.subdiagnostic(MaybeMissingMacroRulesName { spans });
            return;
        }

        if macro_kind == MacroKind::Derive && (ident.name == sym::Send || ident.name == sym::Sync) {
            err.subdiagnostic(ExplicitUnsafeTraits { span: ident.span, ident });
            return;
        }

        let unused_macro = self.unused_macros.iter().find_map(|(def_id, (_, unused_ident))| {
            if unused_ident.name == ident.name { Some((def_id, unused_ident)) } else { None }
        });

        if let Some((def_id, unused_ident)) = unused_macro {
            let scope = self.local_macro_def_scopes[&def_id];
            let parent_nearest = parent_scope.module.nearest_parent_mod();
            let unused_macro_kinds = self.local_macro_map[def_id].macro_kinds();
            if !unused_macro_kinds.contains(macro_kind.into()) {
                match macro_kind {
                    MacroKind::Bang => {
                        err.subdiagnostic(MacroRulesNot::Func { span: unused_ident.span, ident });
                    }
                    MacroKind::Attr => {
                        err.subdiagnostic(MacroRulesNot::Attr { span: unused_ident.span, ident });
                    }
                    MacroKind::Derive => {
                        err.subdiagnostic(MacroRulesNot::Derive { span: unused_ident.span, ident });
                    }
                }
                return;
            }
            if Some(parent_nearest) == scope.opt_def_id() {
                err.subdiagnostic(MacroDefinedLater { span: unused_ident.span });
                err.subdiagnostic(MacroSuggMovePosition { span: ident.span, ident });
                return;
            }
        }

        if ident.name == kw::Default
            && let ModuleKind::Def(DefKind::Enum, def_id, _, _) = parent_scope.module.kind
        {
            let span = self.def_span(def_id);
            let source_map = self.tcx.sess.source_map();
            let head_span = source_map.guess_head_span(span);
            err.subdiagnostic(ConsiderAddingADerive {
                span: head_span.shrink_to_lo(),
                suggestion: "#[derive(Default)]\n".to_string(),
            });
        }
        for ns in [Namespace::MacroNS, Namespace::TypeNS, Namespace::ValueNS] {
            let Ok(binding) = self.cm().resolve_ident_in_scope_set(
                ident,
                ScopeSet::All(ns),
                parent_scope,
                None,
                None,
                None,
            ) else {
                continue;
            };

            let desc = match binding.res() {
                Res::Def(DefKind::Macro(MacroKinds::BANG), _) => {
                    "a function-like macro".to_string()
                }
                Res::Def(DefKind::Macro(MacroKinds::ATTR), _) | Res::NonMacroAttr(..) => {
                    format!("an attribute: `#[{ident}]`")
                }
                Res::Def(DefKind::Macro(MacroKinds::DERIVE), _) => {
                    format!("a derive macro: `#[derive({ident})]`")
                }
                Res::Def(DefKind::Macro(kinds), _) => {
                    format!("{} {}", kinds.article(), kinds.descr())
                }
                Res::ToolMod | Res::OpenMod(..) => {
                    // Don't confuse the user with tool modules or open modules.
                    continue;
                }
                Res::Def(DefKind::Trait, _) if macro_kind == MacroKind::Derive => {
                    "only a trait, without a derive macro".to_string()
                }
                res => format!(
                    "{} {}, not {} {}",
                    res.article(),
                    res.descr(),
                    macro_kind.article(),
                    macro_kind.descr_expected(),
                ),
            };
            if let crate::DeclKind::Import { import, .. } = binding.kind
                && !import.span.is_dummy()
            {
                let note = errors::IdentImporterHereButItIsDesc {
                    span: import.span,
                    imported_ident: ident,
                    imported_ident_desc: &desc,
                };
                err.subdiagnostic(note);
                // Silence the 'unused import' warning we might get,
                // since this diagnostic already covers that import.
                self.record_use(ident, binding, Used::Other);
                return;
            }
            let note = errors::IdentInScopeButItIsDesc {
                imported_ident: ident,
                imported_ident_desc: &desc,
            };
            err.subdiagnostic(note);
            return;
        }

        if self.macro_names.contains(&IdentKey::new(ident)) {
            err.subdiagnostic(AddedMacroUse);
            return;
        }
    }

    /// Given an attribute macro that failed to be resolved, look for `derive` macros that could
    /// provide it, either as-is or with small typos.
    fn detect_derive_attribute(
        &self,
        err: &mut Diag<'_>,
        ident: Ident,
        parent_scope: &ParentScope<'ra>,
        sugg_span: Option<Span>,
    ) {
        // Find all of the `derive`s in scope and collect their corresponding declared
        // attributes.
        // FIXME: this only works if the crate that owns the macro that has the helper_attr
        // has already been imported.
        let mut derives = vec![];
        let mut all_attrs: UnordMap<Symbol, Vec<_>> = UnordMap::default();
        // We're collecting these in a hashmap, and handle ordering the output further down.
        #[allow(rustc::potential_query_instability)]
        for (def_id, ext) in self
            .local_macro_map
            .iter()
            .map(|(local_id, ext)| (local_id.to_def_id(), ext))
            .chain(self.extern_macro_map.borrow().iter().map(|(id, d)| (*id, d)))
        {
            for helper_attr in &ext.helper_attrs {
                let item_name = self.tcx.item_name(def_id);
                all_attrs.entry(*helper_attr).or_default().push(item_name);
                if helper_attr == &ident.name {
                    derives.push(item_name);
                }
            }
        }
        let kind = MacroKind::Derive.descr();
        if !derives.is_empty() {
            // We found an exact match for the missing attribute in a `derive` macro. Suggest it.
            let mut derives: Vec<String> = derives.into_iter().map(|d| d.to_string()).collect();
            derives.sort();
            derives.dedup();
            let msg = match &derives[..] {
                [derive] => format!(" `{derive}`"),
                [start @ .., last] => format!(
                    "s {} and `{last}`",
                    start.iter().map(|d| format!("`{d}`")).collect::<Vec<_>>().join(", ")
                ),
                [] => unreachable!("we checked for this to be non-empty 10 lines above!?"),
            };
            let msg = format!(
                "`{}` is an attribute that can be used by the {kind}{msg}, you might be \
                     missing a `derive` attribute",
                ident.name,
            );
            let sugg_span =
                if let ModuleKind::Def(DefKind::Enum, id, _, _) = parent_scope.module.kind {
                    let span = self.def_span(id);
                    if span.from_expansion() {
                        None
                    } else {
                        // For enum variants sugg_span is empty but we can get the enum's Span.
                        Some(span.shrink_to_lo())
                    }
                } else {
                    // For items this `Span` will be populated, everything else it'll be None.
                    sugg_span
                };
            match sugg_span {
                Some(span) => {
                    err.span_suggestion_verbose(
                        span,
                        msg,
                        format!("#[derive({})]\n", derives.join(", ")),
                        Applicability::MaybeIncorrect,
                    );
                }
                None => {
                    err.note(msg);
                }
            }
        } else {
            // We didn't find an exact match. Look for close matches. If any, suggest fixing typo.
            let all_attr_names = all_attrs.keys().map(|s| *s).into_sorted_stable_ord();
            if let Some(best_match) = find_best_match_for_name(&all_attr_names, ident.name, None)
                && let Some(macros) = all_attrs.get(&best_match)
            {
                let mut macros: Vec<String> = macros.into_iter().map(|d| d.to_string()).collect();
                macros.sort();
                macros.dedup();
                let msg = match &macros[..] {
                    [] => return,
                    [name] => format!(" `{name}` accepts"),
                    [start @ .., end] => format!(
                        "s {} and `{end}` accept",
                        start.iter().map(|m| format!("`{m}`")).collect::<Vec<_>>().join(", "),
                    ),
                };
                let msg = format!("the {kind}{msg} the similarly named `{best_match}` attribute");
                err.span_suggestion_verbose(
                    ident.span,
                    msg,
                    best_match,
                    Applicability::MaybeIncorrect,
                );
            }
        }
    }

    pub(crate) fn add_typo_suggestion(
        &self,
        err: &mut Diag<'_>,
        suggestion: Option<TypoSuggestion>,
        span: Span,
    ) -> bool {
        let suggestion = match suggestion {
            None => return false,
            // We shouldn't suggest underscore.
            Some(suggestion) if suggestion.candidate == kw::Underscore => return false,
            Some(suggestion) => suggestion,
        };

        let mut did_label_def_span = false;

        if let Some(def_span) = suggestion.res.opt_def_id().map(|def_id| self.def_span(def_id)) {
            if span.overlaps(def_span) {
                // Don't suggest typo suggestion for itself like in the following:
                // error[E0423]: expected function, tuple struct or tuple variant, found struct `X`
                //   --> $DIR/unicode-string-literal-syntax-error-64792.rs:4:14
                //    |
                // LL | struct X {}
                //    | ----------- `X` defined here
                // LL |
                // LL | const Y: X = X("ö");
                //    | -------------^^^^^^- similarly named constant `Y` defined here
                //    |
                // help: use struct literal syntax instead
                //    |
                // LL | const Y: X = X {};
                //    |              ^^^^
                // help: a constant with a similar name exists
                //    |
                // LL | const Y: X = Y("ö");
                //    |              ^
                return false;
            }
            let span = self.tcx.sess.source_map().guess_head_span(def_span);
            let candidate_descr = suggestion.res.descr();
            let candidate = suggestion.candidate;
            let label = match suggestion.target {
                SuggestionTarget::SimilarlyNamed => {
                    errors::DefinedHere::SimilarlyNamed { span, candidate_descr, candidate }
                }
                SuggestionTarget::SingleItem => {
                    errors::DefinedHere::SingleItem { span, candidate_descr, candidate }
                }
            };
            did_label_def_span = true;
            err.subdiagnostic(label);
        }

        let (span, msg, sugg) = if let SuggestionTarget::SimilarlyNamed = suggestion.target
            && let Ok(snippet) = self.tcx.sess.source_map().span_to_snippet(span)
            && let Some(span) = suggestion.span
            && let Some(candidate) = suggestion.candidate.as_str().strip_prefix('_')
            && snippet == candidate
        {
            let candidate = suggestion.candidate;
            // When the suggested binding change would be from `x` to `_x`, suggest changing the
            // original binding definition instead. (#60164)
            let msg = format!(
                "the leading underscore in `{candidate}` marks it as unused, consider renaming it to `{snippet}`"
            );
            if !did_label_def_span {
                err.span_label(span, format!("`{candidate}` defined here"));
            }
            (span, msg, snippet)
        } else {
            let msg = match suggestion.target {
                SuggestionTarget::SimilarlyNamed => format!(
                    "{} {} with a similar name exists",
                    suggestion.res.article(),
                    suggestion.res.descr()
                ),
                SuggestionTarget::SingleItem => {
                    format!("maybe you meant this {}", suggestion.res.descr())
                }
            };
            (span, msg, suggestion.candidate.to_ident_string())
        };
        err.span_suggestion_verbose(span, msg, sugg, Applicability::MaybeIncorrect);
        true
    }

    fn decl_description(&self, b: Decl<'_>, ident: Ident, scope: Scope<'_>) -> String {
        let res = b.res();
        if b.span.is_dummy() || !self.tcx.sess.source_map().is_span_accessible(b.span) {
            let (built_in, from) = match scope {
                Scope::StdLibPrelude | Scope::MacroUsePrelude => ("", " from prelude"),
                Scope::ExternPreludeFlags
                    if self.tcx.sess.opts.externs.get(ident.as_str()).is_some()
                        || matches!(res, Res::OpenMod(..)) =>
                {
                    ("", " passed with `--extern`")
                }
                _ => {
                    if matches!(res, Res::NonMacroAttr(..) | Res::PrimTy(..) | Res::ToolMod) {
                        // These already contain the "built-in" prefix or look bad with it.
                        ("", "")
                    } else {
                        (" built-in", "")
                    }
                }
            };

            let a = if built_in.is_empty() { res.article() } else { "a" };
            format!("{a}{built_in} {thing}{from}", thing = res.descr())
        } else {
            let introduced = if b.is_import_user_facing() { "imported" } else { "defined" };
            format!("the {thing} {introduced} here", thing = res.descr())
        }
    }

    fn ambiguity_diagnostic(&self, ambiguity_error: &AmbiguityError<'ra>) -> errors::Ambiguity {
        let AmbiguityError { kind, ambig_vis, ident, b1, b2, scope1, scope2, .. } =
            *ambiguity_error;
        let extern_prelude_ambiguity = || {
            // Note: b1 may come from a module scope, as an extern crate item in module.
            matches!(scope2, Scope::ExternPreludeFlags)
                && self
                    .extern_prelude
                    .get(&IdentKey::new(ident))
                    .is_some_and(|entry| entry.item_decl.map(|(b, ..)| b) == Some(b1))
        };
        let (b1, b2, scope1, scope2, swapped) = if b2.span.is_dummy() && !b1.span.is_dummy() {
            // We have to print the span-less alternative first, otherwise formatting looks bad.
            (b2, b1, scope2, scope1, true)
        } else {
            (b1, b2, scope1, scope2, false)
        };

        let could_refer_to = |b: Decl<'_>, scope: Scope<'ra>, also: &str| {
            let what = self.decl_description(b, ident, scope);
            let note_msg = format!("`{ident}` could{also} refer to {what}");

            let thing = b.res().descr();
            let mut help_msgs = Vec::new();
            if b.is_glob_import()
                && (kind == AmbiguityKind::GlobVsGlob
                    || kind == AmbiguityKind::GlobVsExpanded
                    || kind == AmbiguityKind::GlobVsOuter && swapped != also.is_empty())
            {
                help_msgs.push(format!(
                    "consider adding an explicit import of `{ident}` to disambiguate"
                ))
            }
            if b.is_extern_crate() && ident.span.at_least_rust_2018() && !extern_prelude_ambiguity()
            {
                help_msgs.push(format!("use `::{ident}` to refer to this {thing} unambiguously"))
            }

            if kind != AmbiguityKind::GlobVsGlob {
                if let Scope::ModuleNonGlobs(module, _) | Scope::ModuleGlobs(module, _) = scope {
                    if module == self.graph_root.to_module() {
                        help_msgs.push(format!(
                            "use `crate::{ident}` to refer to this {thing} unambiguously"
                        ));
                    } else if module.is_normal() {
                        help_msgs.push(format!(
                            "use `self::{ident}` to refer to this {thing} unambiguously"
                        ));
                    }
                }
            }

            (
                Spanned { node: note_msg, span: b.span },
                help_msgs
                    .iter()
                    .enumerate()
                    .map(|(i, help_msg)| {
                        let or = if i == 0 { "" } else { "or " };
                        format!("{or}{help_msg}")
                    })
                    .collect::<Vec<_>>(),
            )
        };
        let (b1_note, b1_help_msgs) = could_refer_to(b1, scope1, "");
        let (b2_note, b2_help_msgs) = could_refer_to(b2, scope2, " also");
        let help = if kind == AmbiguityKind::GlobVsGlob
            && b1
                .parent_module
                .and_then(|m| m.opt_def_id())
                .map(|d| !d.is_local())
                .unwrap_or_default()
        {
            Some(&[
                "consider updating this dependency to resolve this error",
                "if updating the dependency does not resolve the problem report the problem to the author of the relevant crate",
            ] as &[_])
        } else {
            None
        };

        let ambig_vis = ambig_vis.map(|(vis1, vis2)| {
            format!(
                "{} or {}",
                vis1.to_string(CRATE_DEF_ID, self.tcx),
                vis2.to_string(CRATE_DEF_ID, self.tcx)
            )
        });

        errors::Ambiguity {
            ident,
            help,
            ambig_vis,
            kind: kind.descr(),
            b1_note,
            b1_help_msgs,
            b2_note,
            b2_help_msgs,
            is_error: false,
        }
    }

    /// If the binding refers to a tuple struct constructor with fields,
    /// returns the span of its fields.
    fn ctor_fields_span(&self, decl: Decl<'_>) -> Option<Span> {
        let DeclKind::Def(Res::Def(DefKind::Ctor(CtorOf::Struct, CtorKind::Fn), ctor_def_id)) =
            decl.kind
        else {
            return None;
        };

        let def_id = self.tcx.parent(ctor_def_id);
        self.field_idents(def_id)?.iter().map(|&f| f.span).reduce(Span::to) // None for `struct Foo()`
    }

    /// Returns the path segments (as symbols) of a module, including `kw::Crate` at the start.
    /// For example, for `crate::foo::bar`, returns `[Crate, foo, bar]`.
    /// Returns `None` for block modules that don't have a `DefId`.
    fn module_path_names(&self, module: Module<'ra>) -> Option<Vec<Symbol>> {
        let mut path = Vec::new();
        let mut def_id = module.opt_def_id()?;
        while let Some(parent) = self.tcx.opt_parent(def_id) {
            if let Some(name) = self.tcx.opt_item_name(def_id) {
                path.push(name);
            }
            if parent.is_top_level_module() {
                break;
            }
            def_id = parent;
        }
        path.reverse();
        path.insert(0, kw::Crate);
        Some(path)
    }

    /// Shortens a candidate import path to use `super::` (up to 1 level) or `self::` (same module)
    /// relative to the current scope, if possible. Only applies to crate-local items and
    /// only when the resulting path is actually shorter than the original.
    fn shorten_candidate_path(
        &self,
        suggestion: &mut ImportSuggestion,
        current_module: Module<'ra>,
    ) {
        const MAX_SUPER_PATH_ITEMS_IN_SUGGESTION: usize = 1;

        // Only shorten local items.
        if suggestion.did.is_none_or(|did| !did.is_local()) {
            return;
        }

        // Build current module path: [Crate, foo, bar, ...].
        let Some(current_mod_path) = self.module_path_names(current_module) else {
            return;
        };

        // Normalise candidate path: filter out `PathRoot` (`::`), and if the path
        // doesn't start with `Crate`, prepend it (edition 2015 paths are relative
        // to the crate root without an explicit `crate::` prefix).
        let candidate_names = {
            let filtered_segments: Vec<_> = suggestion
                .path
                .segments
                .iter()
                .filter(|segment| segment.ident.name != kw::PathRoot)
                .collect();

            let mut candidate_names: Vec<Symbol> =
                filtered_segments.iter().map(|segment| segment.ident.name).collect();
            if candidate_names.first() != Some(&kw::Crate) {
                candidate_names.insert(0, kw::Crate);
            }
            if candidate_names.len() < 2 {
                return;
            }
            candidate_names
        };

        // The candidate's module path is everything except the last segment (the item name).
        let candidate_mod_names = &candidate_names[..candidate_names.len() - 1];

        // Find the longest common prefix between the current module and candidate module paths.
        let common_prefix_length = current_mod_path
            .iter()
            .zip(candidate_mod_names.iter())
            .take_while(|(current, candidate)| current == candidate)
            .count();

        // Non-crate-local item; keep the full absolute path.
        if common_prefix_length == 0 {
            return;
        }

        let super_count = current_mod_path.len() - common_prefix_length;

        // At the crate root, `use` paths resolve from the crate root anyway, so we can
        // drop the `crate::` prefix entirely instead of replacing it with `self::`.
        let at_crate_root = current_mod_path.len() == 1;

        let mut new_segments = if super_count == 0 && at_crate_root {
            ThinVec::new()
        } else {
            let prefix_keyword = match super_count {
                0 => kw::SelfLower,
                1..=MAX_SUPER_PATH_ITEMS_IN_SUGGESTION => kw::Super,
                _ => return, // Too many `super` levels; keep the full absolute path.
            };
            thin_vec![ast::PathSegment::from_ident(Ident::with_dummy_span(prefix_keyword),)]
        };
        for &name in &candidate_names[common_prefix_length..] {
            new_segments.push(ast::PathSegment::from_ident(Ident::with_dummy_span(name)));
        }

        // Only apply if the result is strictly shorter than the original path.
        if new_segments.len() >= suggestion.path.segments.len() {
            return;
        }

        suggestion.path = Path { span: suggestion.path.span, segments: new_segments, tokens: None };
    }

    fn report_privacy_error(&mut self, privacy_error: &PrivacyError<'ra>) {
        let PrivacyError {
            ident,
            decl,
            outermost_res,
            parent_scope,
            single_nested,
            dedup_span,
            ref source,
        } = *privacy_error;

        let res = decl.res();
        let ctor_fields_span = self.ctor_fields_span(decl);
        let plain_descr = res.descr().to_string();
        let nonimport_descr =
            if ctor_fields_span.is_some() { plain_descr + " constructor" } else { plain_descr };
        let import_descr = nonimport_descr.clone() + " import";
        let get_descr = |b: Decl<'_>| if b.is_import() { &import_descr } else { &nonimport_descr };

        // Print the primary message.
        let ident_descr = get_descr(decl);
        let mut err =
            self.dcx().create_err(errors::IsPrivate { span: ident.span, ident_descr, ident });

        self.mention_default_field_values(source, ident, &mut err);

        if let Some((this_res, outer_ident)) = outermost_res {
            let mut import_suggestions = self.lookup_import_candidates(
                outer_ident,
                this_res.ns().unwrap_or(Namespace::TypeNS),
                &parent_scope,
                &|res: Res| res == this_res,
            );
            // Shorten candidate paths using `super::` or `self::` when possible.
            for suggestion in &mut import_suggestions {
                self.shorten_candidate_path(suggestion, parent_scope.module);
            }
            let point_to_def = !show_candidates(
                self.tcx,
                &mut err,
                Some(dedup_span.until(outer_ident.span.shrink_to_hi())),
                &import_suggestions,
                Instead::Yes,
                FoundUse::Yes,
                DiagMode::Import { append: single_nested, unresolved_import: false },
                vec![],
                "",
            );
            // If we suggest importing a public re-export, don't point at the definition.
            if point_to_def && ident.span != outer_ident.span {
                let label = errors::OuterIdentIsNotPubliclyReexported {
                    span: outer_ident.span,
                    outer_ident_descr: this_res.descr(),
                    outer_ident,
                };
                err.subdiagnostic(label);
            }
        }

        let mut non_exhaustive = None;
        // If an ADT is foreign and marked as `non_exhaustive`, then that's
        // probably why we have the privacy error.
        // Otherwise, point out if the struct has any private fields.
        if let Some(def_id) = res.opt_def_id()
            && !def_id.is_local()
            && let Some(attr_span) = find_attr!(self.tcx, def_id, NonExhaustive(span) => *span)
        {
            non_exhaustive = Some(attr_span);
        } else if let Some(span) = ctor_fields_span {
            let label = errors::ConstructorPrivateIfAnyFieldPrivate { span };
            err.subdiagnostic(label);
            if let Res::Def(_, d) = res
                && let Some(fields) = self.field_visibility_spans.get(&d)
            {
                let spans = fields.iter().map(|span| *span).collect();
                let sugg =
                    errors::ConsiderMakingTheFieldPublic { spans, number_of_fields: fields.len() };
                err.subdiagnostic(sugg);
            }
        }

        let mut sugg_paths: Vec<(Vec<Ident>, bool)> = vec![];
        if let Some(mut def_id) = res.opt_def_id() {
            // We can't use `def_path_str` in resolve.
            let mut path = vec![def_id];
            while let Some(parent) = self.tcx.opt_parent(def_id) {
                def_id = parent;
                if !def_id.is_top_level_module() {
                    path.push(def_id);
                } else {
                    break;
                }
            }
            // We will only suggest importing directly if it is accessible through that path.
            let path_names: Option<Vec<Ident>> = path
                .iter()
                .rev()
                .map(|def_id| {
                    self.tcx.opt_item_name(*def_id).map(|name| {
                        Ident::with_dummy_span(if def_id.is_top_level_module() {
                            kw::Crate
                        } else {
                            name
                        })
                    })
                })
                .collect();
            if let Some(&def_id) = path.get(0)
                && let Some(path) = path_names
            {
                if let Some(def_id) = def_id.as_local() {
                    if self.effective_visibilities.is_directly_public(def_id) {
                        sugg_paths.push((path, false));
                    }
                } else if self.is_accessible_from(self.tcx.visibility(def_id), parent_scope.module)
                {
                    sugg_paths.push((path, false));
                }
            }
        }

        // Print the whole import chain to make it easier to see what happens.
        let first_binding = decl;
        let mut next_binding = Some(decl);
        let mut next_ident = ident;
        while let Some(binding) = next_binding {
            let name = next_ident;
            next_binding = match binding.kind {
                _ if res == Res::Err => None,
                DeclKind::Import { source_decl, import, .. } => match import.kind {
                    _ if source_decl.span.is_dummy() => None,
                    ImportKind::Single { source, .. } => {
                        next_ident = source;
                        Some(source_decl)
                    }
                    ImportKind::Glob { .. }
                    | ImportKind::MacroUse { .. }
                    | ImportKind::MacroExport => Some(source_decl),
                    ImportKind::ExternCrate { .. } => None,
                },
                _ => None,
            };

            match binding.kind {
                DeclKind::Import { source_decl, import, .. } => {
                    // Don't include `{{root}}` in suggestions - it's an internal symbol
                    // that should never be shown to users.
                    let path = import
                        .module_path
                        .iter()
                        .filter(|seg| seg.ident.name != kw::PathRoot)
                        .map(|seg| seg.ident.clone())
                        .chain(std::iter::once(ident))
                        .collect::<Vec<_>>();
                    let through_reexport = !matches!(source_decl.kind, DeclKind::Def(_));
                    sugg_paths.push((path, through_reexport));
                }
                DeclKind::Def(_) => {}
            }
            let first = binding == first_binding;
            let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
            let mut note_span = MultiSpan::from_span(def_span);
            if !first && binding.vis().is_public() {
                let desc = match binding.kind {
                    DeclKind::Import { .. } => "re-export",
                    _ => "directly",
                };
                note_span.push_span_label(def_span, format!("you could import this {desc}"));
            }
            // Final step in the import chain, point out if the ADT is `non_exhaustive`
            // which is probably why this privacy violation occurred.
            if next_binding.is_none()
                && let Some(span) = non_exhaustive
            {
                note_span.push_span_label(
                    span,
                    "cannot be constructed because it is `#[non_exhaustive]`",
                );
            }
            let note = errors::NoteAndRefersToTheItemDefinedHere {
                span: note_span,
                binding_descr: get_descr(binding),
                binding_name: name,
                first,
                dots: next_binding.is_some(),
            };
            err.subdiagnostic(note);
        }
        // The suggestion replaces `dedup_span` with a path reaching the failing ident.
        // That's valid only when
        // 1) the failing ident is the imported leaf, otherwise `as` renames and trailing segments
        //    get dropped, and
        // 2) the use isn't nested, otherwise `dedup_span` is one ident in `{...}`.
        //
        // See issue #156060.
        let can_replace_use =
            !single_nested && !outermost_res.is_some_and(|(_, outer)| outer.span != ident.span);
        if can_replace_use {
            // We prioritize shorter paths, non-core imports and direct imports over the
            // alternatives.
            sugg_paths.sort_by_key(|(p, reexport)| (p.len(), p[0].name == sym::core, *reexport));
            for (sugg, reexport) in sugg_paths {
                if sugg.len() <= 1 {
                    // A single path segment suggestion is wrong. This happens on circular
                    // imports. `tests/ui/imports/issue-55884-2.rs`
                    continue;
                }
                let path = join_path_idents(sugg);
                let sugg = if reexport {
                    errors::ImportIdent::ThroughReExport { span: dedup_span, ident, path }
                } else {
                    errors::ImportIdent::Directly { span: dedup_span, ident, path }
                };
                err.subdiagnostic(sugg);
                break;
            }
        }

        err.emit();
    }

    /// When a private field is being set that has a default field value, we suggest using `..` and
    /// setting the value of that field implicitly with its default.
    ///
    /// If we encounter code like
    /// ```text
    /// struct Priv;
    /// pub struct S {
    ///     pub field: Priv = Priv,
    /// }
    /// ```
    /// which is used from a place where `Priv` isn't accessible
    /// ```text
    /// let _ = S { field: m::Priv1 {} };
    /// //                    ^^^^^ private struct
    /// ```
    /// we will suggest instead using the `default_field_values` syntax instead:
    /// ```text
    /// let _ = S { .. };
    /// ```
    fn mention_default_field_values(
        &self,
        source: &Option<ast::Expr>,
        ident: Ident,
        err: &mut Diag<'_>,
    ) {
        let Some(expr) = source else { return };
        let ast::ExprKind::Struct(struct_expr) = &expr.kind else { return };
        // We don't have to handle type-relative paths because they're forbidden in ADT
        // expressions, but that would change with `#[feature(more_qualified_paths)]`.
        let Some(segment) = struct_expr.path.segments.last() else { return };
        let Some(partial_res) = self.partial_res_map.get(&segment.id) else { return };
        let Some(Res::Def(_, def_id)) = partial_res.full_res() else {
            return;
        };
        let Some(default_fields) = self.field_defaults(def_id) else { return };
        if struct_expr.fields.is_empty() {
            return;
        }
        let last_span = struct_expr.fields.iter().last().unwrap().span;
        let mut iter = struct_expr.fields.iter().peekable();
        let mut prev: Option<Span> = None;
        while let Some(field) = iter.next() {
            if field.expr.span.overlaps(ident.span) {
                err.span_label(field.ident.span, "while setting this field");
                if default_fields.contains(&field.ident.name) {
                    let sugg = if last_span == field.span {
                        vec![(field.span, "..".to_string())]
                    } else {
                        vec![
                            (
                                // Account for trailing commas and ensure we remove them.
                                match (prev, iter.peek()) {
                                    (_, Some(next)) => field.span.with_hi(next.span.lo()),
                                    (Some(prev), _) => field.span.with_lo(prev.hi()),
                                    (None, None) => field.span,
                                },
                                String::new(),
                            ),
                            (last_span.shrink_to_hi(), ", ..".to_string()),
                        ]
                    };
                    err.multipart_suggestion(
                        format!(
                            "the type `{ident}` of field `{}` is private, but you can construct \
                             the default value defined for it in `{}` using `..` in the struct \
                             initializer expression",
                            field.ident,
                            self.tcx.item_name(def_id),
                        ),
                        sugg,
                        Applicability::MachineApplicable,
                    );
                    break;
                }
            }
            prev = Some(field.span);
        }
    }

    pub(crate) fn find_similarly_named_module_or_crate(
        &self,
        ident: Symbol,
        current_module: Module<'ra>,
    ) -> Option<Symbol> {
        let mut candidates = self
            .extern_prelude
            .keys()
            .map(|ident| ident.name)
            .chain(
                self.local_module_map
                    .iter()
                    .filter(|(_, module)| {
                        let module = module.to_module();
                        current_module.is_ancestor_of(module) && current_module != module
                    })
                    .flat_map(|(_, module)| module.name()),
            )
            .chain(
                self.extern_module_map
                    .borrow()
                    .iter()
                    .filter(|(_, module)| {
                        let module = module.to_module();
                        current_module.is_ancestor_of(module) && current_module != module
                    })
                    .flat_map(|(_, module)| module.name()),
            )
            .filter(|c| !c.to_string().is_empty())
            .collect::<Vec<_>>();
        candidates.sort();
        candidates.dedup();
        find_best_match_for_name(&candidates, ident, None).filter(|sugg| *sugg != ident)
    }

    pub(crate) fn report_path_resolution_error(
        &mut self,
        path: &[Segment],
        opt_ns: Option<Namespace>, // `None` indicates a module path in import
        parent_scope: &ParentScope<'ra>,
        ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
        ignore_decl: Option<Decl<'ra>>,
        ignore_import: Option<Import<'ra>>,
        module: Option<ModuleOrUniformRoot<'ra>>,
        failed_segment_idx: usize,
        ident: Ident,
        diag_metadata: Option<&DiagMetadata<'_>>,
    ) -> (String, String, Option<Suggestion>) {
        let is_last = failed_segment_idx == path.len() - 1;
        let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
        let module_def_id = match module {
            Some(ModuleOrUniformRoot::Module(module)) => module.opt_def_id(),
            _ => None,
        };
        let scope = match &path[..failed_segment_idx] {
            [.., prev] => {
                if prev.ident.name == kw::PathRoot {
                    format!("the crate root")
                } else {
                    format!("`{}`", prev.ident)
                }
            }
            _ => format!("this scope"),
        };
        let message = format!("cannot find `{ident}` in {scope}");

        if module_def_id == Some(CRATE_DEF_ID.to_def_id()) {
            let is_mod = |res| matches!(res, Res::Def(DefKind::Mod, _));
            let mut candidates = self.lookup_import_candidates(ident, TypeNS, parent_scope, is_mod);
            candidates
                .sort_by_cached_key(|c| (c.path.segments.len(), pprust::path_to_string(&c.path)));
            if let Some(candidate) = candidates.get(0) {
                let path = {
                    // remove the possible common prefix of the path
                    let len = candidate.path.segments.len();
                    let start_index = (0..=failed_segment_idx.min(len - 1))
                        .find(|&i| path[i].ident.name != candidate.path.segments[i].ident.name)
                        .unwrap_or_default();
                    let segments =
                        (start_index..len).map(|s| candidate.path.segments[s].clone()).collect();
                    Path { segments, span: Span::default(), tokens: None }
                };
                (
                    message,
                    String::from("unresolved import"),
                    Some((
                        vec![(ident.span, pprust::path_to_string(&path))],
                        String::from("a similar path exists"),
                        Applicability::MaybeIncorrect,
                    )),
                )
            } else if ident.name == sym::core {
                (
                    message,
                    format!("you might be missing crate `{ident}`"),
                    Some((
                        vec![(ident.span, "std".to_string())],
                        "try using `std` instead of `core`".to_string(),
                        Applicability::MaybeIncorrect,
                    )),
                )
            } else if ident.name == kw::Underscore {
                (
                    "invalid crate or module name `_`".to_string(),
                    "`_` is not a valid crate or module name".to_string(),
                    None,
                )
            } else if self.tcx.sess.is_rust_2015() {
                (
                    format!("cannot find module or crate `{ident}` in {scope}"),
                    format!("use of unresolved module or unlinked crate `{ident}`"),
                    Some((
                        vec![(
                            self.current_crate_outer_attr_insert_span,
                            format!("extern crate {ident};\n"),
                        )],
                        if was_invoked_from_cargo() {
                            format!(
                                "if you wanted to use a crate named `{ident}`, use `cargo add \
                                 {ident}` to add it to your `Cargo.toml` and import it in your \
                                 code",
                            )
                        } else {
                            format!(
                                "you might be missing a crate named `{ident}`, add it to your \
                                 project and import it in your code",
                            )
                        },
                        Applicability::MaybeIncorrect,
                    )),
                )
            } else {
                (message, format!("could not find `{ident}` in the crate root"), None)
            }
        } else if failed_segment_idx > 0 {
            let parent = path[failed_segment_idx - 1].ident.name;
            let parent = match parent {
                // ::foo is mounted at the crate root for 2015, and is the extern
                // prelude for 2018+
                kw::PathRoot if self.tcx.sess.edition() > Edition::Edition2015 => {
                    "the list of imported crates".to_owned()
                }
                kw::PathRoot | kw::Crate => "the crate root".to_owned(),
                _ => format!("`{parent}`"),
            };

            let mut msg = format!("could not find `{ident}` in {parent}");
            if ns == TypeNS || ns == ValueNS {
                let ns_to_try = if ns == TypeNS { ValueNS } else { TypeNS };
                let binding = if let Some(module) = module {
                    self.cm()
                        .resolve_ident_in_module(
                            module,
                            ident,
                            ns_to_try,
                            parent_scope,
                            None,
                            ignore_decl,
                            ignore_import,
                        )
                        .ok()
                } else if let Some(ribs) = ribs
                    && let Some(TypeNS | ValueNS) = opt_ns
                {
                    assert!(ignore_import.is_none());
                    match self.resolve_ident_in_lexical_scope(
                        ident,
                        ns_to_try,
                        parent_scope,
                        None,
                        &ribs[ns_to_try],
                        ignore_decl,
                        diag_metadata,
                    ) {
                        // we found a locally-imported or available item/module
                        Some(LateDecl::Decl(binding)) => Some(binding),
                        _ => None,
                    }
                } else {
                    self.cm()
                        .resolve_ident_in_scope_set(
                            ident,
                            ScopeSet::All(ns_to_try),
                            parent_scope,
                            None,
                            ignore_decl,
                            ignore_import,
                        )
                        .ok()
                };
                if let Some(binding) = binding {
                    msg = format!(
                        "expected {}, found {} `{ident}` in {parent}",
                        ns.descr(),
                        binding.res().descr(),
                    );
                };
            }
            (message, msg, None)
        } else if ident.name == kw::SelfUpper {
            // As mentioned above, `opt_ns` being `None` indicates a module path in import.
            // We can use this to improve a confusing error for, e.g. `use Self::Variant` in an
            // impl
            if opt_ns.is_none() {
                (message, "`Self` cannot be used in imports".to_string(), None)
            } else {
                (
                    message,
                    "`Self` is only available in impls, traits, and type definitions".to_string(),
                    None,
                )
            }
        } else if ident.name.as_str().chars().next().is_some_and(|c| c.is_ascii_uppercase()) {
            // Check whether the name refers to an item in the value namespace.
            let binding = if let Some(ribs) = ribs {
                assert!(ignore_import.is_none());
                self.resolve_ident_in_lexical_scope(
                    ident,
                    ValueNS,
                    parent_scope,
                    None,
                    &ribs[ValueNS],
                    ignore_decl,
                    diag_metadata,
                )
            } else {
                None
            };
            let match_span = match binding {
                // Name matches a local variable. For example:
                // ```
                // fn f() {
                //     let Foo: &str = "";
                //     println!("{}", Foo::Bar); // Name refers to local
                //                               // variable `Foo`.
                // }
                // ```
                Some(LateDecl::RibDef(Res::Local(id))) => {
                    Some((*self.pat_span_map.get(&id).unwrap(), "a", "local binding"))
                }
                // Name matches item from a local name binding
                // created by `use` declaration. For example:
                // ```
                // pub const Foo: &str = "";
                //
                // mod submod {
                //     use super::Foo;
                //     println!("{}", Foo::Bar); // Name refers to local
                //                               // binding `Foo`.
                // }
                // ```
                Some(LateDecl::Decl(name_binding)) => Some((
                    name_binding.span,
                    name_binding.res().article(),
                    name_binding.res().descr(),
                )),
                _ => None,
            };

            let message = format!("cannot find type `{ident}` in {scope}");
            let label = if let Some((span, article, descr)) = match_span {
                format!(
                    "`{ident}` is declared as {article} {descr} at `{}`, not a type",
                    self.tcx
                        .sess
                        .source_map()
                        .span_to_short_string(span, RemapPathScopeComponents::DIAGNOSTICS)
                )
            } else {
                format!("use of undeclared type `{ident}`")
            };
            (message, label, None)
        } else {
            let mut suggestion = None;
            if ident.name == sym::alloc {
                suggestion = Some((
                    vec![],
                    String::from("add `extern crate alloc` to use the `alloc` crate"),
                    Applicability::MaybeIncorrect,
                ))
            }

            suggestion = suggestion.or_else(|| {
                self.find_similarly_named_module_or_crate(ident.name, parent_scope.module).map(
                    |sugg| {
                        (
                            vec![(ident.span, sugg.to_string())],
                            String::from("there is a crate or module with a similar name"),
                            Applicability::MaybeIncorrect,
                        )
                    },
                )
            });
            if let Ok(binding) = self.cm().resolve_ident_in_scope_set(
                ident,
                ScopeSet::All(ValueNS),
                parent_scope,
                None,
                ignore_decl,
                ignore_import,
            ) {
                let descr = binding.res().descr();
                let message = format!("cannot find module or crate `{ident}` in {scope}");
                (message, format!("{descr} `{ident}` is not a crate or module"), suggestion)
            } else {
                let suggestion = if suggestion.is_some() {
                    suggestion
                } else if let Some(m) = self.undeclared_module_exists(ident) {
                    self.undeclared_module_suggest_declare(ident, m)
                } else if was_invoked_from_cargo() {
                    Some((
                        vec![],
                        format!(
                            "if you wanted to use a crate named `{ident}`, use `cargo add {ident}` \
                             to add it to your `Cargo.toml`",
                        ),
                        Applicability::MaybeIncorrect,
                    ))
                } else {
                    Some((
                        vec![],
                        format!("you might be missing a crate named `{ident}`",),
                        Applicability::MaybeIncorrect,
                    ))
                };
                let message = format!("cannot find module or crate `{ident}` in {scope}");
                (
                    message,
                    format!("use of unresolved module or unlinked crate `{ident}`"),
                    suggestion,
                )
            }
        }
    }

    fn undeclared_module_suggest_declare(
        &self,
        ident: Ident,
        path: std::path::PathBuf,
    ) -> Option<(Vec<(Span, String)>, String, Applicability)> {
        Some((
            vec![(self.current_crate_outer_attr_insert_span, format!("mod {ident};\n"))],
            format!(
                "to make use of source file {}, use `mod {ident}` \
                 in this file to declare the module",
                path.display()
            ),
            Applicability::MaybeIncorrect,
        ))
    }

    fn undeclared_module_exists(&self, ident: Ident) -> Option<std::path::PathBuf> {
        let map = self.tcx.sess.source_map();

        let src = map.span_to_filename(ident.span).into_local_path()?;
        let i = ident.as_str();
        // FIXME: add case where non parent using undeclared module (hard?)
        let dir = src.parent()?;
        let src = src.file_stem()?.to_str()?;
        for file in [
            // …/x.rs
            dir.join(i).with_extension("rs"),
            // …/x/mod.rs
            dir.join(i).join("mod.rs"),
        ] {
            if file.exists() {
                return Some(file);
            }
        }
        if !matches!(src, "main" | "lib" | "mod") {
            for file in [
                // …/x/y.rs
                dir.join(src).join(i).with_extension("rs"),
                // …/x/y/mod.rs
                dir.join(src).join(i).join("mod.rs"),
            ] {
                if file.exists() {
                    return Some(file);
                }
            }
        }
        None
    }

    /// Adds suggestions for a path that cannot be resolved.
    #[instrument(level = "debug", skip(self, parent_scope))]
    pub(crate) fn make_path_suggestion(
        &mut self,
        mut path: Vec<Segment>,
        parent_scope: &ParentScope<'ra>,
    ) -> Option<(Vec<Segment>, Option<String>)> {
        match path[..] {
            // `{{root}}::ident::...` on both editions.
            // On 2015 `{{root}}` is usually added implicitly.
            [first, second, ..]
                if first.ident.name == kw::PathRoot && !second.ident.is_path_segment_keyword() => {}
            // `ident::...` on 2018.
            [first, ..]
                if first.ident.span.at_least_rust_2018()
                    && !first.ident.is_path_segment_keyword() =>
            {
                // Insert a placeholder that's later replaced by `self`/`super`/etc.
                path.insert(0, Segment::from_ident(Ident::dummy()));
            }
            _ => return None,
        }

        self.make_missing_self_suggestion(path.clone(), parent_scope)
            .or_else(|| self.make_missing_crate_suggestion(path.clone(), parent_scope))
            .or_else(|| self.make_missing_super_suggestion(path.clone(), parent_scope))
            .or_else(|| self.make_external_crate_suggestion(path, parent_scope))
    }

    /// Suggest a missing `self::` if that resolves to an correct module.
    ///
    /// ```text
    ///    |
    /// LL | use foo::Bar;
    ///    |     ^^^ did you mean `self::foo`?
    /// ```
    #[instrument(level = "debug", skip(self, parent_scope))]
    fn make_missing_self_suggestion(
        &mut self,
        mut path: Vec<Segment>,
        parent_scope: &ParentScope<'ra>,
    ) -> Option<(Vec<Segment>, Option<String>)> {
        // Replace first ident with `self` and check if that is valid.
        path[0].ident.name = kw::SelfLower;
        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
        debug!(?path, ?result);
        if let PathResult::Module(..) = result { Some((path, None)) } else { None }
    }

    /// Suggests a missing `crate::` if that resolves to an correct module.
    ///
    /// ```text
    ///    |
    /// LL | use foo::Bar;
    ///    |     ^^^ did you mean `crate::foo`?
    /// ```
    #[instrument(level = "debug", skip(self, parent_scope))]
    fn make_missing_crate_suggestion(
        &mut self,
        mut path: Vec<Segment>,
        parent_scope: &ParentScope<'ra>,
    ) -> Option<(Vec<Segment>, Option<String>)> {
        // Replace first ident with `crate` and check if that is valid.
        path[0].ident.name = kw::Crate;
        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
        debug!(?path, ?result);
        if let PathResult::Module(..) = result {
            Some((
                path,
                Some(
                    "`use` statements changed in Rust 2018; read more at \
                     <https://doc.rust-lang.org/edition-guide/rust-2018/module-system/path-\
                     clarity.html>"
                        .to_string(),
                ),
            ))
        } else {
            None
        }
    }

    /// Suggests a missing `super::` if that resolves to an correct module.
    ///
    /// ```text
    ///    |
    /// LL | use foo::Bar;
    ///    |     ^^^ did you mean `super::foo`?
    /// ```
    #[instrument(level = "debug", skip(self, parent_scope))]
    fn make_missing_super_suggestion(
        &mut self,
        mut path: Vec<Segment>,
        parent_scope: &ParentScope<'ra>,
    ) -> Option<(Vec<Segment>, Option<String>)> {
        // Replace first ident with `crate` and check if that is valid.
        path[0].ident.name = kw::Super;
        let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
        debug!(?path, ?result);
        if let PathResult::Module(..) = result { Some((path, None)) } else { None }
    }

    /// Suggests a missing external crate name if that resolves to an correct module.
    ///
    /// ```text
    ///    |
    /// LL | use foobar::Baz;
    ///    |     ^^^^^^ did you mean `baz::foobar`?
    /// ```
    ///
    /// Used when importing a submodule of an external crate but missing that crate's
    /// name as the first part of path.
    #[instrument(level = "debug", skip(self, parent_scope))]
    fn make_external_crate_suggestion(
        &mut self,
        mut path: Vec<Segment>,
        parent_scope: &ParentScope<'ra>,
    ) -> Option<(Vec<Segment>, Option<String>)> {
        if path[1].ident.span.is_rust_2015() {
            return None;
        }

        // Sort extern crate names in *reverse* order to get
        // 1) some consistent ordering for emitted diagnostics, and
        // 2) `std` suggestions before `core` suggestions.
        let mut extern_crate_names =
            self.extern_prelude.keys().map(|ident| ident.name).collect::<Vec<_>>();
        extern_crate_names.sort_by(|a, b| b.as_str().cmp(a.as_str()));

        for name in extern_crate_names.into_iter() {
            // Replace first ident with a crate name and check if that is valid.
            path[0].ident.name = name;
            let result = self.cm().maybe_resolve_path(&path, None, parent_scope, None);
            debug!(?path, ?name, ?result);
            if let PathResult::Module(..) = result {
                return Some((path, None));
            }
        }

        None
    }

    /// Suggests importing a macro from the root of the crate rather than a module within
    /// the crate.
    ///
    /// ```text
    /// help: a macro with this name exists at the root of the crate
    ///    |
    /// LL | use issue_59764::makro;
    ///    |     ^^^^^^^^^^^^^^^^^^
    ///    |
    ///    = note: this could be because a macro annotated with `#[macro_export]` will be exported
    ///            at the root of the crate instead of the module where it is defined
    /// ```
    pub(crate) fn check_for_module_export_macro(
        &mut self,
        import: Import<'ra>,
        module: ModuleOrUniformRoot<'ra>,
        ident: Ident,
    ) -> Option<(Option<Suggestion>, Option<String>)> {
        let ModuleOrUniformRoot::Module(mut crate_module) = module else {
            return None;
        };

        while let Some(parent) = crate_module.parent {
            crate_module = parent;
        }

        if module == ModuleOrUniformRoot::Module(crate_module) {
            // Don't make a suggestion if the import was already from the root of the crate.
            return None;
        }

        let binding_key = BindingKey::new(IdentKey::new(ident), MacroNS);
        let binding = self.resolution(crate_module, binding_key)?.best_decl()?;
        let Res::Def(DefKind::Macro(kinds), _) = binding.res() else {
            return None;
        };
        if !kinds.contains(MacroKinds::BANG) {
            return None;
        }
        let module_name = crate_module.name().unwrap_or(kw::Crate);
        let import_snippet = match import.kind {
            ImportKind::Single { source, target, .. } if source != target => {
                format!("{source} as {target}")
            }
            _ => format!("{ident}"),
        };

        let mut corrections: Vec<(Span, String)> = Vec::new();
        if !import.is_nested() {
            // Assume this is the easy case of `use issue_59764::foo::makro;` and just remove
            // intermediate segments.
            corrections.push((import.span, format!("{module_name}::{import_snippet}")));
        } else {
            // Find the binding span (and any trailing commas and spaces).
            //   i.e. `use a::b::{c, d, e};`
            //                      ^^^
            let (found_closing_brace, binding_span) = find_span_of_binding_until_next_binding(
                self.tcx.sess,
                import.span,
                import.use_span,
            );
            debug!(found_closing_brace, ?binding_span);

            let mut removal_span = binding_span;

            // If the binding span ended with a closing brace, as in the below example:
            //   i.e. `use a::b::{c, d};`
            //                      ^
            // Then expand the span of characters to remove to include the previous
            // binding's trailing comma.
            //   i.e. `use a::b::{c, d};`
            //                    ^^^
            if found_closing_brace
                && let Some(previous_span) =
                    extend_span_to_previous_binding(self.tcx.sess, binding_span)
            {
                debug!(?previous_span);
                removal_span = removal_span.with_lo(previous_span.lo());
            }
            debug!(?removal_span);

            // Remove the `removal_span`.
            corrections.push((removal_span, "".to_string()));

            // Find the span after the crate name and if it has nested imports immediately
            // after the crate name already.
            //   i.e. `use a::b::{c, d};`
            //               ^^^^^^^^^
            //   or  `use a::{b, c, d}};`
            //               ^^^^^^^^^^^
            let (has_nested, after_crate_name) =
                find_span_immediately_after_crate_name(self.tcx.sess, import.use_span);
            debug!(has_nested, ?after_crate_name);

            let source_map = self.tcx.sess.source_map();

            // Make sure this is actually crate-relative.
            let is_definitely_crate = import
                .module_path
                .first()
                .is_some_and(|f| f.ident.name != kw::SelfLower && f.ident.name != kw::Super);

            // Add the import to the start, with a `{` if required.
            let start_point = source_map.start_point(after_crate_name);
            if is_definitely_crate
                && let Ok(start_snippet) = source_map.span_to_snippet(start_point)
            {
                corrections.push((
                    start_point,
                    if has_nested {
                        // In this case, `start_snippet` must equal '{'.
                        format!("{start_snippet}{import_snippet}, ")
                    } else {
                        // In this case, add a `{`, then the moved import, then whatever
                        // was there before.
                        format!("{{{import_snippet}, {start_snippet}")
                    },
                ));

                // Add a `};` to the end if nested, matching the `{` added at the start.
                if !has_nested {
                    corrections.push((source_map.end_point(after_crate_name), "};".to_string()));
                }
            } else {
                // If the root import is module-relative, add the import separately
                corrections.push((
                    import.use_span.shrink_to_lo(),
                    format!("use {module_name}::{import_snippet};\n"),
                ));
            }
        }

        let suggestion = Some((
            corrections,
            String::from("a macro with this name exists at the root of the crate"),
            Applicability::MaybeIncorrect,
        ));
        Some((
            suggestion,
            Some(
                "this could be because a macro annotated with `#[macro_export]` will be exported \
            at the root of the crate instead of the module where it is defined"
                    .to_string(),
            ),
        ))
    }

    /// Finds a cfg-ed out item inside `module` with the matching name.
    pub(crate) fn find_cfg_stripped(&self, err: &mut Diag<'_>, segment: &Symbol, module: DefId) {
        let local_items;
        let symbols = if module.is_local() {
            local_items = self
                .stripped_cfg_items
                .iter()
                .filter_map(|item| {
                    let parent_scope = self.local_modules.iter().find_map(|m| match m.kind {
                        ModuleKind::Def(_, def_id, node_id, _) if node_id == item.parent_scope => {
                            Some(def_id)
                        }
                        _ => None,
                    })?;
                    Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() })
                })
                .collect::<Vec<_>>();
            local_items.as_slice()
        } else {
            self.tcx.stripped_cfg_items(module.krate)
        };

        for &StrippedCfgItem { parent_scope, ident, ref cfg } in symbols {
            if ident.name != *segment {
                continue;
            }

            let parent_module = self.get_nearest_non_block_module(parent_scope).def_id();

            fn comes_from_same_module_for_glob(
                r: &Resolver<'_, '_>,
                parent_module: DefId,
                module: DefId,
                visited: &mut FxHashMap<DefId, bool>,
            ) -> bool {
                if let Some(&cached) = visited.get(&parent_module) {
                    // this branch is prevent from being called recursively infinity,
                    // because there has some cycles in globs imports,
                    // see more spec case at `tests/ui/cfg/diagnostics-reexport-2.rs#reexport32`
                    return cached;
                }
                visited.insert(parent_module, false);
                let mut res = false;
                let m = r.expect_module(parent_module);
                if m.is_local() {
                    for importer in m.glob_importers.borrow().iter() {
                        if let Some(next_parent_module) = importer.parent_scope.module.opt_def_id()
                        {
                            if next_parent_module == module
                                || comes_from_same_module_for_glob(
                                    r,
                                    next_parent_module,
                                    module,
                                    visited,
                                )
                            {
                                res = true;
                                break;
                            }
                        }
                    }
                }
                visited.insert(parent_module, res);
                res
            }

            let comes_from_same_module = parent_module == module
                || comes_from_same_module_for_glob(
                    self,
                    parent_module,
                    module,
                    &mut Default::default(),
                );
            if !comes_from_same_module {
                continue;
            }

            let item_was = if let CfgEntry::NameValue { value: Some(feature), .. } = cfg.0 {
                errors::ItemWas::BehindFeature { feature, span: cfg.1 }
            } else {
                errors::ItemWas::CfgOut { span: cfg.1 }
            };
            let note = errors::FoundItemConfigureOut { span: ident.span, item_was };
            err.subdiagnostic(note);
        }
    }

    pub(crate) fn struct_ctor(&self, def_id: DefId) -> Option<StructCtor> {
        match def_id.as_local() {
            Some(def_id) => self.struct_ctors.get(&def_id).cloned(),
            None => {
                self.cstore().ctor_untracked(self.tcx, def_id).map(|(ctor_kind, ctor_def_id)| {
                    let res = Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
                    let vis = self.tcx.visibility(ctor_def_id);
                    let field_visibilities = self
                        .tcx
                        .associated_item_def_ids(def_id)
                        .iter()
                        .map(|&field_id| self.tcx.visibility(field_id))
                        .collect();
                    StructCtor { res, vis, field_visibilities }
                })
            }
        }
    }
}

/// Given a `binding_span` of a binding within a use statement:
///
/// ```ignore (illustrative)
/// use foo::{a, b, c};
/// //           ^
/// ```
///
/// then return the span until the next binding or the end of the statement:
///
/// ```ignore (illustrative)
/// use foo::{a, b, c};
/// //           ^^^
/// ```
fn find_span_of_binding_until_next_binding(
    sess: &Session,
    binding_span: Span,
    use_span: Span,
) -> (bool, Span) {
    let source_map = sess.source_map();

    // Find the span of everything after the binding.
    //   i.e. `a, e};` or `a};`
    let binding_until_end = binding_span.with_hi(use_span.hi());

    // Find everything after the binding but not including the binding.
    //   i.e. `, e};` or `};`
    let after_binding_until_end = binding_until_end.with_lo(binding_span.hi());

    // Keep characters in the span until we encounter something that isn't a comma or
    // whitespace.
    //   i.e. `, ` or ``.
    //
    // Also note whether a closing brace character was encountered. If there
    // was, then later go backwards to remove any trailing commas that are left.
    let mut found_closing_brace = false;
    let after_binding_until_next_binding =
        source_map.span_take_while(after_binding_until_end, |&ch| {
            if ch == '}' {
                found_closing_brace = true;
            }
            ch == ' ' || ch == ','
        });

    // Combine the two spans.
    //   i.e. `a, ` or `a`.
    //
    // Removing these would leave `issue_52891::{d, e};` or `issue_52891::{d, e, };`
    let span = binding_span.with_hi(after_binding_until_next_binding.hi());

    (found_closing_brace, span)
}

/// Given a `binding_span`, return the span through to the comma or opening brace of the previous
/// binding.
///
/// ```ignore (illustrative)
/// use foo::a::{a, b, c};
/// //            ^^--- binding span
/// //            |
/// //            returned span
///
/// use foo::{a, b, c};
/// //        --- binding span
/// ```
fn extend_span_to_previous_binding(sess: &Session, binding_span: Span) -> Option<Span> {
    let source_map = sess.source_map();

    // `prev_source` will contain all of the source that came before the span.
    // Then split based on a command and take the first (i.e. closest to our span)
    // snippet. In the example, this is a space.
    let prev_source = source_map.span_to_prev_source(binding_span).ok()?;

    let prev_comma = prev_source.rsplit(',').collect::<Vec<_>>();
    let prev_starting_brace = prev_source.rsplit('{').collect::<Vec<_>>();
    if prev_comma.len() <= 1 || prev_starting_brace.len() <= 1 {
        return None;
    }

    let prev_comma = prev_comma.first().unwrap();
    let prev_starting_brace = prev_starting_brace.first().unwrap();

    // If the amount of source code before the comma is greater than
    // the amount of source code before the starting brace then we've only
    // got one item in the nested item (eg. `issue_52891::{self}`).
    if prev_comma.len() > prev_starting_brace.len() {
        return None;
    }

    Some(binding_span.with_lo(BytePos(
        // Take away the number of bytes for the characters we've found and an
        // extra for the comma.
        binding_span.lo().0 - (prev_comma.as_bytes().len() as u32) - 1,
    )))
}

/// Given a `use_span` of a binding within a use statement, returns the highlighted span and if
/// it is a nested use tree.
///
/// ```ignore (illustrative)
/// use foo::a::{b, c};
/// //       ^^^^^^^^^^ -- false
///
/// use foo::{a, b, c};
/// //       ^^^^^^^^^^ -- true
///
/// use foo::{a, b::{c, d}};
/// //       ^^^^^^^^^^^^^^^ -- true
/// ```
#[instrument(level = "debug", skip(sess))]
fn find_span_immediately_after_crate_name(sess: &Session, use_span: Span) -> (bool, Span) {
    let source_map = sess.source_map();

    // Using `use issue_59764::foo::{baz, makro};` as an example throughout..
    let mut num_colons = 0;
    // Find second colon.. `use issue_59764:`
    let until_second_colon = source_map.span_take_while(use_span, |c| {
        if *c == ':' {
            num_colons += 1;
        }
        !matches!(c, ':' if num_colons == 2)
    });
    // Find everything after the second colon.. `foo::{baz, makro};`
    let from_second_colon = use_span.with_lo(until_second_colon.hi() + BytePos(1));

    let mut found_a_non_whitespace_character = false;
    // Find the first non-whitespace character in `from_second_colon`.. `f`
    let after_second_colon = source_map.span_take_while(from_second_colon, |c| {
        if found_a_non_whitespace_character {
            return false;
        }
        if !c.is_whitespace() {
            found_a_non_whitespace_character = true;
        }
        true
    });

    // Find the first `{` in from_second_colon.. `foo::{`
    let next_left_bracket = source_map.span_through_char(from_second_colon, '{');

    (next_left_bracket == after_second_colon, from_second_colon)
}

/// A suggestion has already been emitted, change the wording slightly to clarify that both are
/// independent options.
enum Instead {
    Yes,
    No,
}

/// Whether an existing place with an `use` item was found.
enum FoundUse {
    Yes,
    No,
}

/// Whether a binding is part of a pattern or a use statement. Used for diagnostics.
pub(crate) enum DiagMode {
    Normal,
    /// The binding is part of a pattern
    Pattern,
    /// The binding is part of a use statement
    Import {
        /// `true` means diagnostics is for unresolved import
        unresolved_import: bool,
        /// `true` mean add the tips afterward for case `use a::{b,c}`,
        /// rather than replacing within.
        append: bool,
    },
}

pub(crate) fn import_candidates(
    tcx: TyCtxt<'_>,
    err: &mut Diag<'_>,
    // This is `None` if all placement locations are inside expansions
    use_placement_span: Option<Span>,
    candidates: &[ImportSuggestion],
    mode: DiagMode,
    append: &str,
) {
    show_candidates(
        tcx,
        err,
        use_placement_span,
        candidates,
        Instead::Yes,
        FoundUse::Yes,
        mode,
        vec![],
        append,
    );
}

type PathString<'a> = (String, &'a str, Option<Span>, &'a Option<String>, bool);

/// When an entity with a given name is not available in scope, we search for
/// entities with that name in all crates. This method allows outputting the
/// results of this search in a programmer-friendly way. If any entities are
/// found and suggested, returns `true`, otherwise returns `false`.
fn show_candidates(
    tcx: TyCtxt<'_>,
    err: &mut Diag<'_>,
    // This is `None` if all placement locations are inside expansions
    use_placement_span: Option<Span>,
    candidates: &[ImportSuggestion],
    instead: Instead,
    found_use: FoundUse,
    mode: DiagMode,
    path: Vec<Segment>,
    append: &str,
) -> bool {
    if candidates.is_empty() {
        return false;
    }

    let mut showed = false;
    let mut accessible_path_strings: Vec<PathString<'_>> = Vec::new();
    let mut inaccessible_path_strings: Vec<PathString<'_>> = Vec::new();

    candidates.iter().for_each(|c| {
        if c.accessible {
            // Don't suggest `#[doc(hidden)]` items from other crates
            if c.doc_visible {
                accessible_path_strings.push((
                    pprust::path_to_string(&c.path),
                    c.descr,
                    c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
                    &c.note,
                    c.via_import,
                ))
            }
        } else {
            inaccessible_path_strings.push((
                pprust::path_to_string(&c.path),
                c.descr,
                c.did.and_then(|did| Some(tcx.source_span(did.as_local()?))),
                &c.note,
                c.via_import,
            ))
        }
    });

    // we want consistent results across executions, but candidates are produced
    // by iterating through a hash map, so make sure they are ordered:
    for path_strings in [&mut accessible_path_strings, &mut inaccessible_path_strings] {
        path_strings.sort_by(|a, b| a.0.cmp(&b.0));
        path_strings.dedup_by(|a, b| a.0 == b.0);
        let core_path_strings =
            path_strings.extract_if(.., |p| p.0.starts_with("core::")).collect::<Vec<_>>();
        let std_path_strings =
            path_strings.extract_if(.., |p| p.0.starts_with("std::")).collect::<Vec<_>>();
        let foreign_crate_path_strings =
            path_strings.extract_if(.., |p| !p.0.starts_with("crate::")).collect::<Vec<_>>();

        // We list the `crate` local paths first.
        // Then we list the `std`/`core` paths.
        if std_path_strings.len() == core_path_strings.len() {
            // Do not list `core::` paths if we are already listing the `std::` ones.
            path_strings.extend(std_path_strings);
        } else {
            path_strings.extend(std_path_strings);
            path_strings.extend(core_path_strings);
        }
        // List all paths from foreign crates last.
        path_strings.extend(foreign_crate_path_strings);
    }

    if !accessible_path_strings.is_empty() {
        let (determiner, kind, s, name, through) =
            if let [(name, descr, _, _, via_import)] = &accessible_path_strings[..] {
                (
                    "this",
                    *descr,
                    "",
                    format!(" `{name}`"),
                    if *via_import { " through its public re-export" } else { "" },
                )
            } else {
                // Get the unique item kinds and if there's only one, we use the right kind name
                // instead of the more generic "items".
                let kinds = accessible_path_strings
                    .iter()
                    .map(|(_, descr, _, _, _)| *descr)
                    .collect::<UnordSet<&str>>();
                let kind = if let Some(kind) = kinds.get_only() { kind } else { "item" };
                let s = if kind.ends_with('s') { "es" } else { "s" };

                ("one of these", kind, s, String::new(), "")
            };

        let instead = if let Instead::Yes = instead { " instead" } else { "" };
        let mut msg = if let DiagMode::Pattern = mode {
            format!(
                "if you meant to match on {kind}{s}{instead}{name}, use the full path in the \
                 pattern",
            )
        } else {
            format!("consider importing {determiner} {kind}{s}{through}{instead}")
        };

        for note in accessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
            err.note(note.clone());
        }

        let append_candidates = |msg: &mut String, accessible_path_strings: Vec<PathString<'_>>| {
            msg.push(':');

            for candidate in accessible_path_strings {
                msg.push('\n');
                msg.push_str(&candidate.0);
            }
        };

        if let Some(span) = use_placement_span {
            let (add_use, trailing) = match mode {
                DiagMode::Pattern => {
                    err.span_suggestions(
                        span,
                        msg,
                        accessible_path_strings.into_iter().map(|a| a.0),
                        Applicability::MaybeIncorrect,
                    );
                    return true;
                }
                DiagMode::Import { .. } => ("", ""),
                DiagMode::Normal => ("use ", ";\n"),
            };
            for candidate in &mut accessible_path_strings {
                // produce an additional newline to separate the new use statement
                // from the directly following item.
                let additional_newline = if let FoundUse::No = found_use
                    && let DiagMode::Normal = mode
                {
                    "\n"
                } else {
                    ""
                };
                candidate.0 =
                    format!("{add_use}{}{append}{trailing}{additional_newline}", candidate.0);
            }

            match mode {
                DiagMode::Import { append: true, .. } => {
                    append_candidates(&mut msg, accessible_path_strings);
                    err.span_help(span, msg);
                }
                _ => {
                    err.span_suggestions_with_style(
                        span,
                        msg,
                        accessible_path_strings.into_iter().map(|a| a.0),
                        Applicability::MaybeIncorrect,
                        SuggestionStyle::ShowAlways,
                    );
                }
            }

            if let [first, .., last] = &path[..] {
                let sp = first.ident.span.until(last.ident.span);
                // Our suggestion is empty, so make sure the span is not empty (or we'd ICE).
                // Can happen for derive-generated spans.
                if sp.can_be_used_for_suggestions() && !sp.is_empty() {
                    err.span_suggestion_verbose(
                        sp,
                        format!("if you import `{}`, refer to it directly", last.ident),
                        "",
                        Applicability::Unspecified,
                    );
                }
            }
        } else {
            append_candidates(&mut msg, accessible_path_strings);
            err.help(msg);
        }
        showed = true;
    }
    if !inaccessible_path_strings.is_empty()
        && (!matches!(mode, DiagMode::Import { unresolved_import: false, .. }))
    {
        let prefix =
            if let DiagMode::Pattern = mode { "you might have meant to match on " } else { "" };
        if let [(name, descr, source_span, note, _)] = &inaccessible_path_strings[..] {
            let msg = format!(
                "{prefix}{descr} `{name}`{} exists but is inaccessible",
                if let DiagMode::Pattern = mode { ", which" } else { "" }
            );

            if let Some(source_span) = source_span {
                let span = tcx.sess.source_map().guess_head_span(*source_span);
                let mut multi_span = MultiSpan::from_span(span);
                multi_span.push_span_label(span, "not accessible");
                err.span_note(multi_span, msg);
            } else {
                err.note(msg);
            }
            if let Some(note) = (*note).as_deref() {
                err.note(note.to_string());
            }
        } else {
            let descr = inaccessible_path_strings
                .iter()
                .map(|&(_, descr, _, _, _)| descr)
                .all_equal_value()
                .unwrap_or("item");
            let plural_descr =
                if descr.ends_with('s') { format!("{descr}es") } else { format!("{descr}s") };

            let mut msg = format!("{prefix}these {plural_descr} exist but are inaccessible");
            let mut has_colon = false;

            let mut spans = Vec::new();
            for (name, _, source_span, _, _) in &inaccessible_path_strings {
                if let Some(source_span) = source_span {
                    let span = tcx.sess.source_map().guess_head_span(*source_span);
                    spans.push((name, span));
                } else {
                    if !has_colon {
                        msg.push(':');
                        has_colon = true;
                    }
                    msg.push('\n');
                    msg.push_str(name);
                }
            }

            let mut multi_span = MultiSpan::from_spans(spans.iter().map(|(_, sp)| *sp).collect());
            for (name, span) in spans {
                multi_span.push_span_label(span, format!("`{name}`: not accessible"));
            }

            for note in inaccessible_path_strings.iter().flat_map(|cand| cand.3.as_ref()) {
                err.note(note.clone());
            }

            err.span_note(multi_span, msg);
        }
        showed = true;
    }
    showed
}

#[derive(Debug)]
struct UsePlacementFinder {
    target_module: NodeId,
    first_legal_span: Option<Span>,
    first_use_span: Option<Span>,
}

impl UsePlacementFinder {
    fn check(krate: &Crate, target_module: NodeId) -> (Option<Span>, FoundUse) {
        let mut finder =
            UsePlacementFinder { target_module, first_legal_span: None, first_use_span: None };
        finder.visit_crate(krate);
        if let Some(use_span) = finder.first_use_span {
            (Some(use_span), FoundUse::Yes)
        } else {
            (finder.first_legal_span, FoundUse::No)
        }
    }
}

impl<'tcx> Visitor<'tcx> for UsePlacementFinder {
    fn visit_crate(&mut self, c: &Crate) {
        if self.target_module == CRATE_NODE_ID {
            let inject = c.spans.inject_use_span;
            if is_span_suitable_for_use_injection(inject) {
                self.first_legal_span = Some(inject);
            }
            self.first_use_span = search_for_any_use_in_items(&c.items);
        } else {
            visit::walk_crate(self, c);
        }
    }

    fn visit_item(&mut self, item: &'tcx ast::Item) {
        if self.target_module == item.id {
            if let ItemKind::Mod(_, _, ModKind::Loaded(items, _inline, mod_spans)) = &item.kind {
                let inject = mod_spans.inject_use_span;
                if is_span_suitable_for_use_injection(inject) {
                    self.first_legal_span = Some(inject);
                }
                self.first_use_span = search_for_any_use_in_items(items);
            }
        } else {
            visit::walk_item(self, item);
        }
    }
}

#[derive(Default)]
struct BindingVisitor {
    identifiers: Vec<Symbol>,
    spans: FxHashMap<Symbol, Vec<Span>>,
}

impl<'tcx> Visitor<'tcx> for BindingVisitor {
    fn visit_pat(&mut self, pat: &ast::Pat) {
        if let ast::PatKind::Ident(_, ident, _) = pat.kind {
            self.identifiers.push(ident.name);
            self.spans.entry(ident.name).or_default().push(ident.span);
        }
        visit::walk_pat(self, pat);
    }
}

fn search_for_any_use_in_items(items: &[Box<ast::Item>]) -> Option<Span> {
    for item in items {
        if let ItemKind::Use(..) = item.kind
            && is_span_suitable_for_use_injection(item.span)
        {
            let mut lo = item.span.lo();
            for attr in &item.attrs {
                if attr.span.eq_ctxt(item.span) {
                    lo = std::cmp::min(lo, attr.span.lo());
                }
            }
            return Some(Span::new(lo, lo, item.span.ctxt(), item.span.parent()));
        }
    }
    None
}

fn is_span_suitable_for_use_injection(s: Span) -> bool {
    // don't suggest placing a use before the prelude
    // import or other generated ones
    !s.from_expansion()
}
