// ignore-tidy-filelength

use std::borrow::Cow;
use std::iter;
use std::ops::Deref;

use rustc_ast::visit::{FnCtxt, FnKind, LifetimeCtxt, Visitor, walk_ty};
use rustc_ast::{
    self as ast, AssocItemKind, DUMMY_NODE_ID, Expr, ExprKind, GenericParam, GenericParamKind,
    Item, ItemKind, MethodCall, NodeId, Path, PathSegment, Ty, TyKind,
};
use rustc_ast_pretty::pprust::where_bound_predicate_to_string;
use rustc_attr_parsing::is_doc_alias_attrs_contain_symbol;
use rustc_data_structures::fx::{FxHashSet, FxIndexSet};
use rustc_errors::codes::*;
use rustc_errors::{
    Applicability, Diag, ErrorGuaranteed, MultiSpan, SuggestionStyle, pluralize,
    struct_span_code_err,
};
use rustc_hir as hir;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, CtorOf, DefKind, MacroKinds};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId};
use rustc_hir::{MissingLifetimeKind, PrimTy};
use rustc_middle::ty;
use rustc_session::{Session, lint};
use rustc_span::edit_distance::{edit_distance, find_best_match_for_name};
use rustc_span::edition::Edition;
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
use thin_vec::ThinVec;
use tracing::debug;

use super::NoConstantGenericsReason;
use crate::diagnostics::{ImportSuggestion, LabelSuggestion, TypoSuggestion};
use crate::late::{
    AliasPossibility, LateResolutionVisitor, LifetimeBinderKind, LifetimeRes, LifetimeRibKind,
    LifetimeUseSet, QSelf, RibKind,
};
use crate::ty::fast_reject::SimplifiedType;
use crate::{
    Module, ModuleKind, ModuleOrUniformRoot, ParentScope, PathResult, PathSource, Resolver,
    ScopeSet, Segment, errors, path_names_to_string,
};

type Res = def::Res<ast::NodeId>;

/// A field or associated item from self type suggested in case of resolution failure.
enum AssocSuggestion {
    Field(Span),
    MethodWithSelf { called: bool },
    AssocFn { called: bool },
    AssocType,
    AssocConst,
}

impl AssocSuggestion {
    fn action(&self) -> &'static str {
        match self {
            AssocSuggestion::Field(_) => "use the available field",
            AssocSuggestion::MethodWithSelf { called: true } => {
                "call the method with the fully-qualified path"
            }
            AssocSuggestion::MethodWithSelf { called: false } => {
                "refer to the method with the fully-qualified path"
            }
            AssocSuggestion::AssocFn { called: true } => "call the associated function",
            AssocSuggestion::AssocFn { called: false } => "refer to the associated function",
            AssocSuggestion::AssocConst => "use the associated `const`",
            AssocSuggestion::AssocType => "use the associated type",
        }
    }
}

fn is_self_type(path: &[Segment], namespace: Namespace) -> bool {
    namespace == TypeNS && path.len() == 1 && path[0].ident.name == kw::SelfUpper
}

fn is_self_value(path: &[Segment], namespace: Namespace) -> bool {
    namespace == ValueNS && path.len() == 1 && path[0].ident.name == kw::SelfLower
}

/// Gets the stringified path for an enum from an `ImportSuggestion` for an enum variant.
fn import_candidate_to_enum_paths(suggestion: &ImportSuggestion) -> (String, String) {
    let variant_path = &suggestion.path;
    let variant_path_string = path_names_to_string(variant_path);

    let path_len = suggestion.path.segments.len();
    let enum_path = ast::Path {
        span: suggestion.path.span,
        segments: suggestion.path.segments[0..path_len - 1].iter().cloned().collect(),
        tokens: None,
    };
    let enum_path_string = path_names_to_string(&enum_path);

    (variant_path_string, enum_path_string)
}

/// Description of an elided lifetime.
#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Debug)]
pub(super) struct MissingLifetime {
    /// Used to overwrite the resolution with the suggestion, to avoid cascading errors.
    pub id: NodeId,
    /// As we cannot yet emit lints in this crate and have to buffer them instead,
    /// we need to associate each lint with some `NodeId`,
    /// however for some `MissingLifetime`s their `NodeId`s are "fake",
    /// in a sense that they are temporary and not get preserved down the line,
    /// which means that the lints for those nodes will not get emitted.
    /// To combat this, we can try to use some other `NodeId`s as a fallback option.
    pub id_for_lint: NodeId,
    /// Where to suggest adding the lifetime.
    pub span: Span,
    /// How the lifetime was introduced, to have the correct space and comma.
    pub kind: MissingLifetimeKind,
    /// Number of elided lifetimes, used for elision in path.
    pub count: usize,
}

/// Description of the lifetimes appearing in a function parameter.
/// This is used to provide a literal explanation to the elision failure.
#[derive(Clone, Debug)]
pub(super) struct ElisionFnParameter {
    /// The index of the argument in the original definition.
    pub index: usize,
    /// The name of the argument if it's a simple ident.
    pub ident: Option<Ident>,
    /// The number of lifetimes in the parameter.
    pub lifetime_count: usize,
    /// The span of the parameter.
    pub span: Span,
}

/// Description of lifetimes that appear as candidates for elision.
/// This is used to suggest introducing an explicit lifetime.
#[derive(Debug)]
pub(super) enum LifetimeElisionCandidate {
    /// This is not a real lifetime.
    Ignore,
    /// There is a named lifetime, we won't suggest anything.
    Named,
    Missing(MissingLifetime),
}

/// Only used for diagnostics.
#[derive(Debug)]
struct BaseError {
    msg: String,
    fallback_label: String,
    span: Span,
    span_label: Option<(Span, &'static str)>,
    could_be_expr: bool,
    suggestion: Option<(Span, &'static str, String)>,
    module: Option<DefId>,
}

#[derive(Debug)]
enum TypoCandidate {
    Typo(TypoSuggestion),
    Shadowed(Res, Option<Span>),
    None,
}

impl TypoCandidate {
    fn to_opt_suggestion(self) -> Option<TypoSuggestion> {
        match self {
            TypoCandidate::Typo(sugg) => Some(sugg),
            TypoCandidate::Shadowed(_, _) | TypoCandidate::None => None,
        }
    }
}

impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
    fn make_base_error(
        &mut self,
        path: &[Segment],
        span: Span,
        source: PathSource<'_, 'ast, 'ra>,
        res: Option<Res>,
    ) -> BaseError {
        // Make the base error.
        let mut expected = source.descr_expected();
        let path_str = Segment::names_to_string(path);
        let item_str = path.last().unwrap().ident;
        if let Some(res) = res {
            BaseError {
                msg: format!("expected {}, found {} `{}`", expected, res.descr(), path_str),
                fallback_label: format!("not a {expected}"),
                span,
                span_label: match res {
                    Res::Def(DefKind::TyParam, def_id) => {
                        Some((self.r.def_span(def_id), "found this type parameter"))
                    }
                    _ => None,
                },
                could_be_expr: match res {
                    Res::Def(DefKind::Fn, _) => {
                        // Verify whether this is a fn call or an Fn used as a type.
                        self.r
                            .tcx
                            .sess
                            .source_map()
                            .span_to_snippet(span)
                            .is_ok_and(|snippet| snippet.ends_with(')'))
                    }
                    Res::Def(
                        DefKind::Ctor(..) | DefKind::AssocFn | DefKind::Const | DefKind::AssocConst,
                        _,
                    )
                    | Res::SelfCtor(_)
                    | Res::PrimTy(_)
                    | Res::Local(_) => true,
                    _ => false,
                },
                suggestion: None,
                module: None,
            }
        } else {
            let mut span_label = None;
            let item_ident = path.last().unwrap().ident;
            let item_span = item_ident.span;
            let (mod_prefix, mod_str, module, suggestion) = if path.len() == 1 {
                debug!(?self.diag_metadata.current_impl_items);
                debug!(?self.diag_metadata.current_function);
                let suggestion = if self.current_trait_ref.is_none()
                    && let Some((fn_kind, _)) = self.diag_metadata.current_function
                    && let Some(FnCtxt::Assoc(_)) = fn_kind.ctxt()
                    && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = fn_kind
                    && let Some(items) = self.diag_metadata.current_impl_items
                    && let Some(item) = items.iter().find(|i| {
                        i.kind.ident().is_some_and(|ident| {
                            // Don't suggest if the item is in Fn signature arguments (#112590).
                            ident.name == item_str.name && !sig.span.contains(item_span)
                        })
                    }) {
                    let sp = item_span.shrink_to_lo();

                    // Account for `Foo { field }` when suggesting `self.field` so we result on
                    // `Foo { field: self.field }`.
                    let field = match source {
                        PathSource::Expr(Some(Expr { kind: ExprKind::Struct(expr), .. })) => {
                            expr.fields.iter().find(|f| f.ident == item_ident)
                        }
                        _ => None,
                    };
                    let pre = if let Some(field) = field
                        && field.is_shorthand
                    {
                        format!("{item_ident}: ")
                    } else {
                        String::new()
                    };
                    // Ensure we provide a structured suggestion for an assoc fn only for
                    // expressions that are actually a fn call.
                    let is_call = match field {
                        Some(ast::ExprField { expr, .. }) => {
                            matches!(expr.kind, ExprKind::Call(..))
                        }
                        _ => matches!(
                            source,
                            PathSource::Expr(Some(Expr { kind: ExprKind::Call(..), .. })),
                        ),
                    };

                    match &item.kind {
                        AssocItemKind::Fn(fn_)
                            if (!sig.decl.has_self() || !is_call) && fn_.sig.decl.has_self() =>
                        {
                            // Ensure that we only suggest `self.` if `self` is available,
                            // you can't call `fn foo(&self)` from `fn bar()` (#115992).
                            // We also want to mention that the method exists.
                            span_label = Some((
                                fn_.ident.span,
                                "a method by that name is available on `Self` here",
                            ));
                            None
                        }
                        AssocItemKind::Fn(fn_) if !fn_.sig.decl.has_self() && !is_call => {
                            span_label = Some((
                                fn_.ident.span,
                                "an associated function by that name is available on `Self` here",
                            ));
                            None
                        }
                        AssocItemKind::Fn(fn_) if fn_.sig.decl.has_self() => {
                            Some((sp, "consider using the method on `Self`", format!("{pre}self.")))
                        }
                        AssocItemKind::Fn(_) => Some((
                            sp,
                            "consider using the associated function on `Self`",
                            format!("{pre}Self::"),
                        )),
                        AssocItemKind::Const(..) => Some((
                            sp,
                            "consider using the associated constant on `Self`",
                            format!("{pre}Self::"),
                        )),
                        _ => None,
                    }
                } else {
                    None
                };
                (String::new(), "this scope".to_string(), None, suggestion)
            } else if path.len() == 2 && path[0].ident.name == kw::PathRoot {
                if self.r.tcx.sess.edition() > Edition::Edition2015 {
                    // In edition 2018 onwards, the `::foo` syntax may only pull from the extern prelude
                    // which overrides all other expectations of item type
                    expected = "crate";
                    (String::new(), "the list of imported crates".to_string(), None, None)
                } else {
                    (
                        String::new(),
                        "the crate root".to_string(),
                        Some(CRATE_DEF_ID.to_def_id()),
                        None,
                    )
                }
            } else if path.len() == 2 && path[0].ident.name == kw::Crate {
                (String::new(), "the crate root".to_string(), Some(CRATE_DEF_ID.to_def_id()), None)
            } else {
                let mod_path = &path[..path.len() - 1];
                let mod_res = self.resolve_path(mod_path, Some(TypeNS), None, source);
                let mod_prefix = match mod_res {
                    PathResult::Module(ModuleOrUniformRoot::Module(module)) => module.res(),
                    _ => None,
                };

                let module_did = mod_prefix.as_ref().and_then(Res::mod_def_id);

                let mod_prefix =
                    mod_prefix.map_or_else(String::new, |res| format!("{} ", res.descr()));
                (mod_prefix, format!("`{}`", Segment::names_to_string(mod_path)), module_did, None)
            };

            let (fallback_label, suggestion) = if path_str == "async"
                && expected.starts_with("struct")
            {
                ("`async` blocks are only allowed in Rust 2018 or later".to_string(), suggestion)
            } else {
                // check if we are in situation of typo like `True` instead of `true`.
                let override_suggestion =
                    if ["true", "false"].contains(&item_str.to_string().to_lowercase().as_str()) {
                        let item_typo = item_str.to_string().to_lowercase();
                        Some((item_span, "you may want to use a bool value instead", item_typo))
                    // FIXME(vincenzopalazzo): make the check smarter,
                    // and maybe expand with levenshtein distance checks
                    } else if item_str.as_str() == "printf" {
                        Some((
                            item_span,
                            "you may have meant to use the `print` macro",
                            "print!".to_owned(),
                        ))
                    } else {
                        suggestion
                    };
                (format!("not found in {mod_str}"), override_suggestion)
            };

            BaseError {
                msg: format!("cannot find {expected} `{item_str}` in {mod_prefix}{mod_str}"),
                fallback_label,
                span: item_span,
                span_label,
                could_be_expr: false,
                suggestion,
                module,
            }
        }
    }

    /// Try to suggest for a module path that cannot be resolved.
    /// Such as `fmt::Debug` where `fmt` is not resolved without importing,
    /// here we search with `lookup_import_candidates` for a module named `fmt`
    /// with `TypeNS` as namespace.
    ///
    /// We need a separate function here because we won't suggest for a path with single segment
    /// and we won't change `SourcePath` api `is_expected` to match `Type` with `DefKind::Mod`
    pub(crate) fn smart_resolve_partial_mod_path_errors(
        &mut self,
        prefix_path: &[Segment],
        following_seg: Option<&Segment>,
    ) -> Vec<ImportSuggestion> {
        if let Some(segment) = prefix_path.last()
            && let Some(following_seg) = following_seg
        {
            let candidates = self.r.lookup_import_candidates(
                segment.ident,
                Namespace::TypeNS,
                &self.parent_scope,
                &|res: Res| matches!(res, Res::Def(DefKind::Mod, _)),
            );
            // double check next seg is valid
            candidates
                .into_iter()
                .filter(|candidate| {
                    if let Some(def_id) = candidate.did
                        && let Some(module) = self.r.get_module(def_id)
                    {
                        Some(def_id) != self.parent_scope.module.opt_def_id()
                            && self
                                .r
                                .resolutions(module)
                                .borrow()
                                .iter()
                                .any(|(key, _r)| key.ident.name == following_seg.ident.name)
                    } else {
                        false
                    }
                })
                .collect::<Vec<_>>()
        } else {
            Vec::new()
        }
    }

    /// Handles error reporting for `smart_resolve_path_fragment` function.
    /// Creates base error and amends it with one short label and possibly some longer helps/notes.
    pub(crate) fn smart_resolve_report_errors(
        &mut self,
        path: &[Segment],
        following_seg: Option<&Segment>,
        span: Span,
        source: PathSource<'_, 'ast, 'ra>,
        res: Option<Res>,
        qself: Option<&QSelf>,
    ) -> (Diag<'tcx>, Vec<ImportSuggestion>) {
        debug!(?res, ?source);
        let base_error = self.make_base_error(path, span, source, res);

        let code = source.error_code(res.is_some());
        let mut err = self.r.dcx().struct_span_err(base_error.span, base_error.msg.clone());
        err.code(code);

        // Try to get the span of the identifier within the path's syntax context
        // (if that's different).
        if let Some(within_macro_span) =
            base_error.span.within_macro(span, self.r.tcx.sess.source_map())
        {
            err.span_label(within_macro_span, "due to this macro variable");
        }

        self.detect_missing_binding_available_from_pattern(&mut err, path, following_seg);
        self.suggest_at_operator_in_slice_pat_with_range(&mut err, path);
        self.suggest_swapping_misplaced_self_ty_and_trait(&mut err, source, res, base_error.span);

        if let Some((span, label)) = base_error.span_label {
            err.span_label(span, label);
        }

        if let Some(ref sugg) = base_error.suggestion {
            err.span_suggestion_verbose(sugg.0, sugg.1, &sugg.2, Applicability::MaybeIncorrect);
        }

        self.suggest_changing_type_to_const_param(&mut err, res, source, span);
        self.explain_functions_in_pattern(&mut err, res, source);

        if self.suggest_pattern_match_with_let(&mut err, source, span) {
            // Fallback label.
            err.span_label(base_error.span, base_error.fallback_label);
            return (err, Vec::new());
        }

        self.suggest_self_or_self_ref(&mut err, path, span);
        self.detect_assoc_type_constraint_meant_as_path(&mut err, &base_error);
        self.detect_rtn_with_fully_qualified_path(
            &mut err,
            path,
            following_seg,
            span,
            source,
            res,
            qself,
        );
        if self.suggest_self_ty(&mut err, source, path, span)
            || self.suggest_self_value(&mut err, source, path, span)
        {
            return (err, Vec::new());
        }

        if let Some((did, item)) = self.lookup_doc_alias_name(path, source.namespace()) {
            let item_name = item.name;
            let suggestion_name = self.r.tcx.item_name(did);
            err.span_suggestion(
                item.span,
                format!("`{suggestion_name}` has a name defined in the doc alias attribute as `{item_name}`"),
                    suggestion_name,
                    Applicability::MaybeIncorrect
                );

            return (err, Vec::new());
        };

        let (found, suggested_candidates, mut candidates) = self.try_lookup_name_relaxed(
            &mut err,
            source,
            path,
            following_seg,
            span,
            res,
            &base_error,
        );
        if found {
            return (err, candidates);
        }

        if self.suggest_shadowed(&mut err, source, path, following_seg, span) {
            // if there is already a shadowed name, don'suggest candidates for importing
            candidates.clear();
        }

        let mut fallback = self.suggest_trait_and_bounds(&mut err, source, res, span, &base_error);
        fallback |= self.suggest_typo(
            &mut err,
            source,
            path,
            following_seg,
            span,
            &base_error,
            suggested_candidates,
        );

        if fallback {
            // Fallback label.
            err.span_label(base_error.span, base_error.fallback_label);
        }
        self.err_code_special_cases(&mut err, source, path, span);

        let module = base_error.module.unwrap_or_else(|| CRATE_DEF_ID.to_def_id());
        self.r.find_cfg_stripped(&mut err, &path.last().unwrap().ident.name, module);

        (err, candidates)
    }

    fn detect_rtn_with_fully_qualified_path(
        &self,
        err: &mut Diag<'_>,
        path: &[Segment],
        following_seg: Option<&Segment>,
        span: Span,
        source: PathSource<'_, '_, '_>,
        res: Option<Res>,
        qself: Option<&QSelf>,
    ) {
        if let Some(Res::Def(DefKind::AssocFn, _)) = res
            && let PathSource::TraitItem(TypeNS, _) = source
            && let None = following_seg
            && let Some(qself) = qself
            && let TyKind::Path(None, ty_path) = &qself.ty.kind
            && ty_path.segments.len() == 1
            && self.diag_metadata.current_where_predicate.is_some()
        {
            err.span_suggestion_verbose(
                span,
                "you might have meant to use the return type notation syntax",
                format!("{}::{}(..)", ty_path.segments[0].ident, path[path.len() - 1].ident),
                Applicability::MaybeIncorrect,
            );
        }
    }

    fn detect_assoc_type_constraint_meant_as_path(
        &self,
        err: &mut Diag<'_>,
        base_error: &BaseError,
    ) {
        let Some(ty) = self.diag_metadata.current_type_path else {
            return;
        };
        let TyKind::Path(_, path) = &ty.kind else {
            return;
        };
        for segment in &path.segments {
            let Some(params) = &segment.args else {
                continue;
            };
            let ast::GenericArgs::AngleBracketed(params) = params.deref() else {
                continue;
            };
            for param in &params.args {
                let ast::AngleBracketedArg::Constraint(constraint) = param else {
                    continue;
                };
                let ast::AssocItemConstraintKind::Bound { bounds } = &constraint.kind else {
                    continue;
                };
                for bound in bounds {
                    let ast::GenericBound::Trait(trait_ref) = bound else {
                        continue;
                    };
                    if trait_ref.modifiers == ast::TraitBoundModifiers::NONE
                        && base_error.span == trait_ref.span
                    {
                        err.span_suggestion_verbose(
                            constraint.ident.span.between(trait_ref.span),
                            "you might have meant to write a path instead of an associated type bound",
                            "::",
                            Applicability::MachineApplicable,
                        );
                    }
                }
            }
        }
    }

    fn suggest_self_or_self_ref(&mut self, err: &mut Diag<'_>, path: &[Segment], span: Span) {
        if !self.self_type_is_available() {
            return;
        }
        let Some(path_last_segment) = path.last() else { return };
        let item_str = path_last_segment.ident;
        // Emit help message for fake-self from other languages (e.g., `this` in JavaScript).
        if ["this", "my"].contains(&item_str.as_str()) {
            err.span_suggestion_short(
                span,
                "you might have meant to use `self` here instead",
                "self",
                Applicability::MaybeIncorrect,
            );
            if !self.self_value_is_available(path[0].ident.span) {
                if let Some((FnKind::Fn(_, _, ast::Fn { sig, .. }), fn_span)) =
                    &self.diag_metadata.current_function
                {
                    let (span, sugg) = if let Some(param) = sig.decl.inputs.get(0) {
                        (param.span.shrink_to_lo(), "&self, ")
                    } else {
                        (
                            self.r
                                .tcx
                                .sess
                                .source_map()
                                .span_through_char(*fn_span, '(')
                                .shrink_to_hi(),
                            "&self",
                        )
                    };
                    err.span_suggestion_verbose(
                        span,
                        "if you meant to use `self`, you are also missing a `self` receiver \
                         argument",
                        sugg,
                        Applicability::MaybeIncorrect,
                    );
                }
            }
        }
    }

    fn try_lookup_name_relaxed(
        &mut self,
        err: &mut Diag<'_>,
        source: PathSource<'_, '_, '_>,
        path: &[Segment],
        following_seg: Option<&Segment>,
        span: Span,
        res: Option<Res>,
        base_error: &BaseError,
    ) -> (bool, FxHashSet<String>, Vec<ImportSuggestion>) {
        let span = match following_seg {
            Some(_) if path[0].ident.span.eq_ctxt(path[path.len() - 1].ident.span) => {
                // The path `span` that comes in includes any following segments, which we don't
                // want to replace in the suggestions.
                path[0].ident.span.to(path[path.len() - 1].ident.span)
            }
            _ => span,
        };
        let mut suggested_candidates = FxHashSet::default();
        // Try to lookup name in more relaxed fashion for better error reporting.
        let ident = path.last().unwrap().ident;
        let is_expected = &|res| source.is_expected(res);
        let ns = source.namespace();
        let is_enum_variant = &|res| matches!(res, Res::Def(DefKind::Variant, _));
        let path_str = Segment::names_to_string(path);
        let ident_span = path.last().map_or(span, |ident| ident.ident.span);
        let mut candidates = self
            .r
            .lookup_import_candidates(ident, ns, &self.parent_scope, is_expected)
            .into_iter()
            .filter(|ImportSuggestion { did, .. }| {
                match (did, res.and_then(|res| res.opt_def_id())) {
                    (Some(suggestion_did), Some(actual_did)) => *suggestion_did != actual_did,
                    _ => true,
                }
            })
            .collect::<Vec<_>>();
        // Try to filter out intrinsics candidates, as long as we have
        // some other candidates to suggest.
        let intrinsic_candidates: Vec<_> = candidates
            .extract_if(.., |sugg| {
                let path = path_names_to_string(&sugg.path);
                path.starts_with("core::intrinsics::") || path.starts_with("std::intrinsics::")
            })
            .collect();
        if candidates.is_empty() {
            // Put them back if we have no more candidates to suggest...
            candidates = intrinsic_candidates;
        }
        let crate_def_id = CRATE_DEF_ID.to_def_id();
        if candidates.is_empty() && is_expected(Res::Def(DefKind::Enum, crate_def_id)) {
            let mut enum_candidates: Vec<_> = self
                .r
                .lookup_import_candidates(ident, ns, &self.parent_scope, is_enum_variant)
                .into_iter()
                .map(|suggestion| import_candidate_to_enum_paths(&suggestion))
                .filter(|(_, enum_ty_path)| !enum_ty_path.starts_with("std::prelude::"))
                .collect();
            if !enum_candidates.is_empty() {
                enum_candidates.sort();

                // Contextualize for E0412 "cannot find type", but don't belabor the point
                // (that it's a variant) for E0573 "expected type, found variant".
                let preamble = if res.is_none() {
                    let others = match enum_candidates.len() {
                        1 => String::new(),
                        2 => " and 1 other".to_owned(),
                        n => format!(" and {n} others"),
                    };
                    format!("there is an enum variant `{}`{}; ", enum_candidates[0].0, others)
                } else {
                    String::new()
                };
                let msg = format!("{preamble}try using the variant's enum");

                suggested_candidates.extend(
                    enum_candidates
                        .iter()
                        .map(|(_variant_path, enum_ty_path)| enum_ty_path.clone()),
                );
                err.span_suggestions(
                    span,
                    msg,
                    enum_candidates.into_iter().map(|(_variant_path, enum_ty_path)| enum_ty_path),
                    Applicability::MachineApplicable,
                );
            }
        }

        // Try finding a suitable replacement.
        let typo_sugg = self
            .lookup_typo_candidate(path, following_seg, source.namespace(), is_expected)
            .to_opt_suggestion()
            .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str()));
        if let [segment] = path
            && !matches!(source, PathSource::Delegation)
            && self.self_type_is_available()
        {
            if let Some(candidate) =
                self.lookup_assoc_candidate(ident, ns, is_expected, source.is_call())
            {
                let self_is_available = self.self_value_is_available(segment.ident.span);
                // Account for `Foo { field }` when suggesting `self.field` so we result on
                // `Foo { field: self.field }`.
                let pre = match source {
                    PathSource::Expr(Some(Expr { kind: ExprKind::Struct(expr), .. }))
                        if expr
                            .fields
                            .iter()
                            .any(|f| f.ident == segment.ident && f.is_shorthand) =>
                    {
                        format!("{path_str}: ")
                    }
                    _ => String::new(),
                };
                match candidate {
                    AssocSuggestion::Field(field_span) => {
                        if self_is_available {
                            let source_map = self.r.tcx.sess.source_map();
                            // check if the field is used in a format string, such as `"{x}"`
                            let field_is_format_named_arg = source_map
                                .span_to_source(span, |s, start, _| {
                                    Ok(s.get(start - 1..start) == Some("{"))
                                });
                            if let Ok(true) = field_is_format_named_arg {
                                err.help(
                                    format!("you might have meant to use the available field in a format string: `\"{{}}\", self.{}`", segment.ident.name),
                                );
                            } else {
                                err.span_suggestion_verbose(
                                    span.shrink_to_lo(),
                                    "you might have meant to use the available field",
                                    format!("{pre}self."),
                                    Applicability::MaybeIncorrect,
                                );
                            }
                        } else {
                            err.span_label(field_span, "a field by that name exists in `Self`");
                        }
                    }
                    AssocSuggestion::MethodWithSelf { called } if self_is_available => {
                        let msg = if called {
                            "you might have meant to call the method"
                        } else {
                            "you might have meant to refer to the method"
                        };
                        err.span_suggestion_verbose(
                            span.shrink_to_lo(),
                            msg,
                            "self.",
                            Applicability::MachineApplicable,
                        );
                    }
                    AssocSuggestion::MethodWithSelf { .. }
                    | AssocSuggestion::AssocFn { .. }
                    | AssocSuggestion::AssocConst
                    | AssocSuggestion::AssocType => {
                        err.span_suggestion_verbose(
                            span.shrink_to_lo(),
                            format!("you might have meant to {}", candidate.action()),
                            "Self::",
                            Applicability::MachineApplicable,
                        );
                    }
                }
                self.r.add_typo_suggestion(err, typo_sugg, ident_span);
                return (true, suggested_candidates, candidates);
            }

            // If the first argument in call is `self` suggest calling a method.
            if let Some((call_span, args_span)) = self.call_has_self_arg(source) {
                let mut args_snippet = String::new();
                if let Some(args_span) = args_span
                    && let Ok(snippet) = self.r.tcx.sess.source_map().span_to_snippet(args_span)
                {
                    args_snippet = snippet;
                }

                err.span_suggestion(
                    call_span,
                    format!("try calling `{ident}` as a method"),
                    format!("self.{path_str}({args_snippet})"),
                    Applicability::MachineApplicable,
                );
                return (true, suggested_candidates, candidates);
            }
        }

        // Try context-dependent help if relaxed lookup didn't work.
        if let Some(res) = res {
            if self.smart_resolve_context_dependent_help(
                err,
                span,
                source,
                path,
                res,
                &path_str,
                &base_error.fallback_label,
            ) {
                // We do this to avoid losing a secondary span when we override the main error span.
                self.r.add_typo_suggestion(err, typo_sugg, ident_span);
                return (true, suggested_candidates, candidates);
            }
        }

        // Try to find in last block rib
        if let Some(rib) = &self.last_block_rib {
            for (ident, &res) in &rib.bindings {
                if let Res::Local(_) = res
                    && path.len() == 1
                    && ident.span.eq_ctxt(path[0].ident.span)
                    && ident.name == path[0].ident.name
                {
                    err.span_help(
                        ident.span,
                        format!("the binding `{path_str}` is available in a different scope in the same function"),
                    );
                    return (true, suggested_candidates, candidates);
                }
            }
        }

        if candidates.is_empty() {
            candidates = self.smart_resolve_partial_mod_path_errors(path, following_seg);
        }

        (false, suggested_candidates, candidates)
    }

    fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<(DefId, Ident)> {
        let find_doc_alias_name = |r: &mut Resolver<'ra, '_>, m: Module<'ra>, item_name: Symbol| {
            for resolution in r.resolutions(m).borrow().values() {
                let Some(did) = resolution
                    .borrow()
                    .best_binding()
                    .and_then(|binding| binding.res().opt_def_id())
                else {
                    continue;
                };
                if did.is_local() {
                    // We don't record the doc alias name in the local crate
                    // because the people who write doc alias are usually not
                    // confused by them.
                    continue;
                }
                if is_doc_alias_attrs_contain_symbol(r.tcx.get_attrs(did, sym::doc), item_name) {
                    return Some(did);
                }
            }
            None
        };

        if path.len() == 1 {
            for rib in self.ribs[ns].iter().rev() {
                let item = path[0].ident;
                if let RibKind::Module(module) | RibKind::Block(Some(module)) = rib.kind
                    && let Some(did) = find_doc_alias_name(self.r, module, item.name)
                {
                    return Some((did, item));
                }
            }
        } else {
            // Finds to the last resolved module item in the path
            // and searches doc aliases within that module.
            //
            // Example: For the path `a::b::last_resolved::not_exist::c::d`,
            // we will try to find any item has doc aliases named `not_exist`
            // in `last_resolved` module.
            //
            // - Use `skip(1)` because the final segment must remain unresolved.
            for (idx, seg) in path.iter().enumerate().rev().skip(1) {
                let Some(id) = seg.id else {
                    continue;
                };
                let Some(res) = self.r.partial_res_map.get(&id) else {
                    continue;
                };
                if let Res::Def(DefKind::Mod, module) = res.expect_full_res()
                    && let module = self.r.expect_module(module)
                    && let item = path[idx + 1].ident
                    && let Some(did) = find_doc_alias_name(self.r, module, item.name)
                {
                    return Some((did, item));
                }
                break;
            }
        }
        None
    }

    fn suggest_trait_and_bounds(
        &self,
        err: &mut Diag<'_>,
        source: PathSource<'_, '_, '_>,
        res: Option<Res>,
        span: Span,
        base_error: &BaseError,
    ) -> bool {
        let is_macro =
            base_error.span.from_expansion() && base_error.span.desugaring_kind().is_none();
        let mut fallback = false;

        if let (
            PathSource::Trait(AliasPossibility::Maybe),
            Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)),
            false,
        ) = (source, res, is_macro)
            && let Some(bounds @ [first_bound, .., last_bound]) =
                self.diag_metadata.current_trait_object
        {
            fallback = true;
            let spans: Vec<Span> = bounds
                .iter()
                .map(|bound| bound.span())
                .filter(|&sp| sp != base_error.span)
                .collect();

            let start_span = first_bound.span();
            // `end_span` is the end of the poly trait ref (Foo + 'baz + Bar><)
            let end_span = last_bound.span();
            // `last_bound_span` is the last bound of the poly trait ref (Foo + >'baz< + Bar)
            let last_bound_span = spans.last().cloned().unwrap();
            let mut multi_span: MultiSpan = spans.clone().into();
            for sp in spans {
                let msg = if sp == last_bound_span {
                    format!(
                        "...because of {these} bound{s}",
                        these = pluralize!("this", bounds.len() - 1),
                        s = pluralize!(bounds.len() - 1),
                    )
                } else {
                    String::new()
                };
                multi_span.push_span_label(sp, msg);
            }
            multi_span.push_span_label(base_error.span, "expected this type to be a trait...");
            err.span_help(
                multi_span,
                "`+` is used to constrain a \"trait object\" type with lifetimes or \
                        auto-traits; structs and enums can't be bound in that way",
            );
            if bounds.iter().all(|bound| match bound {
                ast::GenericBound::Outlives(_) | ast::GenericBound::Use(..) => true,
                ast::GenericBound::Trait(tr) => tr.span == base_error.span,
            }) {
                let mut sugg = vec![];
                if base_error.span != start_span {
                    sugg.push((start_span.until(base_error.span), String::new()));
                }
                if base_error.span != end_span {
                    sugg.push((base_error.span.shrink_to_hi().to(end_span), String::new()));
                }

                err.multipart_suggestion(
                    "if you meant to use a type and not a trait here, remove the bounds",
                    sugg,
                    Applicability::MaybeIncorrect,
                );
            }
        }

        fallback |= self.restrict_assoc_type_in_where_clause(span, err);
        fallback
    }

    fn suggest_typo(
        &mut self,
        err: &mut Diag<'_>,
        source: PathSource<'_, 'ast, 'ra>,
        path: &[Segment],
        following_seg: Option<&Segment>,
        span: Span,
        base_error: &BaseError,
        suggested_candidates: FxHashSet<String>,
    ) -> bool {
        let is_expected = &|res| source.is_expected(res);
        let ident_span = path.last().map_or(span, |ident| ident.ident.span);
        let typo_sugg =
            self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected);
        let mut fallback = false;
        let typo_sugg = typo_sugg
            .to_opt_suggestion()
            .filter(|sugg| !suggested_candidates.contains(sugg.candidate.as_str()));
        if !self.r.add_typo_suggestion(err, typo_sugg, ident_span) {
            fallback = true;
            match self.diag_metadata.current_let_binding {
                Some((pat_sp, Some(ty_sp), None))
                    if ty_sp.contains(base_error.span) && base_error.could_be_expr =>
                {
                    err.span_suggestion_short(
                        pat_sp.between(ty_sp),
                        "use `=` if you meant to assign",
                        " = ",
                        Applicability::MaybeIncorrect,
                    );
                }
                _ => {}
            }

            // If the trait has a single item (which wasn't matched by the algorithm), suggest it
            let suggestion = self.get_single_associated_item(path, &source, is_expected);
            self.r.add_typo_suggestion(err, suggestion, ident_span);
        }

        if self.let_binding_suggestion(err, ident_span) {
            fallback = false;
        }

        fallback
    }

    fn suggest_shadowed(
        &mut self,
        err: &mut Diag<'_>,
        source: PathSource<'_, '_, '_>,
        path: &[Segment],
        following_seg: Option<&Segment>,
        span: Span,
    ) -> bool {
        let is_expected = &|res| source.is_expected(res);
        let typo_sugg =
            self.lookup_typo_candidate(path, following_seg, source.namespace(), is_expected);
        let is_in_same_file = &|sp1, sp2| {
            let source_map = self.r.tcx.sess.source_map();
            let file1 = source_map.span_to_filename(sp1);
            let file2 = source_map.span_to_filename(sp2);
            file1 == file2
        };
        // print 'you might have meant' if the candidate is (1) is a shadowed name with
        // accessible definition and (2) either defined in the same crate as the typo
        // (could be in a different file) or introduced in the same file as the typo
        // (could belong to a different crate)
        if let TypoCandidate::Shadowed(res, Some(sugg_span)) = typo_sugg
            && res.opt_def_id().is_some_and(|id| id.is_local() || is_in_same_file(span, sugg_span))
        {
            err.span_label(
                sugg_span,
                format!("you might have meant to refer to this {}", res.descr()),
            );
            return true;
        }
        false
    }

    fn err_code_special_cases(
        &mut self,
        err: &mut Diag<'_>,
        source: PathSource<'_, '_, '_>,
        path: &[Segment],
        span: Span,
    ) {
        if let Some(err_code) = err.code {
            if err_code == E0425 {
                for label_rib in &self.label_ribs {
                    for (label_ident, node_id) in &label_rib.bindings {
                        let ident = path.last().unwrap().ident;
                        if format!("'{ident}") == label_ident.to_string() {
                            err.span_label(label_ident.span, "a label with a similar name exists");
                            if let PathSource::Expr(Some(Expr {
                                kind: ExprKind::Break(None, Some(_)),
                                ..
                            })) = source
                            {
                                err.span_suggestion(
                                    span,
                                    "use the similarly named label",
                                    label_ident.name,
                                    Applicability::MaybeIncorrect,
                                );
                                // Do not lint against unused label when we suggest them.
                                self.diag_metadata.unused_labels.swap_remove(node_id);
                            }
                        }
                    }
                }
            } else if err_code == E0412 {
                if let Some(correct) = Self::likely_rust_type(path) {
                    err.span_suggestion(
                        span,
                        "perhaps you intended to use this type",
                        correct,
                        Applicability::MaybeIncorrect,
                    );
                }
            }
        }
    }

    /// Emit special messages for unresolved `Self` and `self`.
    fn suggest_self_ty(
        &self,
        err: &mut Diag<'_>,
        source: PathSource<'_, '_, '_>,
        path: &[Segment],
        span: Span,
    ) -> bool {
        if !is_self_type(path, source.namespace()) {
            return false;
        }
        err.code(E0411);
        err.span_label(span, "`Self` is only available in impls, traits, and type definitions");
        if let Some(item) = self.diag_metadata.current_item
            && let Some(ident) = item.kind.ident()
        {
            err.span_label(
                ident.span,
                format!("`Self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
            );
        }
        true
    }

    fn suggest_self_value(
        &mut self,
        err: &mut Diag<'_>,
        source: PathSource<'_, '_, '_>,
        path: &[Segment],
        span: Span,
    ) -> bool {
        if !is_self_value(path, source.namespace()) {
            return false;
        }

        debug!("smart_resolve_path_fragment: E0424, source={:?}", source);
        err.code(E0424);
        err.span_label(
            span,
            match source {
                PathSource::Pat => {
                    "`self` value is a keyword and may not be bound to variables or shadowed"
                }
                _ => "`self` value is a keyword only available in methods with a `self` parameter",
            },
        );

        // using `let self` is wrong even if we're not in an associated method or if we're in a macro expansion.
        // So, we should return early if we're in a pattern, see issue #143134.
        if matches!(source, PathSource::Pat) {
            return true;
        }

        let is_assoc_fn = self.self_type_is_available();
        let self_from_macro = "a `self` parameter, but a macro invocation can only \
                               access identifiers it receives from parameters";
        if let Some((fn_kind, fn_span)) = &self.diag_metadata.current_function {
            // The current function has a `self` parameter, but we were unable to resolve
            // a reference to `self`. This can only happen if the `self` identifier we
            // are resolving came from a different hygiene context or a variable binding.
            // But variable binding error is returned early above.
            if fn_kind.decl().inputs.get(0).is_some_and(|p| p.is_self()) {
                err.span_label(*fn_span, format!("this function has {self_from_macro}"));
            } else {
                let doesnt = if is_assoc_fn {
                    let (span, sugg) = fn_kind
                        .decl()
                        .inputs
                        .get(0)
                        .map(|p| (p.span.shrink_to_lo(), "&self, "))
                        .unwrap_or_else(|| {
                            // Try to look for the "(" after the function name, if possible.
                            // This avoids placing the suggestion into the visibility specifier.
                            let span = fn_kind
                                .ident()
                                .map_or(*fn_span, |ident| fn_span.with_lo(ident.span.hi()));
                            (
                                self.r
                                    .tcx
                                    .sess
                                    .source_map()
                                    .span_through_char(span, '(')
                                    .shrink_to_hi(),
                                "&self",
                            )
                        });
                    err.span_suggestion_verbose(
                        span,
                        "add a `self` receiver parameter to make the associated `fn` a method",
                        sugg,
                        Applicability::MaybeIncorrect,
                    );
                    "doesn't"
                } else {
                    "can't"
                };
                if let Some(ident) = fn_kind.ident() {
                    err.span_label(
                        ident.span,
                        format!("this function {doesnt} have a `self` parameter"),
                    );
                }
            }
        } else if let Some(item) = self.diag_metadata.current_item {
            if matches!(item.kind, ItemKind::Delegation(..)) {
                err.span_label(item.span, format!("delegation supports {self_from_macro}"));
            } else {
                let span = if let Some(ident) = item.kind.ident() { ident.span } else { item.span };
                err.span_label(
                    span,
                    format!("`self` not allowed in {} {}", item.kind.article(), item.kind.descr()),
                );
            }
        }
        true
    }

    fn detect_missing_binding_available_from_pattern(
        &self,
        err: &mut Diag<'_>,
        path: &[Segment],
        following_seg: Option<&Segment>,
    ) {
        let [segment] = path else { return };
        let None = following_seg else { return };
        for rib in self.ribs[ValueNS].iter().rev() {
            let patterns_with_skipped_bindings = self.r.tcx.with_stable_hashing_context(|hcx| {
                rib.patterns_with_skipped_bindings.to_sorted(&hcx, true)
            });
            for (def_id, spans) in patterns_with_skipped_bindings {
                if let DefKind::Struct | DefKind::Variant = self.r.tcx.def_kind(*def_id)
                    && let Some(fields) = self.r.field_idents(*def_id)
                {
                    for field in fields {
                        if field.name == segment.ident.name {
                            if spans.iter().all(|(_, had_error)| had_error.is_err()) {
                                // This resolution error will likely be fixed by fixing a
                                // syntax error in a pattern, so it is irrelevant to the user.
                                let multispan: MultiSpan =
                                    spans.iter().map(|(s, _)| *s).collect::<Vec<_>>().into();
                                err.span_note(
                                    multispan,
                                    "this pattern had a recovered parse error which likely lost \
                                     the expected fields",
                                );
                                err.downgrade_to_delayed_bug();
                            }
                            let ty = self.r.tcx.item_name(*def_id);
                            for (span, _) in spans {
                                err.span_label(
                                    *span,
                                    format!(
                                        "this pattern doesn't include `{field}`, which is \
                                         available in `{ty}`",
                                    ),
                                );
                            }
                        }
                    }
                }
            }
        }
    }

    fn suggest_at_operator_in_slice_pat_with_range(&self, err: &mut Diag<'_>, path: &[Segment]) {
        let Some(pat) = self.diag_metadata.current_pat else { return };
        let (bound, side, range) = match &pat.kind {
            ast::PatKind::Range(Some(bound), None, range) => (bound, Side::Start, range),
            ast::PatKind::Range(None, Some(bound), range) => (bound, Side::End, range),
            _ => return,
        };
        if let ExprKind::Path(None, range_path) = &bound.kind
            && let [segment] = &range_path.segments[..]
            && let [s] = path
            && segment.ident == s.ident
            && segment.ident.span.eq_ctxt(range.span)
        {
            // We've encountered `[first, rest..]` (#88404) or `[first, ..rest]` (#120591)
            // where the user might have meant `[first, rest @ ..]`.
            let (span, snippet) = match side {
                Side::Start => (segment.ident.span.between(range.span), " @ ".into()),
                Side::End => (range.span.to(segment.ident.span), format!("{} @ ..", segment.ident)),
            };
            err.subdiagnostic(errors::UnexpectedResUseAtOpInSlicePatWithRangeSugg {
                span,
                ident: segment.ident,
                snippet,
            });
        }

        enum Side {
            Start,
            End,
        }
    }

    fn suggest_swapping_misplaced_self_ty_and_trait(
        &mut self,
        err: &mut Diag<'_>,
        source: PathSource<'_, 'ast, 'ra>,
        res: Option<Res>,
        span: Span,
    ) {
        if let Some((trait_ref, self_ty)) =
            self.diag_metadata.currently_processing_impl_trait.clone()
            && let TyKind::Path(_, self_ty_path) = &self_ty.kind
            && let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
                self.resolve_path(&Segment::from_path(self_ty_path), Some(TypeNS), None, source)
            && let ModuleKind::Def(DefKind::Trait, ..) = module.kind
            && trait_ref.path.span == span
            && let PathSource::Trait(_) = source
            && let Some(Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _)) = res
            && let Ok(self_ty_str) = self.r.tcx.sess.source_map().span_to_snippet(self_ty.span)
            && let Ok(trait_ref_str) =
                self.r.tcx.sess.source_map().span_to_snippet(trait_ref.path.span)
        {
            err.multipart_suggestion(
                    "`impl` items mention the trait being implemented first and the type it is being implemented for second",
                    vec![(trait_ref.path.span, self_ty_str), (self_ty.span, trait_ref_str)],
                    Applicability::MaybeIncorrect,
                );
        }
    }

    fn explain_functions_in_pattern(
        &self,
        err: &mut Diag<'_>,
        res: Option<Res>,
        source: PathSource<'_, '_, '_>,
    ) {
        let PathSource::TupleStruct(_, _) = source else { return };
        let Some(Res::Def(DefKind::Fn, _)) = res else { return };
        err.primary_message("expected a pattern, found a function call");
        err.note("function calls are not allowed in patterns: <https://doc.rust-lang.org/book/ch19-00-patterns.html>");
    }

    fn suggest_changing_type_to_const_param(
        &self,
        err: &mut Diag<'_>,
        res: Option<Res>,
        source: PathSource<'_, '_, '_>,
        span: Span,
    ) {
        let PathSource::Trait(_) = source else { return };

        // We don't include `DefKind::Str` and `DefKind::AssocTy` as they can't be reached here anyway.
        let applicability = match res {
            Some(Res::PrimTy(PrimTy::Int(_) | PrimTy::Uint(_) | PrimTy::Bool | PrimTy::Char)) => {
                Applicability::MachineApplicable
            }
            // FIXME(const_generics): Add `DefKind::TyParam` and `SelfTyParam` once we support generic
            // const generics. Of course, `Struct` and `Enum` may contain ty params, too, but the
            // benefits of including them here outweighs the small number of false positives.
            Some(Res::Def(DefKind::Struct | DefKind::Enum, _))
                if self.r.tcx.features().adt_const_params() =>
            {
                Applicability::MaybeIncorrect
            }
            _ => return,
        };

        let Some(item) = self.diag_metadata.current_item else { return };
        let Some(generics) = item.kind.generics() else { return };

        let param = generics.params.iter().find_map(|param| {
            // Only consider type params with exactly one trait bound.
            if let [bound] = &*param.bounds
                && let ast::GenericBound::Trait(tref) = bound
                && tref.modifiers == ast::TraitBoundModifiers::NONE
                && tref.span == span
                && param.ident.span.eq_ctxt(span)
            {
                Some(param.ident.span)
            } else {
                None
            }
        });

        if let Some(param) = param {
            err.subdiagnostic(errors::UnexpectedResChangeTyToConstParamSugg {
                span: param.shrink_to_lo(),
                applicability,
            });
        }
    }

    fn suggest_pattern_match_with_let(
        &self,
        err: &mut Diag<'_>,
        source: PathSource<'_, '_, '_>,
        span: Span,
    ) -> bool {
        if let PathSource::Expr(_) = source
            && let Some(Expr { span: expr_span, kind: ExprKind::Assign(lhs, _, _), .. }) =
                self.diag_metadata.in_if_condition
        {
            // Icky heuristic so we don't suggest:
            // `if (i + 2) = 2` => `if let (i + 2) = 2` (approximately pattern)
            // `if 2 = i` => `if let 2 = i` (lhs needs to contain error span)
            if lhs.is_approximately_pattern() && lhs.span.contains(span) {
                err.span_suggestion_verbose(
                    expr_span.shrink_to_lo(),
                    "you might have meant to use pattern matching",
                    "let ",
                    Applicability::MaybeIncorrect,
                );
                return true;
            }
        }
        false
    }

    fn get_single_associated_item(
        &mut self,
        path: &[Segment],
        source: &PathSource<'_, 'ast, 'ra>,
        filter_fn: &impl Fn(Res) -> bool,
    ) -> Option<TypoSuggestion> {
        if let crate::PathSource::TraitItem(_, _) = source {
            let mod_path = &path[..path.len() - 1];
            if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
                self.resolve_path(mod_path, None, None, *source)
            {
                let targets: Vec<_> = self
                    .r
                    .resolutions(module)
                    .borrow()
                    .iter()
                    .filter_map(|(key, resolution)| {
                        resolution
                            .borrow()
                            .best_binding()
                            .map(|binding| binding.res())
                            .and_then(|res| if filter_fn(res) { Some((*key, res)) } else { None })
                    })
                    .collect();
                if let [target] = targets.as_slice() {
                    return Some(TypoSuggestion::single_item_from_ident(
                        target.0.ident.0,
                        target.1,
                    ));
                }
            }
        }
        None
    }

    /// Given `where <T as Bar>::Baz: String`, suggest `where T: Bar<Baz = String>`.
    fn restrict_assoc_type_in_where_clause(&self, span: Span, err: &mut Diag<'_>) -> bool {
        // Detect that we are actually in a `where` predicate.
        let (bounded_ty, bounds, where_span) = if let Some(ast::WherePredicate {
            kind:
                ast::WherePredicateKind::BoundPredicate(ast::WhereBoundPredicate {
                    bounded_ty,
                    bound_generic_params,
                    bounds,
                }),
            span,
            ..
        }) = self.diag_metadata.current_where_predicate
        {
            if !bound_generic_params.is_empty() {
                return false;
            }
            (bounded_ty, bounds, span)
        } else {
            return false;
        };

        // Confirm that the target is an associated type.
        let (ty, _, path) = if let ast::TyKind::Path(Some(qself), path) = &bounded_ty.kind {
            // use this to verify that ident is a type param.
            let Some(partial_res) = self.r.partial_res_map.get(&bounded_ty.id) else {
                return false;
            };
            if !matches!(
                partial_res.full_res(),
                Some(hir::def::Res::Def(hir::def::DefKind::AssocTy, _))
            ) {
                return false;
            }
            (&qself.ty, qself.position, path)
        } else {
            return false;
        };

        let peeled_ty = ty.peel_refs();
        if let ast::TyKind::Path(None, type_param_path) = &peeled_ty.kind {
            // Confirm that the `SelfTy` is a type parameter.
            let Some(partial_res) = self.r.partial_res_map.get(&peeled_ty.id) else {
                return false;
            };
            if !matches!(
                partial_res.full_res(),
                Some(hir::def::Res::Def(hir::def::DefKind::TyParam, _))
            ) {
                return false;
            }
            if let (
                [ast::PathSegment { args: None, .. }],
                [ast::GenericBound::Trait(poly_trait_ref)],
            ) = (&type_param_path.segments[..], &bounds[..])
                && poly_trait_ref.modifiers == ast::TraitBoundModifiers::NONE
            {
                if let [ast::PathSegment { ident, args: None, .. }] =
                    &poly_trait_ref.trait_ref.path.segments[..]
                {
                    if ident.span == span {
                        let Some(new_where_bound_predicate) =
                            mk_where_bound_predicate(path, poly_trait_ref, ty)
                        else {
                            return false;
                        };
                        err.span_suggestion_verbose(
                            *where_span,
                            format!("constrain the associated type to `{ident}`"),
                            where_bound_predicate_to_string(&new_where_bound_predicate),
                            Applicability::MaybeIncorrect,
                        );
                    }
                    return true;
                }
            }
        }
        false
    }

    /// Check if the source is call expression and the first argument is `self`. If true,
    /// return the span of whole call and the span for all arguments expect the first one (`self`).
    fn call_has_self_arg(&self, source: PathSource<'_, '_, '_>) -> Option<(Span, Option<Span>)> {
        let mut has_self_arg = None;
        if let PathSource::Expr(Some(parent)) = source
            && let ExprKind::Call(_, args) = &parent.kind
            && !args.is_empty()
        {
            let mut expr_kind = &args[0].kind;
            loop {
                match expr_kind {
                    ExprKind::Path(_, arg_name) if arg_name.segments.len() == 1 => {
                        if arg_name.segments[0].ident.name == kw::SelfLower {
                            let call_span = parent.span;
                            let tail_args_span = if args.len() > 1 {
                                Some(Span::new(
                                    args[1].span.lo(),
                                    args.last().unwrap().span.hi(),
                                    call_span.ctxt(),
                                    None,
                                ))
                            } else {
                                None
                            };
                            has_self_arg = Some((call_span, tail_args_span));
                        }
                        break;
                    }
                    ExprKind::AddrOf(_, _, expr) => expr_kind = &expr.kind,
                    _ => break,
                }
            }
        }
        has_self_arg
    }

    fn followed_by_brace(&self, span: Span) -> (bool, Option<Span>) {
        // HACK(estebank): find a better way to figure out that this was a
        // parser issue where a struct literal is being used on an expression
        // where a brace being opened means a block is being started. Look
        // ahead for the next text to see if `span` is followed by a `{`.
        let sm = self.r.tcx.sess.source_map();
        if let Some(followed_brace_span) = sm.span_look_ahead(span, "{", Some(50)) {
            // In case this could be a struct literal that needs to be surrounded
            // by parentheses, find the appropriate span.
            let close_brace_span = sm.span_look_ahead(followed_brace_span, "}", Some(50));
            let closing_brace = close_brace_span.map(|sp| span.to(sp));
            (true, closing_brace)
        } else {
            (false, None)
        }
    }

    /// Provides context-dependent help for errors reported by the `smart_resolve_path_fragment`
    /// function.
    /// Returns `true` if able to provide context-dependent help.
    fn smart_resolve_context_dependent_help(
        &mut self,
        err: &mut Diag<'_>,
        span: Span,
        source: PathSource<'_, '_, '_>,
        path: &[Segment],
        res: Res,
        path_str: &str,
        fallback_label: &str,
    ) -> bool {
        let ns = source.namespace();
        let is_expected = &|res| source.is_expected(res);

        let path_sep = |this: &Self, err: &mut Diag<'_>, expr: &Expr, kind: DefKind| {
            const MESSAGE: &str = "use the path separator to refer to an item";

            let (lhs_span, rhs_span) = match &expr.kind {
                ExprKind::Field(base, ident) => (base.span, ident.span),
                ExprKind::MethodCall(box MethodCall { receiver, span, .. }) => {
                    (receiver.span, *span)
                }
                _ => return false,
            };

            if lhs_span.eq_ctxt(rhs_span) {
                err.span_suggestion_verbose(
                    lhs_span.between(rhs_span),
                    MESSAGE,
                    "::",
                    Applicability::MaybeIncorrect,
                );
                true
            } else if matches!(kind, DefKind::Struct | DefKind::TyAlias)
                && let Some(lhs_source_span) = lhs_span.find_ancestor_inside(expr.span)
                && let Ok(snippet) = this.r.tcx.sess.source_map().span_to_snippet(lhs_source_span)
            {
                // The LHS is a type that originates from a macro call.
                // We have to add angle brackets around it.

                err.span_suggestion_verbose(
                    lhs_source_span.until(rhs_span),
                    MESSAGE,
                    format!("<{snippet}>::"),
                    Applicability::MaybeIncorrect,
                );
                true
            } else {
                // Either we were unable to obtain the source span / the snippet or
                // the LHS originates from a macro call and it is not a type and thus
                // there is no way to replace `.` with `::` and still somehow suggest
                // valid Rust code.

                false
            }
        };

        let find_span = |source: &PathSource<'_, '_, '_>, err: &mut Diag<'_>| {
            match source {
                PathSource::Expr(Some(Expr { span, kind: ExprKind::Call(_, _), .. }))
                | PathSource::TupleStruct(span, _) => {
                    // We want the main underline to cover the suggested code as well for
                    // cleaner output.
                    err.span(*span);
                    *span
                }
                _ => span,
            }
        };

        let bad_struct_syntax_suggestion = |this: &mut Self, err: &mut Diag<'_>, def_id: DefId| {
            let (followed_by_brace, closing_brace) = this.followed_by_brace(span);

            match source {
                PathSource::Expr(Some(
                    parent @ Expr { kind: ExprKind::Field(..) | ExprKind::MethodCall(..), .. },
                )) if path_sep(this, err, parent, DefKind::Struct) => {}
                PathSource::Expr(
                    None
                    | Some(Expr {
                        kind:
                            ExprKind::Path(..)
                            | ExprKind::Binary(..)
                            | ExprKind::Unary(..)
                            | ExprKind::If(..)
                            | ExprKind::While(..)
                            | ExprKind::ForLoop { .. }
                            | ExprKind::Match(..),
                        ..
                    }),
                ) if followed_by_brace => {
                    if let Some(sp) = closing_brace {
                        err.span_label(span, fallback_label.to_string());
                        err.multipart_suggestion(
                            "surround the struct literal with parentheses",
                            vec![
                                (sp.shrink_to_lo(), "(".to_string()),
                                (sp.shrink_to_hi(), ")".to_string()),
                            ],
                            Applicability::MaybeIncorrect,
                        );
                    } else {
                        err.span_label(
                            span, // Note the parentheses surrounding the suggestion below
                            format!(
                                "you might want to surround a struct literal with parentheses: \
                                 `({path_str} {{ /* fields */ }})`?"
                            ),
                        );
                    }
                }
                PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
                    let span = find_span(&source, err);
                    err.span_label(this.r.def_span(def_id), format!("`{path_str}` defined here"));

                    let (tail, descr, applicability, old_fields) = match source {
                        PathSource::Pat => ("", "pattern", Applicability::MachineApplicable, None),
                        PathSource::TupleStruct(_, args) => (
                            "",
                            "pattern",
                            Applicability::MachineApplicable,
                            Some(
                                args.iter()
                                    .map(|a| this.r.tcx.sess.source_map().span_to_snippet(*a).ok())
                                    .collect::<Vec<Option<String>>>(),
                            ),
                        ),
                        _ => (": val", "literal", Applicability::HasPlaceholders, None),
                    };

                    if !this.has_private_fields(def_id) {
                        // If the fields of the type are private, we shouldn't be suggesting using
                        // the struct literal syntax at all, as that will cause a subsequent error.
                        let fields = this.r.field_idents(def_id);
                        let has_fields = fields.as_ref().is_some_and(|f| !f.is_empty());

                        if let PathSource::Expr(Some(Expr {
                            kind: ExprKind::Call(path, args),
                            span,
                            ..
                        })) = source
                            && !args.is_empty()
                            && let Some(fields) = &fields
                            && args.len() == fields.len()
                        // Make sure we have same number of args as fields
                        {
                            let path_span = path.span;
                            let mut parts = Vec::new();

                            // Start with the opening brace
                            parts.push((
                                path_span.shrink_to_hi().until(args[0].span),
                                "{".to_owned(),
                            ));

                            for (field, arg) in fields.iter().zip(args.iter()) {
                                // Add the field name before the argument
                                parts.push((arg.span.shrink_to_lo(), format!("{}: ", field)));
                            }

                            // Add the closing brace
                            parts.push((
                                args.last().unwrap().span.shrink_to_hi().until(span.shrink_to_hi()),
                                "}".to_owned(),
                            ));

                            err.multipart_suggestion_verbose(
                                format!("use struct {descr} syntax instead of calling"),
                                parts,
                                applicability,
                            );
                        } else {
                            let (fields, applicability) = match fields {
                                Some(fields) => {
                                    let fields = if let Some(old_fields) = old_fields {
                                        fields
                                            .iter()
                                            .enumerate()
                                            .map(|(idx, new)| (new, old_fields.get(idx)))
                                            .map(|(new, old)| {
                                                if let Some(Some(old)) = old
                                                    && new.as_str() != old
                                                {
                                                    format!("{new}: {old}")
                                                } else {
                                                    new.to_string()
                                                }
                                            })
                                            .collect::<Vec<String>>()
                                    } else {
                                        fields
                                            .iter()
                                            .map(|f| format!("{f}{tail}"))
                                            .collect::<Vec<String>>()
                                    };

                                    (fields.join(", "), applicability)
                                }
                                None => {
                                    ("/* fields */".to_string(), Applicability::HasPlaceholders)
                                }
                            };
                            let pad = if has_fields { " " } else { "" };
                            err.span_suggestion(
                                span,
                                format!("use struct {descr} syntax instead"),
                                format!("{path_str} {{{pad}{fields}{pad}}}"),
                                applicability,
                            );
                        }
                    }
                    if let PathSource::Expr(Some(Expr {
                        kind: ExprKind::Call(path, args),
                        span: call_span,
                        ..
                    })) = source
                    {
                        this.suggest_alternative_construction_methods(
                            def_id,
                            err,
                            path.span,
                            *call_span,
                            &args[..],
                        );
                    }
                }
                _ => {
                    err.span_label(span, fallback_label.to_string());
                }
            }
        };

        match (res, source) {
            (
                Res::Def(DefKind::Macro(kinds), def_id),
                PathSource::Expr(Some(Expr {
                    kind: ExprKind::Index(..) | ExprKind::Call(..), ..
                }))
                | PathSource::Struct(_),
            ) if kinds.contains(MacroKinds::BANG) => {
                // Don't suggest macro if it's unstable.
                let suggestable = def_id.is_local()
                    || self.r.tcx.lookup_stability(def_id).is_none_or(|s| s.is_stable());

                err.span_label(span, fallback_label.to_string());

                // Don't suggest `!` for a macro invocation if there are generic args
                if path
                    .last()
                    .is_some_and(|segment| !segment.has_generic_args && !segment.has_lifetime_args)
                    && suggestable
                {
                    err.span_suggestion_verbose(
                        span.shrink_to_hi(),
                        "use `!` to invoke the macro",
                        "!",
                        Applicability::MaybeIncorrect,
                    );
                }

                if path_str == "try" && span.is_rust_2015() {
                    err.note("if you want the `try` keyword, you need Rust 2018 or later");
                }
            }
            (Res::Def(DefKind::Macro(kinds), _), _) if kinds.contains(MacroKinds::BANG) => {
                err.span_label(span, fallback_label.to_string());
            }
            (Res::Def(DefKind::TyAlias, def_id), PathSource::Trait(_)) => {
                err.span_label(span, "type aliases cannot be used as traits");
                if self.r.tcx.sess.is_nightly_build() {
                    let msg = "you might have meant to use `#![feature(trait_alias)]` instead of a \
                               `type` alias";
                    let span = self.r.def_span(def_id);
                    if let Ok(snip) = self.r.tcx.sess.source_map().span_to_snippet(span) {
                        // The span contains a type alias so we should be able to
                        // replace `type` with `trait`.
                        let snip = snip.replacen("type", "trait", 1);
                        err.span_suggestion(span, msg, snip, Applicability::MaybeIncorrect);
                    } else {
                        err.span_help(span, msg);
                    }
                }
            }
            (
                Res::Def(kind @ (DefKind::Mod | DefKind::Trait | DefKind::TyAlias), _),
                PathSource::Expr(Some(parent)),
            ) if path_sep(self, err, parent, kind) => {
                return true;
            }
            (
                Res::Def(DefKind::Enum, def_id),
                PathSource::TupleStruct(..) | PathSource::Expr(..),
            ) => {
                self.suggest_using_enum_variant(err, source, def_id, span);
            }
            (Res::Def(DefKind::Struct, def_id), source) if ns == ValueNS => {
                let struct_ctor = match def_id.as_local() {
                    Some(def_id) => self.r.struct_constructors.get(&def_id).cloned(),
                    None => {
                        let ctor = self.r.cstore().ctor_untracked(def_id);
                        ctor.map(|(ctor_kind, ctor_def_id)| {
                            let ctor_res =
                                Res::Def(DefKind::Ctor(CtorOf::Struct, ctor_kind), ctor_def_id);
                            let ctor_vis = self.r.tcx.visibility(ctor_def_id);
                            let field_visibilities = self
                                .r
                                .tcx
                                .associated_item_def_ids(def_id)
                                .iter()
                                .map(|field_id| self.r.tcx.visibility(field_id))
                                .collect();
                            (ctor_res, ctor_vis, field_visibilities)
                        })
                    }
                };

                let (ctor_def, ctor_vis, fields) = if let Some(struct_ctor) = struct_ctor {
                    if let PathSource::Expr(Some(parent)) = source
                        && let ExprKind::Field(..) | ExprKind::MethodCall(..) = parent.kind
                    {
                        bad_struct_syntax_suggestion(self, err, def_id);
                        return true;
                    }
                    struct_ctor
                } else {
                    bad_struct_syntax_suggestion(self, err, def_id);
                    return true;
                };

                let update_message =
                    |this: &mut Self, err: &mut Diag<'_>, source: &PathSource<'_, '_, '_>| {
                        match source {
                            // e.g. `if let Enum::TupleVariant(field1, field2) = _`
                            PathSource::TupleStruct(_, pattern_spans) => {
                                err.primary_message(
                                "cannot match against a tuple struct which contains private fields",
                            );

                                // Use spans of the tuple struct pattern.
                                Some(Vec::from(*pattern_spans))
                            }
                            // e.g. `let _ = Enum::TupleVariant(field1, field2);`
                            PathSource::Expr(Some(Expr {
                                kind: ExprKind::Call(path, args),
                                span: call_span,
                                ..
                            })) => {
                                err.primary_message(
                                "cannot initialize a tuple struct which contains private fields",
                            );
                                this.suggest_alternative_construction_methods(
                                    def_id,
                                    err,
                                    path.span,
                                    *call_span,
                                    &args[..],
                                );
                                // Use spans of the tuple struct definition.
                                this.r
                                    .field_idents(def_id)
                                    .map(|fields| fields.iter().map(|f| f.span).collect::<Vec<_>>())
                            }
                            _ => None,
                        }
                    };
                let is_accessible = self.r.is_accessible_from(ctor_vis, self.parent_scope.module);
                if let Some(use_span) = self.r.inaccessible_ctor_reexport.get(&span)
                    && is_accessible
                {
                    err.span_note(
                        *use_span,
                        "the type is accessed through this re-export, but the type's constructor \
                         is not visible in this import's scope due to private fields",
                    );
                    if is_accessible
                        && fields
                            .iter()
                            .all(|vis| self.r.is_accessible_from(*vis, self.parent_scope.module))
                    {
                        err.span_suggestion_verbose(
                            span,
                            "the type can be constructed directly, because its fields are \
                             available from the current scope",
                            // Using `tcx.def_path_str` causes the compiler to hang.
                            // We don't need to handle foreign crate types because in that case you
                            // can't access the ctor either way.
                            format!(
                                "crate{}", // The method already has leading `::`.
                                self.r.tcx.def_path(def_id).to_string_no_crate_verbose(),
                            ),
                            Applicability::MachineApplicable,
                        );
                    }
                    update_message(self, err, &source);
                }
                if !is_expected(ctor_def) || is_accessible {
                    return true;
                }

                let field_spans = update_message(self, err, &source);

                if let Some(spans) =
                    field_spans.filter(|spans| spans.len() > 0 && fields.len() == spans.len())
                {
                    let non_visible_spans: Vec<Span> = iter::zip(&fields, &spans)
                        .filter(|(vis, _)| {
                            !self.r.is_accessible_from(**vis, self.parent_scope.module)
                        })
                        .map(|(_, span)| *span)
                        .collect();

                    if non_visible_spans.len() > 0 {
                        if let Some(fields) = self.r.field_visibility_spans.get(&def_id) {
                            err.multipart_suggestion_verbose(
                                format!(
                                    "consider making the field{} publicly accessible",
                                    pluralize!(fields.len())
                                ),
                                fields.iter().map(|span| (*span, "pub ".to_string())).collect(),
                                Applicability::MaybeIncorrect,
                            );
                        }

                        let mut m: MultiSpan = non_visible_spans.clone().into();
                        non_visible_spans
                            .into_iter()
                            .for_each(|s| m.push_span_label(s, "private field"));
                        err.span_note(m, "constructor is not visible here due to private fields");
                    }

                    return true;
                }

                err.span_label(span, "constructor is not visible here due to private fields");
            }
            (Res::Def(DefKind::Union | DefKind::Variant, def_id), _) if ns == ValueNS => {
                bad_struct_syntax_suggestion(self, err, def_id);
            }
            (Res::Def(DefKind::Ctor(_, CtorKind::Const), def_id), _) if ns == ValueNS => {
                match source {
                    PathSource::Expr(_) | PathSource::TupleStruct(..) | PathSource::Pat => {
                        let span = find_span(&source, err);
                        err.span_label(
                            self.r.def_span(def_id),
                            format!("`{path_str}` defined here"),
                        );
                        err.span_suggestion(
                            span,
                            "use this syntax instead",
                            path_str,
                            Applicability::MaybeIncorrect,
                        );
                    }
                    _ => return false,
                }
            }
            (Res::Def(DefKind::Ctor(_, CtorKind::Fn), ctor_def_id), _) if ns == ValueNS => {
                let def_id = self.r.tcx.parent(ctor_def_id);
                err.span_label(self.r.def_span(def_id), format!("`{path_str}` defined here"));
                let fields = self.r.field_idents(def_id).map_or_else(
                    || "/* fields */".to_string(),
                    |field_ids| vec!["_"; field_ids.len()].join(", "),
                );
                err.span_suggestion(
                    span,
                    "use the tuple variant pattern syntax instead",
                    format!("{path_str}({fields})"),
                    Applicability::HasPlaceholders,
                );
            }
            (Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }, _) if ns == ValueNS => {
                err.span_label(span, fallback_label.to_string());
                err.note("can't use `Self` as a constructor, you must use the implemented struct");
            }
            (
                Res::Def(DefKind::TyAlias | DefKind::AssocTy, _),
                PathSource::TraitItem(ValueNS, PathSource::TupleStruct(whole, args)),
            ) => {
                err.note("can't use a type alias as tuple pattern");

                let mut suggestion = Vec::new();

                if let &&[first, ..] = args
                    && let &&[.., last] = args
                {
                    suggestion.extend([
                        // "0: " has to be included here so that the fix is machine applicable.
                        //
                        // If this would only add " { " and then the code below add "0: ",
                        // rustfix would crash, because end of this suggestion is the same as start
                        // of the suggestion below. Thus, we have to merge these...
                        (span.between(first), " { 0: ".to_owned()),
                        (last.between(whole.shrink_to_hi()), " }".to_owned()),
                    ]);

                    suggestion.extend(
                        args.iter()
                            .enumerate()
                            .skip(1) // See above
                            .map(|(index, &arg)| (arg.shrink_to_lo(), format!("{index}: "))),
                    )
                } else {
                    suggestion.push((span.between(whole.shrink_to_hi()), " {}".to_owned()));
                }

                err.multipart_suggestion(
                    "use struct pattern instead",
                    suggestion,
                    Applicability::MachineApplicable,
                );
            }
            (
                Res::Def(DefKind::TyAlias | DefKind::AssocTy, _),
                PathSource::TraitItem(
                    ValueNS,
                    PathSource::Expr(Some(ast::Expr {
                        span: whole,
                        kind: ast::ExprKind::Call(_, args),
                        ..
                    })),
                ),
            ) => {
                err.note("can't use a type alias as a constructor");

                let mut suggestion = Vec::new();

                if let [first, ..] = &**args
                    && let [.., last] = &**args
                {
                    suggestion.extend([
                        // "0: " has to be included here so that the fix is machine applicable.
                        //
                        // If this would only add " { " and then the code below add "0: ",
                        // rustfix would crash, because end of this suggestion is the same as start
                        // of the suggestion below. Thus, we have to merge these...
                        (span.between(first.span), " { 0: ".to_owned()),
                        (last.span.between(whole.shrink_to_hi()), " }".to_owned()),
                    ]);

                    suggestion.extend(
                        args.iter()
                            .enumerate()
                            .skip(1) // See above
                            .map(|(index, arg)| (arg.span.shrink_to_lo(), format!("{index}: "))),
                    )
                } else {
                    suggestion.push((span.between(whole.shrink_to_hi()), " {}".to_owned()));
                }

                err.multipart_suggestion(
                    "use struct expression instead",
                    suggestion,
                    Applicability::MachineApplicable,
                );
            }
            _ => return false,
        }
        true
    }

    fn suggest_alternative_construction_methods(
        &mut self,
        def_id: DefId,
        err: &mut Diag<'_>,
        path_span: Span,
        call_span: Span,
        args: &[Box<Expr>],
    ) {
        if def_id.is_local() {
            // Doing analysis on local `DefId`s would cause infinite recursion.
            return;
        }
        // Look at all the associated functions without receivers in the type's
        // inherent impls to look for builders that return `Self`
        let mut items = self
            .r
            .tcx
            .inherent_impls(def_id)
            .iter()
            .flat_map(|i| self.r.tcx.associated_items(i).in_definition_order())
            // Only assoc fn with no receivers.
            .filter(|item| item.is_fn() && !item.is_method())
            .filter_map(|item| {
                // Only assoc fns that return `Self`
                let fn_sig = self.r.tcx.fn_sig(item.def_id).skip_binder();
                // Don't normalize the return type, because that can cause cycle errors.
                let ret_ty = fn_sig.output().skip_binder();
                let ty::Adt(def, _args) = ret_ty.kind() else {
                    return None;
                };
                let input_len = fn_sig.inputs().skip_binder().len();
                if def.did() != def_id {
                    return None;
                }
                let name = item.name();
                let order = !name.as_str().starts_with("new");
                Some((order, name, input_len))
            })
            .collect::<Vec<_>>();
        items.sort_by_key(|(order, _, _)| *order);
        let suggestion = |name, args| {
            format!(
                "::{name}({})",
                std::iter::repeat("_").take(args).collect::<Vec<_>>().join(", ")
            )
        };
        match &items[..] {
            [] => {}
            [(_, name, len)] if *len == args.len() => {
                err.span_suggestion_verbose(
                    path_span.shrink_to_hi(),
                    format!("you might have meant to use the `{name}` associated function",),
                    format!("::{name}"),
                    Applicability::MaybeIncorrect,
                );
            }
            [(_, name, len)] => {
                err.span_suggestion_verbose(
                    path_span.shrink_to_hi().with_hi(call_span.hi()),
                    format!("you might have meant to use the `{name}` associated function",),
                    suggestion(name, *len),
                    Applicability::MaybeIncorrect,
                );
            }
            _ => {
                err.span_suggestions_with_style(
                    path_span.shrink_to_hi().with_hi(call_span.hi()),
                    "you might have meant to use an associated function to build this type",
                    items.iter().map(|(_, name, len)| suggestion(name, *len)),
                    Applicability::MaybeIncorrect,
                    SuggestionStyle::ShowAlways,
                );
            }
        }
        // We'd ideally use `type_implements_trait` but don't have access to
        // the trait solver here. We can't use `get_diagnostic_item` or
        // `all_traits` in resolve either. So instead we abuse the import
        // suggestion machinery to get `std::default::Default` and perform some
        // checks to confirm that we got *only* that trait. We then see if the
        // Adt we have has a direct implementation of `Default`. If so, we
        // provide a structured suggestion.
        let default_trait = self
            .r
            .lookup_import_candidates(
                Ident::with_dummy_span(sym::Default),
                Namespace::TypeNS,
                &self.parent_scope,
                &|res: Res| matches!(res, Res::Def(DefKind::Trait, _)),
            )
            .iter()
            .filter_map(|candidate| candidate.did)
            .find(|did| {
                self.r
                    .tcx
                    .get_attrs(*did, sym::rustc_diagnostic_item)
                    .any(|attr| attr.value_str() == Some(sym::Default))
            });
        let Some(default_trait) = default_trait else {
            return;
        };
        if self
            .r
            .extern_crate_map
            .items()
            // FIXME: This doesn't include impls like `impl Default for String`.
            .flat_map(|(_, crate_)| self.r.tcx.implementations_of_trait((*crate_, default_trait)))
            .filter_map(|(_, simplified_self_ty)| *simplified_self_ty)
            .filter_map(|simplified_self_ty| match simplified_self_ty {
                SimplifiedType::Adt(did) => Some(did),
                _ => None,
            })
            .any(|did| did == def_id)
        {
            err.multipart_suggestion(
                "consider using the `Default` trait",
                vec![
                    (path_span.shrink_to_lo(), "<".to_string()),
                    (
                        path_span.shrink_to_hi().with_hi(call_span.hi()),
                        " as std::default::Default>::default()".to_string(),
                    ),
                ],
                Applicability::MaybeIncorrect,
            );
        }
    }

    fn has_private_fields(&self, def_id: DefId) -> bool {
        let fields = match def_id.as_local() {
            Some(def_id) => self.r.struct_constructors.get(&def_id).cloned().map(|(_, _, f)| f),
            None => Some(
                self.r
                    .tcx
                    .associated_item_def_ids(def_id)
                    .iter()
                    .map(|field_id| self.r.tcx.visibility(field_id))
                    .collect(),
            ),
        };

        fields.is_some_and(|fields| {
            fields.iter().any(|vis| !self.r.is_accessible_from(*vis, self.parent_scope.module))
        })
    }

    /// Given the target `ident` and `kind`, search for the similarly named associated item
    /// in `self.current_trait_ref`.
    pub(crate) fn find_similarly_named_assoc_item(
        &mut self,
        ident: Symbol,
        kind: &AssocItemKind,
    ) -> Option<Symbol> {
        let (module, _) = self.current_trait_ref.as_ref()?;
        if ident == kw::Underscore {
            // We do nothing for `_`.
            return None;
        }

        let targets = self
            .r
            .resolutions(*module)
            .borrow()
            .iter()
            .filter_map(|(key, res)| {
                res.borrow().best_binding().map(|binding| (key, binding.res()))
            })
            .filter(|(_, res)| match (kind, res) {
                (AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true,
                (AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true,
                (AssocItemKind::Type(..), Res::Def(DefKind::AssocTy, _)) => true,
                (AssocItemKind::Delegation(_), Res::Def(DefKind::AssocFn, _)) => true,
                _ => false,
            })
            .map(|(key, _)| key.ident.name)
            .collect::<Vec<_>>();

        find_best_match_for_name(&targets, ident, None)
    }

    fn lookup_assoc_candidate<FilterFn>(
        &mut self,
        ident: Ident,
        ns: Namespace,
        filter_fn: FilterFn,
        called: bool,
    ) -> Option<AssocSuggestion>
    where
        FilterFn: Fn(Res) -> bool,
    {
        fn extract_node_id(t: &Ty) -> Option<NodeId> {
            match t.kind {
                TyKind::Path(None, _) => Some(t.id),
                TyKind::Ref(_, ref mut_ty) => extract_node_id(&mut_ty.ty),
                // This doesn't handle the remaining `Ty` variants as they are not
                // that commonly the self_type, it might be interesting to provide
                // support for those in future.
                _ => None,
            }
        }
        // Fields are generally expected in the same contexts as locals.
        if filter_fn(Res::Local(ast::DUMMY_NODE_ID)) {
            if let Some(node_id) =
                self.diag_metadata.current_self_type.as_ref().and_then(extract_node_id)
                && let Some(resolution) = self.r.partial_res_map.get(&node_id)
                && let Some(Res::Def(DefKind::Struct | DefKind::Union, did)) = resolution.full_res()
                && let Some(fields) = self.r.field_idents(did)
                && let Some(field) = fields.iter().find(|id| ident.name == id.name)
            {
                // Look for a field with the same name in the current self_type.
                return Some(AssocSuggestion::Field(field.span));
            }
        }

        if let Some(items) = self.diag_metadata.current_trait_assoc_items {
            for assoc_item in items {
                if let Some(assoc_ident) = assoc_item.kind.ident()
                    && assoc_ident == ident
                {
                    return Some(match &assoc_item.kind {
                        ast::AssocItemKind::Const(..) => AssocSuggestion::AssocConst,
                        ast::AssocItemKind::Fn(box ast::Fn { sig, .. }) if sig.decl.has_self() => {
                            AssocSuggestion::MethodWithSelf { called }
                        }
                        ast::AssocItemKind::Fn(..) => AssocSuggestion::AssocFn { called },
                        ast::AssocItemKind::Type(..) => AssocSuggestion::AssocType,
                        ast::AssocItemKind::Delegation(..)
                            if self
                                .r
                                .delegation_fn_sigs
                                .get(&self.r.local_def_id(assoc_item.id))
                                .is_some_and(|sig| sig.has_self) =>
                        {
                            AssocSuggestion::MethodWithSelf { called }
                        }
                        ast::AssocItemKind::Delegation(..) => AssocSuggestion::AssocFn { called },
                        ast::AssocItemKind::MacCall(_) | ast::AssocItemKind::DelegationMac(..) => {
                            continue;
                        }
                    });
                }
            }
        }

        // Look for associated items in the current trait.
        if let Some((module, _)) = self.current_trait_ref
            && let Ok(binding) = self.r.cm().maybe_resolve_ident_in_module(
                ModuleOrUniformRoot::Module(module),
                ident,
                ns,
                &self.parent_scope,
                None,
            )
        {
            let res = binding.res();
            if filter_fn(res) {
                match res {
                    Res::Def(DefKind::Fn | DefKind::AssocFn, def_id) => {
                        let has_self = match def_id.as_local() {
                            Some(def_id) => self
                                .r
                                .delegation_fn_sigs
                                .get(&def_id)
                                .is_some_and(|sig| sig.has_self),
                            None => {
                                self.r.tcx.fn_arg_idents(def_id).first().is_some_and(|&ident| {
                                    matches!(ident, Some(Ident { name: kw::SelfLower, .. }))
                                })
                            }
                        };
                        if has_self {
                            return Some(AssocSuggestion::MethodWithSelf { called });
                        } else {
                            return Some(AssocSuggestion::AssocFn { called });
                        }
                    }
                    Res::Def(DefKind::AssocConst, _) => {
                        return Some(AssocSuggestion::AssocConst);
                    }
                    Res::Def(DefKind::AssocTy, _) => {
                        return Some(AssocSuggestion::AssocType);
                    }
                    _ => {}
                }
            }
        }

        None
    }

    fn lookup_typo_candidate(
        &mut self,
        path: &[Segment],
        following_seg: Option<&Segment>,
        ns: Namespace,
        filter_fn: &impl Fn(Res) -> bool,
    ) -> TypoCandidate {
        let mut names = Vec::new();
        if let [segment] = path {
            let mut ctxt = segment.ident.span.ctxt();

            // Search in lexical scope.
            // Walk backwards up the ribs in scope and collect candidates.
            for rib in self.ribs[ns].iter().rev() {
                let rib_ctxt = if rib.kind.contains_params() {
                    ctxt.normalize_to_macros_2_0()
                } else {
                    ctxt.normalize_to_macro_rules()
                };

                // Locals and type parameters
                for (ident, &res) in &rib.bindings {
                    if filter_fn(res) && ident.span.ctxt() == rib_ctxt {
                        names.push(TypoSuggestion::typo_from_ident(*ident, res));
                    }
                }

                if let RibKind::Block(Some(module)) = rib.kind {
                    self.r.add_module_candidates(module, &mut names, &filter_fn, Some(ctxt));
                } else if let RibKind::Module(module) = rib.kind {
                    // Encountered a module item, abandon ribs and look into that module and preludes.
                    let parent_scope = &ParentScope { module, ..self.parent_scope };
                    self.r.add_scope_set_candidates(
                        &mut names,
                        ScopeSet::All(ns),
                        parent_scope,
                        ctxt,
                        filter_fn,
                    );
                    break;
                }

                if let RibKind::MacroDefinition(def) = rib.kind
                    && def == self.r.macro_def(ctxt)
                {
                    // If an invocation of this macro created `ident`, give up on `ident`
                    // and switch to `ident`'s source from the macro definition.
                    ctxt.remove_mark();
                }
            }
        } else {
            // Search in module.
            let mod_path = &path[..path.len() - 1];
            if let PathResult::Module(ModuleOrUniformRoot::Module(module)) =
                self.resolve_path(mod_path, Some(TypeNS), None, PathSource::Type)
            {
                self.r.add_module_candidates(module, &mut names, &filter_fn, None);
            }
        }

        // if next_seg is present, let's filter everything that does not continue the path
        if let Some(following_seg) = following_seg {
            names.retain(|suggestion| match suggestion.res {
                Res::Def(DefKind::Struct | DefKind::Enum | DefKind::Union, _) => {
                    // FIXME: this is not totally accurate, but mostly works
                    suggestion.candidate != following_seg.ident.name
                }
                Res::Def(DefKind::Mod, def_id) => {
                    let module = self.r.expect_module(def_id);
                    self.r
                        .resolutions(module)
                        .borrow()
                        .iter()
                        .any(|(key, _)| key.ident.name == following_seg.ident.name)
                }
                _ => true,
            });
        }
        let name = path[path.len() - 1].ident.name;
        // Make sure error reporting is deterministic.
        names.sort_by(|a, b| a.candidate.as_str().cmp(b.candidate.as_str()));

        match find_best_match_for_name(
            &names.iter().map(|suggestion| suggestion.candidate).collect::<Vec<Symbol>>(),
            name,
            None,
        ) {
            Some(found) => {
                let Some(sugg) = names.into_iter().find(|suggestion| suggestion.candidate == found)
                else {
                    return TypoCandidate::None;
                };
                if found == name {
                    TypoCandidate::Shadowed(sugg.res, sugg.span)
                } else {
                    TypoCandidate::Typo(sugg)
                }
            }
            _ => TypoCandidate::None,
        }
    }

    // Returns the name of the Rust type approximately corresponding to
    // a type name in another programming language.
    fn likely_rust_type(path: &[Segment]) -> Option<Symbol> {
        let name = path[path.len() - 1].ident.as_str();
        // Common Java types
        Some(match name {
            "byte" => sym::u8, // In Java, bytes are signed, but in practice one almost always wants unsigned bytes.
            "short" => sym::i16,
            "Bool" => sym::bool,
            "Boolean" => sym::bool,
            "boolean" => sym::bool,
            "int" => sym::i32,
            "long" => sym::i64,
            "float" => sym::f32,
            "double" => sym::f64,
            _ => return None,
        })
    }

    // try to give a suggestion for this pattern: `name = blah`, which is common in other languages
    // suggest `let name = blah` to introduce a new binding
    fn let_binding_suggestion(&self, err: &mut Diag<'_>, ident_span: Span) -> bool {
        if ident_span.from_expansion() {
            return false;
        }

        // only suggest when the code is a assignment without prefix code
        if let Some(Expr { kind: ExprKind::Assign(lhs, ..), .. }) = self.diag_metadata.in_assignment
            && let ast::ExprKind::Path(None, ref path) = lhs.kind
            && self.r.tcx.sess.source_map().is_line_before_span_empty(ident_span)
        {
            let (span, text) = match path.segments.first() {
                Some(seg) if let Some(name) = seg.ident.as_str().strip_prefix("let") => {
                    // a special case for #117894
                    let name = name.strip_prefix('_').unwrap_or(name);
                    (ident_span, format!("let {name}"))
                }
                _ => (ident_span.shrink_to_lo(), "let ".to_string()),
            };

            err.span_suggestion_verbose(
                span,
                "you might have meant to introduce a new binding",
                text,
                Applicability::MaybeIncorrect,
            );
            return true;
        }

        // a special case for #133713
        // '=' maybe a typo of `:`, which is a type annotation instead of assignment
        if err.code == Some(E0423)
            && let Some((let_span, None, Some(val_span))) = self.diag_metadata.current_let_binding
            && val_span.contains(ident_span)
            && val_span.lo() == ident_span.lo()
        {
            err.span_suggestion_verbose(
                let_span.shrink_to_hi().to(val_span.shrink_to_lo()),
                "you might have meant to use `:` for type annotation",
                ": ",
                Applicability::MaybeIncorrect,
            );
            return true;
        }
        false
    }

    fn find_module(&self, def_id: DefId) -> Option<(Module<'ra>, ImportSuggestion)> {
        let mut result = None;
        let mut seen_modules = FxHashSet::default();
        let root_did = self.r.graph_root.def_id();
        let mut worklist = vec![(
            self.r.graph_root,
            ThinVec::new(),
            root_did.is_local() || !self.r.tcx.is_doc_hidden(root_did),
        )];

        while let Some((in_module, path_segments, doc_visible)) = worklist.pop() {
            // abort if the module is already found
            if result.is_some() {
                break;
            }

            in_module.for_each_child(self.r, |r, ident, _, name_binding| {
                // abort if the module is already found or if name_binding is private external
                if result.is_some() || !name_binding.vis.is_visible_locally() {
                    return;
                }
                if let Some(module_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.0));
                    let doc_visible = doc_visible
                        && (module_def_id.is_local() || !r.tcx.is_doc_hidden(module_def_id));
                    if module_def_id == def_id {
                        let path =
                            Path { span: name_binding.span, segments: path_segments, tokens: None };
                        result = Some((
                            r.expect_module(module_def_id),
                            ImportSuggestion {
                                did: Some(def_id),
                                descr: "module",
                                path,
                                accessible: true,
                                doc_visible,
                                note: None,
                                via_import: false,
                                is_stable: true,
                            },
                        ));
                    } else {
                        // add the module to the lookup
                        if seen_modules.insert(module_def_id) {
                            let module = r.expect_module(module_def_id);
                            worklist.push((module, path_segments, doc_visible));
                        }
                    }
                }
            });
        }

        result
    }

    fn collect_enum_ctors(&self, def_id: DefId) -> Option<Vec<(Path, DefId, CtorKind)>> {
        self.find_module(def_id).map(|(enum_module, enum_import_suggestion)| {
            let mut variants = Vec::new();
            enum_module.for_each_child(self.r, |_, ident, _, name_binding| {
                if let Res::Def(DefKind::Ctor(CtorOf::Variant, kind), def_id) = name_binding.res() {
                    let mut segms = enum_import_suggestion.path.segments.clone();
                    segms.push(ast::PathSegment::from_ident(ident.0));
                    let path = Path { span: name_binding.span, segments: segms, tokens: None };
                    variants.push((path, def_id, kind));
                }
            });
            variants
        })
    }

    /// Adds a suggestion for using an enum's variant when an enum is used instead.
    fn suggest_using_enum_variant(
        &self,
        err: &mut Diag<'_>,
        source: PathSource<'_, '_, '_>,
        def_id: DefId,
        span: Span,
    ) {
        let Some(variant_ctors) = self.collect_enum_ctors(def_id) else {
            err.note("you might have meant to use one of the enum's variants");
            return;
        };

        // If the expression is a field-access or method-call, try to find a variant with the field/method name
        // that could have been intended, and suggest replacing the `.` with `::`.
        // Otherwise, suggest adding `::VariantName` after the enum;
        // and if the expression is call-like, only suggest tuple variants.
        let (suggest_path_sep_dot_span, suggest_only_tuple_variants) = match source {
            // `Type(a, b)` in a pattern, only suggest adding a tuple variant after `Type`.
            PathSource::TupleStruct(..) => (None, true),
            PathSource::Expr(Some(expr)) => match &expr.kind {
                // `Type(a, b)`, only suggest adding a tuple variant after `Type`.
                ExprKind::Call(..) => (None, true),
                // `Type.Foo(a, b)`, suggest replacing `.` -> `::` if variant `Foo` exists and is a tuple variant,
                // otherwise suggest adding a variant after `Type`.
                ExprKind::MethodCall(box MethodCall {
                    receiver,
                    span,
                    seg: PathSegment { ident, .. },
                    ..
                }) => {
                    let dot_span = receiver.span.between(*span);
                    let found_tuple_variant = variant_ctors.iter().any(|(path, _, ctor_kind)| {
                        *ctor_kind == CtorKind::Fn
                            && path.segments.last().is_some_and(|seg| seg.ident == *ident)
                    });
                    (found_tuple_variant.then_some(dot_span), false)
                }
                // `Type.Foo`, suggest replacing `.` -> `::` if variant `Foo` exists and is a unit or tuple variant,
                // otherwise suggest adding a variant after `Type`.
                ExprKind::Field(base, ident) => {
                    let dot_span = base.span.between(ident.span);
                    let found_tuple_or_unit_variant = variant_ctors.iter().any(|(path, ..)| {
                        path.segments.last().is_some_and(|seg| seg.ident == *ident)
                    });
                    (found_tuple_or_unit_variant.then_some(dot_span), false)
                }
                _ => (None, false),
            },
            _ => (None, false),
        };

        if let Some(dot_span) = suggest_path_sep_dot_span {
            err.span_suggestion_verbose(
                dot_span,
                "use the path separator to refer to a variant",
                "::",
                Applicability::MaybeIncorrect,
            );
        } else if suggest_only_tuple_variants {
            // Suggest only tuple variants regardless of whether they have fields and do not
            // suggest path with added parentheses.
            let mut suggestable_variants = variant_ctors
                .iter()
                .filter(|(.., kind)| *kind == CtorKind::Fn)
                .map(|(variant, ..)| path_names_to_string(variant))
                .collect::<Vec<_>>();
            suggestable_variants.sort();

            let non_suggestable_variant_count = variant_ctors.len() - suggestable_variants.len();

            let source_msg = if matches!(source, PathSource::TupleStruct(..)) {
                "to match against"
            } else {
                "to construct"
            };

            if !suggestable_variants.is_empty() {
                let msg = if non_suggestable_variant_count == 0 && suggestable_variants.len() == 1 {
                    format!("try {source_msg} the enum's variant")
                } else {
                    format!("try {source_msg} one of the enum's variants")
                };

                err.span_suggestions(
                    span,
                    msg,
                    suggestable_variants,
                    Applicability::MaybeIncorrect,
                );
            }

            // If the enum has no tuple variants..
            if non_suggestable_variant_count == variant_ctors.len() {
                err.help(format!("the enum has no tuple variants {source_msg}"));
            }

            // If there are also non-tuple variants..
            if non_suggestable_variant_count == 1 {
                err.help(format!("you might have meant {source_msg} the enum's non-tuple variant"));
            } else if non_suggestable_variant_count >= 1 {
                err.help(format!(
                    "you might have meant {source_msg} one of the enum's non-tuple variants"
                ));
            }
        } else {
            let needs_placeholder = |ctor_def_id: DefId, kind: CtorKind| {
                let def_id = self.r.tcx.parent(ctor_def_id);
                match kind {
                    CtorKind::Const => false,
                    CtorKind::Fn => {
                        !self.r.field_idents(def_id).is_some_and(|field_ids| field_ids.is_empty())
                    }
                }
            };

            let mut suggestable_variants = variant_ctors
                .iter()
                .filter(|(_, def_id, kind)| !needs_placeholder(*def_id, *kind))
                .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
                .map(|(variant, kind)| match kind {
                    CtorKind::Const => variant,
                    CtorKind::Fn => format!("({variant}())"),
                })
                .collect::<Vec<_>>();
            suggestable_variants.sort();
            let no_suggestable_variant = suggestable_variants.is_empty();

            if !no_suggestable_variant {
                let msg = if suggestable_variants.len() == 1 {
                    "you might have meant to use the following enum variant"
                } else {
                    "you might have meant to use one of the following enum variants"
                };

                err.span_suggestions(
                    span,
                    msg,
                    suggestable_variants,
                    Applicability::MaybeIncorrect,
                );
            }

            let mut suggestable_variants_with_placeholders = variant_ctors
                .iter()
                .filter(|(_, def_id, kind)| needs_placeholder(*def_id, *kind))
                .map(|(variant, _, kind)| (path_names_to_string(variant), kind))
                .filter_map(|(variant, kind)| match kind {
                    CtorKind::Fn => Some(format!("({variant}(/* fields */))")),
                    _ => None,
                })
                .collect::<Vec<_>>();
            suggestable_variants_with_placeholders.sort();

            if !suggestable_variants_with_placeholders.is_empty() {
                let msg =
                    match (no_suggestable_variant, suggestable_variants_with_placeholders.len()) {
                        (true, 1) => "the following enum variant is available",
                        (true, _) => "the following enum variants are available",
                        (false, 1) => "alternatively, the following enum variant is available",
                        (false, _) => {
                            "alternatively, the following enum variants are also available"
                        }
                    };

                err.span_suggestions(
                    span,
                    msg,
                    suggestable_variants_with_placeholders,
                    Applicability::HasPlaceholders,
                );
            }
        };

        if def_id.is_local() {
            err.span_note(self.r.def_span(def_id), "the enum is defined here");
        }
    }

    pub(crate) fn suggest_adding_generic_parameter(
        &self,
        path: &[Segment],
        source: PathSource<'_, '_, '_>,
    ) -> Option<(Span, &'static str, String, Applicability)> {
        let (ident, span) = match path {
            [segment]
                if !segment.has_generic_args
                    && segment.ident.name != kw::SelfUpper
                    && segment.ident.name != kw::Dyn =>
            {
                (segment.ident.to_string(), segment.ident.span)
            }
            _ => return None,
        };
        let mut iter = ident.chars().map(|c| c.is_uppercase());
        let single_uppercase_char =
            matches!(iter.next(), Some(true)) && matches!(iter.next(), None);
        if !self.diag_metadata.currently_processing_generic_args && !single_uppercase_char {
            return None;
        }
        match (self.diag_metadata.current_item, single_uppercase_char, self.diag_metadata.currently_processing_generic_args) {
            (Some(Item { kind: ItemKind::Fn(fn_), .. }), _, _) if fn_.ident.name == sym::main => {
                // Ignore `fn main()` as we don't want to suggest `fn main<T>()`
            }
            (
                Some(Item {
                    kind:
                        kind @ ItemKind::Fn(..)
                        | kind @ ItemKind::Enum(..)
                        | kind @ ItemKind::Struct(..)
                        | kind @ ItemKind::Union(..),
                    ..
                }),
                true, _
            )
            // Without the 2nd `true`, we'd suggest `impl <T>` for `impl T` when a type `T` isn't found
            | (Some(Item { kind: kind @ ItemKind::Impl(..), .. }), true, true)
            | (Some(Item { kind, .. }), false, _) => {
                if let Some(generics) = kind.generics() {
                    if span.overlaps(generics.span) {
                        // Avoid the following:
                        // error[E0405]: cannot find trait `A` in this scope
                        //  --> $DIR/typo-suggestion-named-underscore.rs:CC:LL
                        //   |
                        // L | fn foo<T: A>(x: T) {} // Shouldn't suggest underscore
                        //   |           ^- help: you might be missing a type parameter: `, A`
                        //   |           |
                        //   |           not found in this scope
                        return None;
                    }

                    let (msg, sugg) = match source {
                        PathSource::Type | PathSource::PreciseCapturingArg(TypeNS) => {
                            ("you might be missing a type parameter", ident)
                        }
                        PathSource::Expr(_) | PathSource::PreciseCapturingArg(ValueNS) => (
                            "you might be missing a const parameter",
                            format!("const {ident}: /* Type */"),
                        ),
                        _ => return None,
                    };
                    let (span, sugg) = if let [.., param] = &generics.params[..] {
                        let span = if let [.., bound] = &param.bounds[..] {
                            bound.span()
                        } else if let GenericParam {
                            kind: GenericParamKind::Const { ty, span: _, default  }, ..
                        } = param {
                            default.as_ref().map(|def| def.value.span).unwrap_or(ty.span)
                        } else {
                            param.ident.span
                        };
                        (span, format!(", {sugg}"))
                    } else {
                        (generics.span, format!("<{sugg}>"))
                    };
                    // Do not suggest if this is coming from macro expansion.
                    if span.can_be_used_for_suggestions() {
                        return Some((
                            span.shrink_to_hi(),
                            msg,
                            sugg,
                            Applicability::MaybeIncorrect,
                        ));
                    }
                }
            }
            _ => {}
        }
        None
    }

    /// Given the target `label`, search the `rib_index`th label rib for similarly named labels,
    /// optionally returning the closest match and whether it is reachable.
    pub(crate) fn suggestion_for_label_in_rib(
        &self,
        rib_index: usize,
        label: Ident,
    ) -> Option<LabelSuggestion> {
        // Are ribs from this `rib_index` within scope?
        let within_scope = self.is_label_valid_from_rib(rib_index);

        let rib = &self.label_ribs[rib_index];
        let names = rib
            .bindings
            .iter()
            .filter(|(id, _)| id.span.eq_ctxt(label.span))
            .map(|(id, _)| id.name)
            .collect::<Vec<Symbol>>();

        find_best_match_for_name(&names, label.name, None).map(|symbol| {
            // Upon finding a similar name, get the ident that it was from - the span
            // contained within helps make a useful diagnostic. In addition, determine
            // whether this candidate is within scope.
            let (ident, _) = rib.bindings.iter().find(|(ident, _)| ident.name == symbol).unwrap();
            (*ident, within_scope)
        })
    }

    pub(crate) fn maybe_report_lifetime_uses(
        &mut self,
        generics_span: Span,
        params: &[ast::GenericParam],
    ) {
        for (param_index, param) in params.iter().enumerate() {
            let GenericParamKind::Lifetime = param.kind else { continue };

            let def_id = self.r.local_def_id(param.id);

            let use_set = self.lifetime_uses.remove(&def_id);
            debug!(
                "Use set for {:?}({:?} at {:?}) is {:?}",
                def_id, param.ident, param.ident.span, use_set
            );

            let deletion_span = || {
                if params.len() == 1 {
                    // if sole lifetime, remove the entire `<>` brackets
                    Some(generics_span)
                } else if param_index == 0 {
                    // if removing within `<>` brackets, we also want to
                    // delete a leading or trailing comma as appropriate
                    match (
                        param.span().find_ancestor_inside(generics_span),
                        params[param_index + 1].span().find_ancestor_inside(generics_span),
                    ) {
                        (Some(param_span), Some(next_param_span)) => {
                            Some(param_span.to(next_param_span.shrink_to_lo()))
                        }
                        _ => None,
                    }
                } else {
                    // if removing within `<>` brackets, we also want to
                    // delete a leading or trailing comma as appropriate
                    match (
                        param.span().find_ancestor_inside(generics_span),
                        params[param_index - 1].span().find_ancestor_inside(generics_span),
                    ) {
                        (Some(param_span), Some(prev_param_span)) => {
                            Some(prev_param_span.shrink_to_hi().to(param_span))
                        }
                        _ => None,
                    }
                }
            };
            match use_set {
                Some(LifetimeUseSet::Many) => {}
                Some(LifetimeUseSet::One { use_span, use_ctxt }) => {
                    debug!(?param.ident, ?param.ident.span, ?use_span);

                    let elidable = matches!(use_ctxt, LifetimeCtxt::Ref);
                    let deletion_span =
                        if param.bounds.is_empty() { deletion_span() } else { None };

                    self.r.lint_buffer.buffer_lint(
                        lint::builtin::SINGLE_USE_LIFETIMES,
                        param.id,
                        param.ident.span,
                        lint::BuiltinLintDiag::SingleUseLifetime {
                            param_span: param.ident.span,
                            use_span: Some((use_span, elidable)),
                            deletion_span,
                            ident: param.ident,
                        },
                    );
                }
                None => {
                    debug!(?param.ident, ?param.ident.span);
                    let deletion_span = deletion_span();

                    // if the lifetime originates from expanded code, we won't be able to remove it #104432
                    if deletion_span.is_some_and(|sp| !sp.in_derive_expansion()) {
                        self.r.lint_buffer.buffer_lint(
                            lint::builtin::UNUSED_LIFETIMES,
                            param.id,
                            param.ident.span,
                            lint::BuiltinLintDiag::SingleUseLifetime {
                                param_span: param.ident.span,
                                use_span: None,
                                deletion_span,
                                ident: param.ident,
                            },
                        );
                    }
                }
            }
        }
    }

    pub(crate) fn emit_undeclared_lifetime_error(
        &self,
        lifetime_ref: &ast::Lifetime,
        outer_lifetime_ref: Option<Ident>,
    ) {
        debug_assert_ne!(lifetime_ref.ident.name, kw::UnderscoreLifetime);
        let mut err = if let Some(outer) = outer_lifetime_ref {
            struct_span_code_err!(
                self.r.dcx(),
                lifetime_ref.ident.span,
                E0401,
                "can't use generic parameters from outer item",
            )
            .with_span_label(lifetime_ref.ident.span, "use of generic parameter from outer item")
            .with_span_label(outer.span, "lifetime parameter from outer item")
        } else {
            struct_span_code_err!(
                self.r.dcx(),
                lifetime_ref.ident.span,
                E0261,
                "use of undeclared lifetime name `{}`",
                lifetime_ref.ident
            )
            .with_span_label(lifetime_ref.ident.span, "undeclared lifetime")
        };

        // Check if this is a typo of `'static`.
        if edit_distance(lifetime_ref.ident.name.as_str(), "'static", 2).is_some() {
            err.span_suggestion_verbose(
                lifetime_ref.ident.span,
                "you may have misspelled the `'static` lifetime",
                "'static",
                Applicability::MachineApplicable,
            );
        } else {
            self.suggest_introducing_lifetime(
                &mut err,
                Some(lifetime_ref.ident),
                |err, _, span, message, suggestion, span_suggs| {
                    err.multipart_suggestion_verbose(
                        message,
                        std::iter::once((span, suggestion)).chain(span_suggs).collect(),
                        Applicability::MaybeIncorrect,
                    );
                    true
                },
            );
        }

        err.emit();
    }

    fn suggest_introducing_lifetime(
        &self,
        err: &mut Diag<'_>,
        name: Option<Ident>,
        suggest: impl Fn(
            &mut Diag<'_>,
            bool,
            Span,
            Cow<'static, str>,
            String,
            Vec<(Span, String)>,
        ) -> bool,
    ) {
        let mut suggest_note = true;
        for rib in self.lifetime_ribs.iter().rev() {
            let mut should_continue = true;
            match rib.kind {
                LifetimeRibKind::Generics { binder, span, kind } => {
                    // Avoid suggesting placing lifetime parameters on constant items unless the relevant
                    // feature is enabled. Suggest the parent item as a possible location if applicable.
                    if let LifetimeBinderKind::ConstItem = kind
                        && !self.r.tcx().features().generic_const_items()
                    {
                        continue;
                    }

                    if !span.can_be_used_for_suggestions()
                        && suggest_note
                        && let Some(name) = name
                    {
                        suggest_note = false; // Avoid displaying the same help multiple times.
                        err.span_label(
                            span,
                            format!(
                                "lifetime `{name}` is missing in item created through this procedural macro",
                            ),
                        );
                        continue;
                    }

                    let higher_ranked = matches!(
                        kind,
                        LifetimeBinderKind::FnPtrType
                            | LifetimeBinderKind::PolyTrait
                            | LifetimeBinderKind::WhereBound
                    );

                    let mut rm_inner_binders: FxIndexSet<Span> = Default::default();
                    let (span, sugg) = if span.is_empty() {
                        let mut binder_idents: FxIndexSet<Ident> = Default::default();
                        binder_idents.insert(name.unwrap_or(Ident::from_str("'a")));

                        // We need to special case binders in the following situation:
                        // Change `T: for<'a> Trait<T> + 'b` to `for<'a, 'b> T: Trait<T> + 'b`
                        // T: for<'a> Trait<T> + 'b
                        //    ^^^^^^^  remove existing inner binder `for<'a>`
                        // for<'a, 'b> T: Trait<T> + 'b
                        // ^^^^^^^^^^^  suggest outer binder `for<'a, 'b>`
                        if let LifetimeBinderKind::WhereBound = kind
                            && let Some(predicate) = self.diag_metadata.current_where_predicate
                            && let ast::WherePredicateKind::BoundPredicate(
                                ast::WhereBoundPredicate { bounded_ty, bounds, .. },
                            ) = &predicate.kind
                            && bounded_ty.id == binder
                        {
                            for bound in bounds {
                                if let ast::GenericBound::Trait(poly_trait_ref) = bound
                                    && let span = poly_trait_ref
                                        .span
                                        .with_hi(poly_trait_ref.trait_ref.path.span.lo())
                                    && !span.is_empty()
                                {
                                    rm_inner_binders.insert(span);
                                    poly_trait_ref.bound_generic_params.iter().for_each(|v| {
                                        binder_idents.insert(v.ident);
                                    });
                                }
                            }
                        }

                        let binders_sugg: String = binder_idents
                            .into_iter()
                            .map(|ident| ident.to_string())
                            .intersperse(", ".to_owned())
                            .collect();
                        let sugg = format!(
                            "{}<{}>{}",
                            if higher_ranked { "for" } else { "" },
                            binders_sugg,
                            if higher_ranked { " " } else { "" },
                        );
                        (span, sugg)
                    } else {
                        let span = self
                            .r
                            .tcx
                            .sess
                            .source_map()
                            .span_through_char(span, '<')
                            .shrink_to_hi();
                        let sugg =
                            format!("{}, ", name.map(|i| i.to_string()).as_deref().unwrap_or("'a"));
                        (span, sugg)
                    };

                    if higher_ranked {
                        let message = Cow::from(format!(
                            "consider making the {} lifetime-generic with a new `{}` lifetime",
                            kind.descr(),
                            name.map(|i| i.to_string()).as_deref().unwrap_or("'a"),
                        ));
                        should_continue = suggest(
                            err,
                            true,
                            span,
                            message,
                            sugg,
                            if !rm_inner_binders.is_empty() {
                                rm_inner_binders
                                    .into_iter()
                                    .map(|v| (v, "".to_string()))
                                    .collect::<Vec<_>>()
                            } else {
                                vec![]
                            },
                        );
                        err.note_once(
                            "for more information on higher-ranked polymorphism, visit \
                             https://doc.rust-lang.org/nomicon/hrtb.html",
                        );
                    } else if let Some(name) = name {
                        let message =
                            Cow::from(format!("consider introducing lifetime `{name}` here"));
                        should_continue = suggest(err, false, span, message, sugg, vec![]);
                    } else {
                        let message = Cow::from("consider introducing a named lifetime parameter");
                        should_continue = suggest(err, false, span, message, sugg, vec![]);
                    }
                }
                LifetimeRibKind::Item | LifetimeRibKind::ConstParamTy => break,
                _ => {}
            }
            if !should_continue {
                break;
            }
        }
    }

    pub(crate) fn emit_non_static_lt_in_const_param_ty_error(&self, lifetime_ref: &ast::Lifetime) {
        self.r
            .dcx()
            .create_err(errors::ParamInTyOfConstParam {
                span: lifetime_ref.ident.span,
                name: lifetime_ref.ident.name,
            })
            .emit();
    }

    /// Non-static lifetimes are prohibited in anonymous constants under `min_const_generics`.
    /// This function will emit an error if `generic_const_exprs` is not enabled, the body identified by
    /// `body_id` is an anonymous constant and `lifetime_ref` is non-static.
    pub(crate) fn emit_forbidden_non_static_lifetime_error(
        &self,
        cause: NoConstantGenericsReason,
        lifetime_ref: &ast::Lifetime,
    ) {
        match cause {
            NoConstantGenericsReason::IsEnumDiscriminant => {
                self.r
                    .dcx()
                    .create_err(errors::ParamInEnumDiscriminant {
                        span: lifetime_ref.ident.span,
                        name: lifetime_ref.ident.name,
                        param_kind: errors::ParamKindInEnumDiscriminant::Lifetime,
                    })
                    .emit();
            }
            NoConstantGenericsReason::NonTrivialConstArg => {
                assert!(!self.r.tcx.features().generic_const_exprs());
                self.r
                    .dcx()
                    .create_err(errors::ParamInNonTrivialAnonConst {
                        span: lifetime_ref.ident.span,
                        name: lifetime_ref.ident.name,
                        param_kind: errors::ParamKindInNonTrivialAnonConst::Lifetime,
                        help: self
                            .r
                            .tcx
                            .sess
                            .is_nightly_build()
                            .then_some(errors::ParamInNonTrivialAnonConstHelp),
                    })
                    .emit();
            }
        }
    }

    pub(crate) fn report_missing_lifetime_specifiers(
        &mut self,
        lifetime_refs: Vec<MissingLifetime>,
        function_param_lifetimes: Option<(Vec<MissingLifetime>, Vec<ElisionFnParameter>)>,
    ) -> ErrorGuaranteed {
        let num_lifetimes: usize = lifetime_refs.iter().map(|lt| lt.count).sum();
        let spans: Vec<_> = lifetime_refs.iter().map(|lt| lt.span).collect();

        let mut err = struct_span_code_err!(
            self.r.dcx(),
            spans,
            E0106,
            "missing lifetime specifier{}",
            pluralize!(num_lifetimes)
        );
        self.add_missing_lifetime_specifiers_label(
            &mut err,
            lifetime_refs,
            function_param_lifetimes,
        );
        err.emit()
    }

    fn add_missing_lifetime_specifiers_label(
        &mut self,
        err: &mut Diag<'_>,
        lifetime_refs: Vec<MissingLifetime>,
        function_param_lifetimes: Option<(Vec<MissingLifetime>, Vec<ElisionFnParameter>)>,
    ) {
        for &lt in &lifetime_refs {
            err.span_label(
                lt.span,
                format!(
                    "expected {} lifetime parameter{}",
                    if lt.count == 1 { "named".to_string() } else { lt.count.to_string() },
                    pluralize!(lt.count),
                ),
            );
        }

        let mut in_scope_lifetimes: Vec<_> = self
            .lifetime_ribs
            .iter()
            .rev()
            .take_while(|rib| {
                !matches!(rib.kind, LifetimeRibKind::Item | LifetimeRibKind::ConstParamTy)
            })
            .flat_map(|rib| rib.bindings.iter())
            .map(|(&ident, &res)| (ident, res))
            .filter(|(ident, _)| ident.name != kw::UnderscoreLifetime)
            .collect();
        debug!(?in_scope_lifetimes);

        let mut maybe_static = false;
        debug!(?function_param_lifetimes);
        if let Some((param_lifetimes, params)) = &function_param_lifetimes {
            let elided_len = param_lifetimes.len();
            let num_params = params.len();

            let mut m = String::new();

            for (i, info) in params.iter().enumerate() {
                let ElisionFnParameter { ident, index, lifetime_count, span } = *info;
                debug_assert_ne!(lifetime_count, 0);

                err.span_label(span, "");

                if i != 0 {
                    if i + 1 < num_params {
                        m.push_str(", ");
                    } else if num_params == 2 {
                        m.push_str(" or ");
                    } else {
                        m.push_str(", or ");
                    }
                }

                let help_name = if let Some(ident) = ident {
                    format!("`{ident}`")
                } else {
                    format!("argument {}", index + 1)
                };

                if lifetime_count == 1 {
                    m.push_str(&help_name[..])
                } else {
                    m.push_str(&format!("one of {help_name}'s {lifetime_count} lifetimes")[..])
                }
            }

            if num_params == 0 {
                err.help(
                    "this function's return type contains a borrowed value, but there is no value \
                     for it to be borrowed from",
                );
                if in_scope_lifetimes.is_empty() {
                    maybe_static = true;
                    in_scope_lifetimes = vec![(
                        Ident::with_dummy_span(kw::StaticLifetime),
                        (DUMMY_NODE_ID, LifetimeRes::Static),
                    )];
                }
            } else if elided_len == 0 {
                err.help(
                    "this function's return type contains a borrowed value with an elided \
                     lifetime, but the lifetime cannot be derived from the arguments",
                );
                if in_scope_lifetimes.is_empty() {
                    maybe_static = true;
                    in_scope_lifetimes = vec![(
                        Ident::with_dummy_span(kw::StaticLifetime),
                        (DUMMY_NODE_ID, LifetimeRes::Static),
                    )];
                }
            } else if num_params == 1 {
                err.help(format!(
                    "this function's return type contains a borrowed value, but the signature does \
                     not say which {m} it is borrowed from",
                ));
            } else {
                err.help(format!(
                    "this function's return type contains a borrowed value, but the signature does \
                     not say whether it is borrowed from {m}",
                ));
            }
        }

        #[allow(rustc::symbol_intern_string_literal)]
        let existing_name = match &in_scope_lifetimes[..] {
            [] => Symbol::intern("'a"),
            [(existing, _)] => existing.name,
            _ => Symbol::intern("'lifetime"),
        };

        let mut spans_suggs: Vec<_> = Vec::new();
        let build_sugg = |lt: MissingLifetime| match lt.kind {
            MissingLifetimeKind::Underscore => {
                debug_assert_eq!(lt.count, 1);
                (lt.span, existing_name.to_string())
            }
            MissingLifetimeKind::Ampersand => {
                debug_assert_eq!(lt.count, 1);
                (lt.span.shrink_to_hi(), format!("{existing_name} "))
            }
            MissingLifetimeKind::Comma => {
                let sugg: String = std::iter::repeat([existing_name.as_str(), ", "])
                    .take(lt.count)
                    .flatten()
                    .collect();
                (lt.span.shrink_to_hi(), sugg)
            }
            MissingLifetimeKind::Brackets => {
                let sugg: String = std::iter::once("<")
                    .chain(
                        std::iter::repeat(existing_name.as_str()).take(lt.count).intersperse(", "),
                    )
                    .chain([">"])
                    .collect();
                (lt.span.shrink_to_hi(), sugg)
            }
        };
        for &lt in &lifetime_refs {
            spans_suggs.push(build_sugg(lt));
        }
        debug!(?spans_suggs);
        match in_scope_lifetimes.len() {
            0 => {
                if let Some((param_lifetimes, _)) = function_param_lifetimes {
                    for lt in param_lifetimes {
                        spans_suggs.push(build_sugg(lt))
                    }
                }
                self.suggest_introducing_lifetime(
                    err,
                    None,
                    |err, higher_ranked, span, message, intro_sugg, _| {
                        err.multipart_suggestion_verbose(
                            message,
                            std::iter::once((span, intro_sugg))
                                .chain(spans_suggs.clone())
                                .collect(),
                            Applicability::MaybeIncorrect,
                        );
                        higher_ranked
                    },
                );
            }
            1 => {
                let post = if maybe_static {
                    let owned = if let [lt] = &lifetime_refs[..]
                        && lt.kind != MissingLifetimeKind::Ampersand
                    {
                        ", or if you will only have owned values"
                    } else {
                        ""
                    };
                    format!(
                        ", but this is uncommon unless you're returning a borrowed value from a \
                         `const` or a `static`{owned}",
                    )
                } else {
                    String::new()
                };
                err.multipart_suggestion_verbose(
                    format!("consider using the `{existing_name}` lifetime{post}"),
                    spans_suggs,
                    Applicability::MaybeIncorrect,
                );
                if maybe_static {
                    // FIXME: what follows are general suggestions, but we'd want to perform some
                    // minimal flow analysis to provide more accurate suggestions. For example, if
                    // we identified that the return expression references only one argument, we
                    // would suggest borrowing only that argument, and we'd skip the prior
                    // "use `'static`" suggestion entirely.
                    if let [lt] = &lifetime_refs[..]
                        && (lt.kind == MissingLifetimeKind::Ampersand
                            || lt.kind == MissingLifetimeKind::Underscore)
                    {
                        let pre = if lt.kind == MissingLifetimeKind::Ampersand
                            && let Some((kind, _span)) = self.diag_metadata.current_function
                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                            && !sig.decl.inputs.is_empty()
                            && let sugg = sig
                                .decl
                                .inputs
                                .iter()
                                .filter_map(|param| {
                                    if param.ty.span.contains(lt.span) {
                                        // We don't want to suggest `fn elision(_: &fn() -> &i32)`
                                        // when we have `fn elision(_: fn() -> &i32)`
                                        None
                                    } else if let TyKind::CVarArgs = param.ty.kind {
                                        // Don't suggest `&...` for ffi fn with varargs
                                        None
                                    } else if let TyKind::ImplTrait(..) = &param.ty.kind {
                                        // We handle these in the next `else if` branch.
                                        None
                                    } else {
                                        Some((param.ty.span.shrink_to_lo(), "&".to_string()))
                                    }
                                })
                                .collect::<Vec<_>>()
                            && !sugg.is_empty()
                        {
                            let (the, s) = if sig.decl.inputs.len() == 1 {
                                ("the", "")
                            } else {
                                ("one of the", "s")
                            };
                            err.multipart_suggestion_verbose(
                                format!(
                                    "instead, you are more likely to want to change {the} \
                                     argument{s} to be borrowed...",
                                ),
                                sugg,
                                Applicability::MaybeIncorrect,
                            );
                            "...or alternatively, you might want"
                        } else if (lt.kind == MissingLifetimeKind::Ampersand
                            || lt.kind == MissingLifetimeKind::Underscore)
                            && let Some((kind, _span)) = self.diag_metadata.current_function
                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                            && let ast::FnRetTy::Ty(ret_ty) = &sig.decl.output
                            && !sig.decl.inputs.is_empty()
                            && let arg_refs = sig
                                .decl
                                .inputs
                                .iter()
                                .filter_map(|param| match &param.ty.kind {
                                    TyKind::ImplTrait(_, bounds) => Some(bounds),
                                    _ => None,
                                })
                                .flat_map(|bounds| bounds.into_iter())
                                .collect::<Vec<_>>()
                            && !arg_refs.is_empty()
                        {
                            // We have a situation like
                            // fn g(mut x: impl Iterator<Item = &()>) -> Option<&()>
                            // So we look at every ref in the trait bound. If there's any, we
                            // suggest
                            // fn g<'a>(mut x: impl Iterator<Item = &'a ()>) -> Option<&'a ()>
                            let mut lt_finder =
                                LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] };
                            for bound in arg_refs {
                                if let ast::GenericBound::Trait(trait_ref) = bound {
                                    lt_finder.visit_trait_ref(&trait_ref.trait_ref);
                                }
                            }
                            lt_finder.visit_ty(ret_ty);
                            let spans_suggs: Vec<_> = lt_finder
                                .seen
                                .iter()
                                .filter_map(|ty| match &ty.kind {
                                    TyKind::Ref(_, mut_ty) => {
                                        let span = ty.span.with_hi(mut_ty.ty.span.lo());
                                        Some((span, "&'a ".to_string()))
                                    }
                                    _ => None,
                                })
                                .collect();
                            self.suggest_introducing_lifetime(
                                err,
                                None,
                                |err, higher_ranked, span, message, intro_sugg, _| {
                                    err.multipart_suggestion_verbose(
                                        message,
                                        std::iter::once((span, intro_sugg))
                                            .chain(spans_suggs.clone())
                                            .collect(),
                                        Applicability::MaybeIncorrect,
                                    );
                                    higher_ranked
                                },
                            );
                            "alternatively, you might want"
                        } else {
                            "instead, you are more likely to want"
                        };
                        let mut owned_sugg = lt.kind == MissingLifetimeKind::Ampersand;
                        let mut sugg = vec![(lt.span, String::new())];
                        if let Some((kind, _span)) = self.diag_metadata.current_function
                            && let FnKind::Fn(_, _, ast::Fn { sig, .. }) = kind
                            && let ast::FnRetTy::Ty(ty) = &sig.decl.output
                        {
                            let mut lt_finder =
                                LifetimeFinder { lifetime: lt.span, found: None, seen: vec![] };
                            lt_finder.visit_ty(&ty);

                            if let [Ty { span, kind: TyKind::Ref(_, mut_ty), .. }] =
                                &lt_finder.seen[..]
                            {
                                // We might have a situation like
                                // fn g(mut x: impl Iterator<Item = &'_ ()>) -> Option<&'_ ()>
                                // but `lt.span` only points at `'_`, so to suggest `-> Option<()>`
                                // we need to find a more accurate span to end up with
                                // fn g<'a>(mut x: impl Iterator<Item = &'_ ()>) -> Option<()>
                                sugg = vec![(span.with_hi(mut_ty.ty.span.lo()), String::new())];
                                owned_sugg = true;
                            }
                            if let Some(ty) = lt_finder.found {
                                if let TyKind::Path(None, path) = &ty.kind {
                                    // Check if the path being borrowed is likely to be owned.
                                    let path: Vec<_> = Segment::from_path(path);
                                    match self.resolve_path(
                                        &path,
                                        Some(TypeNS),
                                        None,
                                        PathSource::Type,
                                    ) {
                                        PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
                                            match module.res() {
                                                Some(Res::PrimTy(PrimTy::Str)) => {
                                                    // Don't suggest `-> str`, suggest `-> String`.
                                                    sugg = vec![(
                                                        lt.span.with_hi(ty.span.hi()),
                                                        "String".to_string(),
                                                    )];
                                                }
                                                Some(Res::PrimTy(..)) => {}
                                                Some(Res::Def(
                                                    DefKind::Struct
                                                    | DefKind::Union
                                                    | DefKind::Enum
                                                    | DefKind::ForeignTy
                                                    | DefKind::AssocTy
                                                    | DefKind::OpaqueTy
                                                    | DefKind::TyParam,
                                                    _,
                                                )) => {}
                                                _ => {
                                                    // Do not suggest in all other cases.
                                                    owned_sugg = false;
                                                }
                                            }
                                        }
                                        PathResult::NonModule(res) => {
                                            match res.base_res() {
                                                Res::PrimTy(PrimTy::Str) => {
                                                    // Don't suggest `-> str`, suggest `-> String`.
                                                    sugg = vec![(
                                                        lt.span.with_hi(ty.span.hi()),
                                                        "String".to_string(),
                                                    )];
                                                }
                                                Res::PrimTy(..) => {}
                                                Res::Def(
                                                    DefKind::Struct
                                                    | DefKind::Union
                                                    | DefKind::Enum
                                                    | DefKind::ForeignTy
                                                    | DefKind::AssocTy
                                                    | DefKind::OpaqueTy
                                                    | DefKind::TyParam,
                                                    _,
                                                ) => {}
                                                _ => {
                                                    // Do not suggest in all other cases.
                                                    owned_sugg = false;
                                                }
                                            }
                                        }
                                        _ => {
                                            // Do not suggest in all other cases.
                                            owned_sugg = false;
                                        }
                                    }
                                }
                                if let TyKind::Slice(inner_ty) = &ty.kind {
                                    // Don't suggest `-> [T]`, suggest `-> Vec<T>`.
                                    sugg = vec![
                                        (lt.span.with_hi(inner_ty.span.lo()), "Vec<".to_string()),
                                        (ty.span.with_lo(inner_ty.span.hi()), ">".to_string()),
                                    ];
                                }
                            }
                        }
                        if owned_sugg {
                            err.multipart_suggestion_verbose(
                                format!("{pre} to return an owned value"),
                                sugg,
                                Applicability::MaybeIncorrect,
                            );
                        }
                    }
                }
            }
            _ => {
                let lifetime_spans: Vec<_> =
                    in_scope_lifetimes.iter().map(|(ident, _)| ident.span).collect();
                err.span_note(lifetime_spans, "these named lifetimes are available to use");

                if spans_suggs.len() > 0 {
                    // This happens when we have `Foo<T>` where we point at the space before `T`,
                    // but this can be confusing so we give a suggestion with placeholders.
                    err.multipart_suggestion_verbose(
                        "consider using one of the available lifetimes here",
                        spans_suggs,
                        Applicability::HasPlaceholders,
                    );
                }
            }
        }
    }
}

fn mk_where_bound_predicate(
    path: &Path,
    poly_trait_ref: &ast::PolyTraitRef,
    ty: &Ty,
) -> Option<ast::WhereBoundPredicate> {
    let modified_segments = {
        let mut segments = path.segments.clone();
        let [preceding @ .., second_last, last] = segments.as_mut_slice() else {
            return None;
        };
        let mut segments = ThinVec::from(preceding);

        let added_constraint = ast::AngleBracketedArg::Constraint(ast::AssocItemConstraint {
            id: DUMMY_NODE_ID,
            ident: last.ident,
            gen_args: None,
            kind: ast::AssocItemConstraintKind::Equality {
                term: ast::Term::Ty(Box::new(ast::Ty {
                    kind: ast::TyKind::Path(None, poly_trait_ref.trait_ref.path.clone()),
                    id: DUMMY_NODE_ID,
                    span: DUMMY_SP,
                    tokens: None,
                })),
            },
            span: DUMMY_SP,
        });

        match second_last.args.as_deref_mut() {
            Some(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs { args, .. })) => {
                args.push(added_constraint);
            }
            Some(_) => return None,
            None => {
                second_last.args =
                    Some(Box::new(ast::GenericArgs::AngleBracketed(ast::AngleBracketedArgs {
                        args: ThinVec::from([added_constraint]),
                        span: DUMMY_SP,
                    })));
            }
        }

        segments.push(second_last.clone());
        segments
    };

    let new_where_bound_predicate = ast::WhereBoundPredicate {
        bound_generic_params: ThinVec::new(),
        bounded_ty: Box::new(ty.clone()),
        bounds: vec![ast::GenericBound::Trait(ast::PolyTraitRef {
            bound_generic_params: ThinVec::new(),
            modifiers: ast::TraitBoundModifiers::NONE,
            trait_ref: ast::TraitRef {
                path: ast::Path { segments: modified_segments, span: DUMMY_SP, tokens: None },
                ref_id: DUMMY_NODE_ID,
            },
            span: DUMMY_SP,
            parens: ast::Parens::No,
        })],
    };

    Some(new_where_bound_predicate)
}

/// Report lifetime/lifetime shadowing as an error.
pub(super) fn signal_lifetime_shadowing(sess: &Session, orig: Ident, shadower: Ident) {
    struct_span_code_err!(
        sess.dcx(),
        shadower.span,
        E0496,
        "lifetime name `{}` shadows a lifetime name that is already in scope",
        orig.name,
    )
    .with_span_label(orig.span, "first declared here")
    .with_span_label(shadower.span, format!("lifetime `{}` already in scope", orig.name))
    .emit();
}

struct LifetimeFinder<'ast> {
    lifetime: Span,
    found: Option<&'ast Ty>,
    seen: Vec<&'ast Ty>,
}

impl<'ast> Visitor<'ast> for LifetimeFinder<'ast> {
    fn visit_ty(&mut self, t: &'ast Ty) {
        if let TyKind::Ref(_, mut_ty) | TyKind::PinnedRef(_, mut_ty) = &t.kind {
            self.seen.push(t);
            if t.span.lo() == self.lifetime.lo() {
                self.found = Some(&mut_ty.ty);
            }
        }
        walk_ty(self, t)
    }
}

/// Shadowing involving a label is only a warning for historical reasons.
//FIXME: make this a proper lint.
pub(super) fn signal_label_shadowing(sess: &Session, orig: Span, shadower: Ident) {
    let name = shadower.name;
    let shadower = shadower.span;
    sess.dcx()
        .struct_span_warn(
            shadower,
            format!("label name `{name}` shadows a label name that is already in scope"),
        )
        .with_span_label(orig, "first declared here")
        .with_span_label(shadower, format!("label `{name}` already in scope"))
        .emit();
}
