// ignore-tidy-filelength
//! "Late resolution" is the pass that resolves most of names in a crate beside imports and macros.
//! It runs when the crate is fully expanded and its module structure is fully built.
//! So it just walks through the crate and resolves all the expressions, types, etc.
//!
//! If you wonder why there's no `early.rs`, that's because it's split into three files -
//! `build_reduced_graph.rs`, `macros.rs` and `imports.rs`.

use std::assert_matches::debug_assert_matches;
use std::borrow::Cow;
use std::collections::BTreeSet;
use std::collections::hash_map::Entry;
use std::mem::{replace, swap, take};

use rustc_ast::ptr::P;
use rustc_ast::visit::{AssocCtxt, BoundKind, FnCtxt, FnKind, Visitor, visit_opt, walk_list};
use rustc_ast::*;
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap};
use rustc_errors::codes::*;
use rustc_errors::{Applicability, DiagArgValue, IntoDiagArg, StashKey, Suggestions};
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, PartialRes, PerNS};
use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
use rustc_middle::middle::resolve_bound_vars::Set1;
use rustc_middle::ty::DelegationFnSig;
use rustc_middle::{bug, span_bug};
use rustc_session::config::{CrateType, ResolveDocLinks};
use rustc_session::lint::{self, BuiltinLintDiag};
use rustc_session::parse::feature_err;
use rustc_span::source_map::{Spanned, respan};
use rustc_span::symbol::{Ident, Symbol, kw, sym};
use rustc_span::{BytePos, Span, SyntaxContext};
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument, trace};

use crate::{
    BindingError, BindingKey, Finalize, LexicalScopeBinding, Module, ModuleOrUniformRoot,
    NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, TyCtxt, UseError,
    Used, errors, path_names_to_string, rustdoc,
};

mod diagnostics;

type Res = def::Res<NodeId>;

type IdentMap<T> = FxHashMap<Ident, T>;

use diagnostics::{ElisionFnParameter, LifetimeElisionCandidate, MissingLifetime};

#[derive(Copy, Clone, Debug)]
struct BindingInfo {
    span: Span,
    annotation: BindingMode,
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(crate) enum PatternSource {
    Match,
    Let,
    For,
    FnParam,
}

#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum IsRepeatExpr {
    No,
    Yes,
}

struct IsNeverPattern;

/// Describes whether an `AnonConst` is a type level const arg or
/// some other form of anon const (i.e. inline consts or enum discriminants)
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
enum AnonConstKind {
    EnumDiscriminant,
    InlineConst,
    ConstArg(IsRepeatExpr),
}

impl PatternSource {
    fn descr(self) -> &'static str {
        match self {
            PatternSource::Match => "match binding",
            PatternSource::Let => "let binding",
            PatternSource::For => "for binding",
            PatternSource::FnParam => "function parameter",
        }
    }
}

impl IntoDiagArg for PatternSource {
    fn into_diag_arg(self) -> DiagArgValue {
        DiagArgValue::Str(Cow::Borrowed(self.descr()))
    }
}

/// Denotes whether the context for the set of already bound bindings is a `Product`
/// or `Or` context. This is used in e.g., `fresh_binding` and `resolve_pattern_inner`.
/// See those functions for more information.
#[derive(PartialEq)]
enum PatBoundCtx {
    /// A product pattern context, e.g., `Variant(a, b)`.
    Product,
    /// An or-pattern context, e.g., `p_0 | ... | p_n`.
    Or,
}

/// Does this the item (from the item rib scope) allow generic parameters?
#[derive(Copy, Clone, Debug)]
pub(crate) enum HasGenericParams {
    Yes(Span),
    No,
}

/// May this constant have generics?
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum ConstantHasGenerics {
    Yes,
    No(NoConstantGenericsReason),
}

impl ConstantHasGenerics {
    fn force_yes_if(self, b: bool) -> Self {
        if b { Self::Yes } else { self }
    }
}

/// Reason for why an anon const is not allowed to reference generic parameters
#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum NoConstantGenericsReason {
    /// Const arguments are only allowed to use generic parameters when:
    /// - `feature(generic_const_exprs)` is enabled
    /// or
    /// - the const argument is a sole const generic parameter, i.e. `foo::<{ N }>()`
    ///
    /// If neither of the above are true then this is used as the cause.
    NonTrivialConstArg,
    /// Enum discriminants are not allowed to reference generic parameters ever, this
    /// is used when an anon const is in the following position:
    ///
    /// ```rust,compile_fail
    /// enum Foo<const N: isize> {
    ///     Variant = { N }, // this anon const is not allowed to use generics
    /// }
    /// ```
    IsEnumDiscriminant,
}

#[derive(Copy, Clone, Debug, Eq, PartialEq)]
pub(crate) enum ConstantItemKind {
    Const,
    Static,
}

impl ConstantItemKind {
    pub(crate) fn as_str(&self) -> &'static str {
        match self {
            Self::Const => "const",
            Self::Static => "static",
        }
    }
}

#[derive(Debug, Copy, Clone, PartialEq, Eq)]
enum RecordPartialRes {
    Yes,
    No,
}

/// The rib kind restricts certain accesses,
/// e.g. to a `Res::Local` of an outer item.
#[derive(Copy, Clone, Debug)]
pub(crate) enum RibKind<'ra> {
    /// No restriction needs to be applied.
    Normal,

    /// We passed through an impl or trait and are now in one of its
    /// methods or associated types. Allow references to ty params that impl or trait
    /// binds. Disallow any other upvars (including other ty params that are
    /// upvars).
    AssocItem,

    /// We passed through a function, closure or coroutine signature. Disallow labels.
    FnOrCoroutine,

    /// We passed through an item scope. Disallow upvars.
    Item(HasGenericParams, DefKind),

    /// We're in a constant item. Can't refer to dynamic stuff.
    ///
    /// The item may reference generic parameters in trivial constant expressions.
    /// All other constants aren't allowed to use generic params at all.
    ConstantItem(ConstantHasGenerics, Option<(Ident, ConstantItemKind)>),

    /// We passed through a module.
    Module(Module<'ra>),

    /// We passed through a `macro_rules!` statement
    MacroDefinition(DefId),

    /// All bindings in this rib are generic parameters that can't be used
    /// from the default of a generic parameter because they're not declared
    /// before said generic parameter. Also see the `visit_generics` override.
    ForwardGenericParamBan,

    /// We are inside of the type of a const parameter. Can't refer to any
    /// parameters.
    ConstParamTy,

    /// We are inside a `sym` inline assembly operand. Can only refer to
    /// globals.
    InlineAsmSym,
}

impl RibKind<'_> {
    /// Whether this rib kind contains generic parameters, as opposed to local
    /// variables.
    pub(crate) fn contains_params(&self) -> bool {
        match self {
            RibKind::Normal
            | RibKind::FnOrCoroutine
            | RibKind::ConstantItem(..)
            | RibKind::Module(_)
            | RibKind::MacroDefinition(_)
            | RibKind::ConstParamTy
            | RibKind::InlineAsmSym => false,
            RibKind::AssocItem | RibKind::Item(..) | RibKind::ForwardGenericParamBan => true,
        }
    }

    /// This rib forbids referring to labels defined in upwards ribs.
    fn is_label_barrier(self) -> bool {
        match self {
            RibKind::Normal | RibKind::MacroDefinition(..) => false,

            RibKind::AssocItem
            | RibKind::FnOrCoroutine
            | RibKind::Item(..)
            | RibKind::ConstantItem(..)
            | RibKind::Module(..)
            | RibKind::ForwardGenericParamBan
            | RibKind::ConstParamTy
            | RibKind::InlineAsmSym => true,
        }
    }
}

/// A single local scope.
///
/// A rib represents a scope names can live in. Note that these appear in many places, not just
/// around braces. At any place where the list of accessible names (of the given namespace)
/// changes or a new restrictions on the name accessibility are introduced, a new rib is put onto a
/// stack. This may be, for example, a `let` statement (because it introduces variables), a macro,
/// etc.
///
/// Different [rib kinds](enum@RibKind) are transparent for different names.
///
/// The resolution keeps a separate stack of ribs as it traverses the AST for each namespace. When
/// resolving, the name is looked up from inside out.
#[derive(Debug)]
pub(crate) struct Rib<'ra, R = Res> {
    pub bindings: IdentMap<R>,
    pub kind: RibKind<'ra>,
}

impl<'ra, R> Rib<'ra, R> {
    fn new(kind: RibKind<'ra>) -> Rib<'ra, R> {
        Rib { bindings: Default::default(), kind }
    }
}

#[derive(Clone, Copy, Debug)]
enum LifetimeUseSet {
    One { use_span: Span, use_ctxt: visit::LifetimeCtxt },
    Many,
}

#[derive(Copy, Clone, Debug)]
enum LifetimeRibKind {
    // -- Ribs introducing named lifetimes
    //
    /// This rib declares generic parameters.
    /// Only for this kind the `LifetimeRib::bindings` field can be non-empty.
    Generics { binder: NodeId, span: Span, kind: LifetimeBinderKind },

    // -- Ribs introducing unnamed lifetimes
    //
    /// Create a new anonymous lifetime parameter and reference it.
    ///
    /// If `report_in_path`, report an error when encountering lifetime elision in a path:
    /// ```compile_fail
    /// struct Foo<'a> { x: &'a () }
    /// async fn foo(x: Foo) {}
    /// ```
    ///
    /// Note: the error should not trigger when the elided lifetime is in a pattern or
    /// expression-position path:
    /// ```
    /// struct Foo<'a> { x: &'a () }
    /// async fn foo(Foo { x: _ }: Foo<'_>) {}
    /// ```
    AnonymousCreateParameter { binder: NodeId, report_in_path: bool },

    /// Replace all anonymous lifetimes by provided lifetime.
    Elided(LifetimeRes),

    // -- Barrier ribs that stop lifetime lookup, or continue it but produce an error later.
    //
    /// Give a hard error when either `&` or `'_` is written. Used to
    /// rule out things like `where T: Foo<'_>`. Does not imply an
    /// error on default object bounds (e.g., `Box<dyn Foo>`).
    AnonymousReportError,

    /// Resolves elided lifetimes to `'static` if there are no other lifetimes in scope,
    /// otherwise give a warning that the previous behavior of introducing a new early-bound
    /// lifetime is a bug and will be removed (if `emit_lint` is enabled).
    StaticIfNoLifetimeInScope { lint_id: NodeId, emit_lint: bool },

    /// Signal we cannot find which should be the anonymous lifetime.
    ElisionFailure,

    /// This rib forbids usage of generic parameters inside of const parameter types.
    ///
    /// While this is desirable to support eventually, it is difficult to do and so is
    /// currently forbidden. See rust-lang/project-const-generics#28 for more info.
    ConstParamTy,

    /// Usage of generic parameters is forbidden in various positions for anon consts:
    /// - const arguments when `generic_const_exprs` is not enabled
    /// - enum discriminant values
    ///
    /// This rib emits an error when a lifetime would resolve to a lifetime parameter.
    ConcreteAnonConst(NoConstantGenericsReason),

    /// This rib acts as a barrier to forbid reference to lifetimes of a parent item.
    Item,
}

#[derive(Copy, Clone, Debug)]
enum LifetimeBinderKind {
    BareFnType,
    PolyTrait,
    WhereBound,
    Item,
    ConstItem,
    Function,
    Closure,
    ImplBlock,
}

impl LifetimeBinderKind {
    fn descr(self) -> &'static str {
        use LifetimeBinderKind::*;
        match self {
            BareFnType => "type",
            PolyTrait => "bound",
            WhereBound => "bound",
            Item | ConstItem => "item",
            ImplBlock => "impl block",
            Function => "function",
            Closure => "closure",
        }
    }
}

#[derive(Debug)]
struct LifetimeRib {
    kind: LifetimeRibKind,
    // We need to preserve insertion order for async fns.
    bindings: FxIndexMap<Ident, (NodeId, LifetimeRes)>,
}

impl LifetimeRib {
    fn new(kind: LifetimeRibKind) -> LifetimeRib {
        LifetimeRib { bindings: Default::default(), kind }
    }
}

#[derive(Copy, Clone, PartialEq, Eq, Debug)]
pub(crate) enum AliasPossibility {
    No,
    Maybe,
}

#[derive(Copy, Clone, Debug)]
pub(crate) enum PathSource<'a> {
    // Type paths `Path`.
    Type,
    // Trait paths in bounds or impls.
    Trait(AliasPossibility),
    // Expression paths `path`, with optional parent context.
    Expr(Option<&'a Expr>),
    // Paths in path patterns `Path`.
    Pat,
    // Paths in struct expressions and patterns `Path { .. }`.
    Struct,
    // Paths in tuple struct patterns `Path(..)`.
    TupleStruct(Span, &'a [Span]),
    // `m::A::B` in `<T as m::A>::B::C`.
    TraitItem(Namespace),
    // Paths in delegation item
    Delegation,
    /// An arg in a `use<'a, N>` precise-capturing bound.
    PreciseCapturingArg(Namespace),
    // Paths that end with `(..)`, for return type notation.
    ReturnTypeNotation,
}

impl<'a> PathSource<'a> {
    fn namespace(self) -> Namespace {
        match self {
            PathSource::Type | PathSource::Trait(_) | PathSource::Struct => TypeNS,
            PathSource::Expr(..)
            | PathSource::Pat
            | PathSource::TupleStruct(..)
            | PathSource::Delegation
            | PathSource::ReturnTypeNotation => ValueNS,
            PathSource::TraitItem(ns) => ns,
            PathSource::PreciseCapturingArg(ns) => ns,
        }
    }

    fn defer_to_typeck(self) -> bool {
        match self {
            PathSource::Type
            | PathSource::Expr(..)
            | PathSource::Pat
            | PathSource::Struct
            | PathSource::TupleStruct(..)
            | PathSource::ReturnTypeNotation => true,
            PathSource::Trait(_)
            | PathSource::TraitItem(..)
            | PathSource::Delegation
            | PathSource::PreciseCapturingArg(..) => false,
        }
    }

    fn descr_expected(self) -> &'static str {
        match &self {
            PathSource::Type => "type",
            PathSource::Trait(_) => "trait",
            PathSource::Pat => "unit struct, unit variant or constant",
            PathSource::Struct => "struct, variant or union type",
            PathSource::TupleStruct(..) => "tuple struct or tuple variant",
            PathSource::TraitItem(ns) => match ns {
                TypeNS => "associated type",
                ValueNS => "method or associated constant",
                MacroNS => bug!("associated macro"),
            },
            PathSource::Expr(parent) => match parent.as_ref().map(|p| &p.kind) {
                // "function" here means "anything callable" rather than `DefKind::Fn`,
                // this is not precise but usually more helpful than just "value".
                Some(ExprKind::Call(call_expr, _)) => match &call_expr.kind {
                    // the case of `::some_crate()`
                    ExprKind::Path(_, path)
                        if let [segment, _] = path.segments.as_slice()
                            && segment.ident.name == kw::PathRoot =>
                    {
                        "external crate"
                    }
                    ExprKind::Path(_, path) => {
                        let mut msg = "function";
                        if let Some(segment) = path.segments.iter().last() {
                            if let Some(c) = segment.ident.to_string().chars().next() {
                                if c.is_uppercase() {
                                    msg = "function, tuple struct or tuple variant";
                                }
                            }
                        }
                        msg
                    }
                    _ => "function",
                },
                _ => "value",
            },
            PathSource::ReturnTypeNotation | PathSource::Delegation => "function",
            PathSource::PreciseCapturingArg(..) => "type or const parameter",
        }
    }

    fn is_call(self) -> bool {
        matches!(self, PathSource::Expr(Some(&Expr { kind: ExprKind::Call(..), .. })))
    }

    pub(crate) fn is_expected(self, res: Res) -> bool {
        match self {
            PathSource::Type => matches!(
                res,
                Res::Def(
                    DefKind::Struct
                        | DefKind::Union
                        | DefKind::Enum
                        | DefKind::Trait
                        | DefKind::TraitAlias
                        | DefKind::TyAlias
                        | DefKind::AssocTy
                        | DefKind::TyParam
                        | DefKind::OpaqueTy
                        | DefKind::ForeignTy,
                    _,
                ) | Res::PrimTy(..)
                    | Res::SelfTyParam { .. }
                    | Res::SelfTyAlias { .. }
            ),
            PathSource::Trait(AliasPossibility::No) => matches!(res, Res::Def(DefKind::Trait, _)),
            PathSource::Trait(AliasPossibility::Maybe) => {
                matches!(res, Res::Def(DefKind::Trait | DefKind::TraitAlias, _))
            }
            PathSource::Expr(..) => matches!(
                res,
                Res::Def(
                    DefKind::Ctor(_, CtorKind::Const | CtorKind::Fn)
                        | DefKind::Const
                        | DefKind::Static { .. }
                        | DefKind::Fn
                        | DefKind::AssocFn
                        | DefKind::AssocConst
                        | DefKind::ConstParam,
                    _,
                ) | Res::Local(..)
                    | Res::SelfCtor(..)
            ),
            PathSource::Pat => {
                res.expected_in_unit_struct_pat()
                    || matches!(res, Res::Def(DefKind::Const | DefKind::AssocConst, _))
            }
            PathSource::TupleStruct(..) => res.expected_in_tuple_struct_pat(),
            PathSource::Struct => matches!(
                res,
                Res::Def(
                    DefKind::Struct
                        | DefKind::Union
                        | DefKind::Variant
                        | DefKind::TyAlias
                        | DefKind::AssocTy,
                    _,
                ) | Res::SelfTyParam { .. }
                    | Res::SelfTyAlias { .. }
            ),
            PathSource::TraitItem(ns) => match res {
                Res::Def(DefKind::AssocConst | DefKind::AssocFn, _) if ns == ValueNS => true,
                Res::Def(DefKind::AssocTy, _) if ns == TypeNS => true,
                _ => false,
            },
            PathSource::ReturnTypeNotation => match res {
                Res::Def(DefKind::AssocFn, _) => true,
                _ => false,
            },
            PathSource::Delegation => matches!(res, Res::Def(DefKind::Fn | DefKind::AssocFn, _)),
            PathSource::PreciseCapturingArg(ValueNS) => {
                matches!(res, Res::Def(DefKind::ConstParam, _))
            }
            // We allow `SelfTyAlias` here so we can give a more descriptive error later.
            PathSource::PreciseCapturingArg(TypeNS) => matches!(
                res,
                Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }
            ),
            PathSource::PreciseCapturingArg(MacroNS) => false,
        }
    }

    fn error_code(self, has_unexpected_resolution: bool) -> ErrCode {
        match (self, has_unexpected_resolution) {
            (PathSource::Trait(_), true) => E0404,
            (PathSource::Trait(_), false) => E0405,
            (PathSource::Type, true) => E0573,
            (PathSource::Type, false) => E0412,
            (PathSource::Struct, true) => E0574,
            (PathSource::Struct, false) => E0422,
            (PathSource::Expr(..), true) | (PathSource::Delegation, true) => E0423,
            (PathSource::Expr(..), false) | (PathSource::Delegation, false) => E0425,
            (PathSource::Pat | PathSource::TupleStruct(..), true) => E0532,
            (PathSource::Pat | PathSource::TupleStruct(..), false) => E0531,
            (PathSource::TraitItem(..), true) | (PathSource::ReturnTypeNotation, true) => E0575,
            (PathSource::TraitItem(..), false) | (PathSource::ReturnTypeNotation, false) => E0576,
            (PathSource::PreciseCapturingArg(..), true) => E0799,
            (PathSource::PreciseCapturingArg(..), false) => E0800,
        }
    }
}

/// At this point for most items we can answer whether that item is exported or not,
/// but some items like impls require type information to determine exported-ness, so we make a
/// conservative estimate for them (e.g. based on nominal visibility).
#[derive(Clone, Copy)]
enum MaybeExported<'a> {
    Ok(NodeId),
    Impl(Option<DefId>),
    ImplItem(Result<DefId, &'a Visibility>),
    NestedUse(&'a Visibility),
}

impl MaybeExported<'_> {
    fn eval(self, r: &Resolver<'_, '_>) -> bool {
        let def_id = match self {
            MaybeExported::Ok(node_id) => Some(r.local_def_id(node_id)),
            MaybeExported::Impl(Some(trait_def_id)) | MaybeExported::ImplItem(Ok(trait_def_id)) => {
                trait_def_id.as_local()
            }
            MaybeExported::Impl(None) => return true,
            MaybeExported::ImplItem(Err(vis)) | MaybeExported::NestedUse(vis) => {
                return vis.kind.is_pub();
            }
        };
        def_id.map_or(true, |def_id| r.effective_visibilities.is_exported(def_id))
    }
}

/// Used for recording UnnecessaryQualification.
#[derive(Debug)]
pub(crate) struct UnnecessaryQualification<'ra> {
    pub binding: LexicalScopeBinding<'ra>,
    pub node_id: NodeId,
    pub path_span: Span,
    pub removal_span: Span,
}

#[derive(Default)]
struct DiagMetadata<'ast> {
    /// The current trait's associated items' ident, used for diagnostic suggestions.
    current_trait_assoc_items: Option<&'ast [P<AssocItem>]>,

    /// The current self type if inside an impl (used for better errors).
    current_self_type: Option<Ty>,

    /// The current self item if inside an ADT (used for better errors).
    current_self_item: Option<NodeId>,

    /// The current trait (used to suggest).
    current_item: Option<&'ast Item>,

    /// When processing generic arguments and encountering an unresolved ident not found,
    /// suggest introducing a type or const param depending on the context.
    currently_processing_generic_args: bool,

    /// The current enclosing (non-closure) function (used for better errors).
    current_function: Option<(FnKind<'ast>, Span)>,

    /// A list of labels as of yet unused. Labels will be removed from this map when
    /// they are used (in a `break` or `continue` statement)
    unused_labels: FxHashMap<NodeId, Span>,

    /// Only used for better errors on `let x = { foo: bar };`.
    /// In the case of a parse error with `let x = { foo: bar, };`, this isn't needed, it's only
    /// needed for cases where this parses as a correct type ascription.
    current_block_could_be_bare_struct_literal: Option<Span>,

    /// Only used for better errors on `let <pat>: <expr, not type>;`.
    current_let_binding: Option<(Span, Option<Span>, Option<Span>)>,

    current_pat: Option<&'ast Pat>,

    /// Used to detect possible `if let` written without `let` and to provide structured suggestion.
    in_if_condition: Option<&'ast Expr>,

    /// Used to detect possible new binding written without `let` and to provide structured suggestion.
    in_assignment: Option<&'ast Expr>,
    is_assign_rhs: bool,

    /// If we are setting an associated type in trait impl, is it a non-GAT type?
    in_non_gat_assoc_type: Option<bool>,

    /// Used to detect possible `.` -> `..` typo when calling methods.
    in_range: Option<(&'ast Expr, &'ast Expr)>,

    /// If we are currently in a trait object definition. Used to point at the bounds when
    /// encountering a struct or enum.
    current_trait_object: Option<&'ast [ast::GenericBound]>,

    /// Given `where <T as Bar>::Baz: String`, suggest `where T: Bar<Baz = String>`.
    current_where_predicate: Option<&'ast WherePredicate>,

    current_type_path: Option<&'ast Ty>,

    /// The current impl items (used to suggest).
    current_impl_items: Option<&'ast [P<AssocItem>]>,

    /// When processing impl trait
    currently_processing_impl_trait: Option<(TraitRef, Ty)>,

    /// Accumulate the errors due to missed lifetime elision,
    /// and report them all at once for each function.
    current_elision_failures: Vec<MissingLifetime>,
}

struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
    r: &'a mut Resolver<'ra, 'tcx>,

    /// The module that represents the current item scope.
    parent_scope: ParentScope<'ra>,

    /// The current set of local scopes for types and values.
    ribs: PerNS<Vec<Rib<'ra>>>,

    /// Previous popped `rib`, only used for diagnostic.
    last_block_rib: Option<Rib<'ra>>,

    /// The current set of local scopes, for labels.
    label_ribs: Vec<Rib<'ra, NodeId>>,

    /// The current set of local scopes for lifetimes.
    lifetime_ribs: Vec<LifetimeRib>,

    /// We are looking for lifetimes in an elision context.
    /// The set contains all the resolutions that we encountered so far.
    /// They will be used to determine the correct lifetime for the fn return type.
    /// The `LifetimeElisionCandidate` is used for diagnostics, to suggest introducing named
    /// lifetimes.
    lifetime_elision_candidates: Option<Vec<(LifetimeRes, LifetimeElisionCandidate)>>,

    /// The trait that the current context can refer to.
    current_trait_ref: Option<(Module<'ra>, TraitRef)>,

    /// Fields used to add information to diagnostic errors.
    diag_metadata: Box<DiagMetadata<'ast>>,

    /// State used to know whether to ignore resolution errors for function bodies.
    ///
    /// In particular, rustdoc uses this to avoid giving errors for `cfg()` items.
    /// In most cases this will be `None`, in which case errors will always be reported.
    /// If it is `true`, then it will be updated when entering a nested function or trait body.
    in_func_body: bool,

    /// Count the number of places a lifetime is used.
    lifetime_uses: FxHashMap<LocalDefId, LifetimeUseSet>,
}

/// Walks the whole crate in DFS order, visiting each item, resolving names as it goes.
impl<'ra: 'ast, 'ast, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
    fn visit_attribute(&mut self, _: &'ast Attribute) {
        // We do not want to resolve expressions that appear in attributes,
        // as they do not correspond to actual code.
    }
    fn visit_item(&mut self, item: &'ast Item) {
        let prev = replace(&mut self.diag_metadata.current_item, Some(item));
        // Always report errors in items we just entered.
        let old_ignore = replace(&mut self.in_func_body, false);
        self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item));
        self.in_func_body = old_ignore;
        self.diag_metadata.current_item = prev;
    }
    fn visit_arm(&mut self, arm: &'ast Arm) {
        self.resolve_arm(arm);
    }
    fn visit_block(&mut self, block: &'ast Block) {
        let old_macro_rules = self.parent_scope.macro_rules;
        self.resolve_block(block);
        self.parent_scope.macro_rules = old_macro_rules;
    }
    fn visit_anon_const(&mut self, _constant: &'ast AnonConst) {
        bug!("encountered anon const without a manual call to `resolve_anon_const`");
    }
    fn visit_expr(&mut self, expr: &'ast Expr) {
        self.resolve_expr(expr, None);
    }
    fn visit_pat(&mut self, p: &'ast Pat) {
        let prev = self.diag_metadata.current_pat;
        self.diag_metadata.current_pat = Some(p);
        visit::walk_pat(self, p);
        self.diag_metadata.current_pat = prev;
    }
    fn visit_local(&mut self, local: &'ast Local) {
        let local_spans = match local.pat.kind {
            // We check for this to avoid tuple struct fields.
            PatKind::Wild => None,
            _ => Some((
                local.pat.span,
                local.ty.as_ref().map(|ty| ty.span),
                local.kind.init().map(|init| init.span),
            )),
        };
        let original = replace(&mut self.diag_metadata.current_let_binding, local_spans);
        self.resolve_local(local);
        self.diag_metadata.current_let_binding = original;
    }
    fn visit_ty(&mut self, ty: &'ast Ty) {
        let prev = self.diag_metadata.current_trait_object;
        let prev_ty = self.diag_metadata.current_type_path;
        match &ty.kind {
            TyKind::Ref(None, _) | TyKind::PinnedRef(None, _) => {
                // Elided lifetime in reference: we resolve as if there was some lifetime `'_` with
                // NodeId `ty.id`.
                // This span will be used in case of elision failure.
                let span = self.r.tcx.sess.source_map().start_point(ty.span);
                self.resolve_elided_lifetime(ty.id, span);
                visit::walk_ty(self, ty);
            }
            TyKind::Path(qself, path) => {
                self.diag_metadata.current_type_path = Some(ty);

                // If we have a path that ends with `(..)`, then it must be
                // return type notation. Resolve that path in the *value*
                // namespace.
                let source = if let Some(seg) = path.segments.last()
                    && let Some(args) = &seg.args
                    && matches!(**args, GenericArgs::ParenthesizedElided(..))
                {
                    PathSource::ReturnTypeNotation
                } else {
                    PathSource::Type
                };

                self.smart_resolve_path(ty.id, qself, path, source);

                // Check whether we should interpret this as a bare trait object.
                if qself.is_none()
                    && let Some(partial_res) = self.r.partial_res_map.get(&ty.id)
                    && let Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) =
                        partial_res.full_res()
                {
                    // This path is actually a bare trait object. In case of a bare `Fn`-trait
                    // object with anonymous lifetimes, we need this rib to correctly place the
                    // synthetic lifetimes.
                    let span = ty.span.shrink_to_lo().to(path.span.shrink_to_lo());
                    self.with_generic_param_rib(
                        &[],
                        RibKind::Normal,
                        LifetimeRibKind::Generics {
                            binder: ty.id,
                            kind: LifetimeBinderKind::PolyTrait,
                            span,
                        },
                        |this| this.visit_path(path, ty.id),
                    );
                } else {
                    visit::walk_ty(self, ty)
                }
            }
            TyKind::ImplicitSelf => {
                let self_ty = Ident::with_dummy_span(kw::SelfUpper);
                let res = self
                    .resolve_ident_in_lexical_scope(
                        self_ty,
                        TypeNS,
                        Some(Finalize::new(ty.id, ty.span)),
                        None,
                    )
                    .map_or(Res::Err, |d| d.res());
                self.r.record_partial_res(ty.id, PartialRes::new(res));
                visit::walk_ty(self, ty)
            }
            TyKind::ImplTrait(node_id, _) => {
                let candidates = self.lifetime_elision_candidates.take();
                visit::walk_ty(self, ty);
                self.record_lifetime_params_for_impl_trait(*node_id);
                self.lifetime_elision_candidates = candidates;
            }
            TyKind::TraitObject(bounds, ..) => {
                self.diag_metadata.current_trait_object = Some(&bounds[..]);
                visit::walk_ty(self, ty)
            }
            TyKind::BareFn(bare_fn) => {
                let span = ty.span.shrink_to_lo().to(bare_fn.decl_span.shrink_to_lo());
                self.with_generic_param_rib(
                    &bare_fn.generic_params,
                    RibKind::Normal,
                    LifetimeRibKind::Generics {
                        binder: ty.id,
                        kind: LifetimeBinderKind::BareFnType,
                        span,
                    },
                    |this| {
                        this.visit_generic_params(&bare_fn.generic_params, false);
                        this.with_lifetime_rib(
                            LifetimeRibKind::AnonymousCreateParameter {
                                binder: ty.id,
                                report_in_path: false,
                            },
                            |this| {
                                this.resolve_fn_signature(
                                    ty.id,
                                    false,
                                    // We don't need to deal with patterns in parameters, because
                                    // they are not possible for foreign or bodiless functions.
                                    bare_fn
                                        .decl
                                        .inputs
                                        .iter()
                                        .map(|Param { ty, .. }| (None, &**ty)),
                                    &bare_fn.decl.output,
                                )
                            },
                        );
                    },
                )
            }
            TyKind::Array(element_ty, length) => {
                self.visit_ty(element_ty);
                self.resolve_anon_const(length, AnonConstKind::ConstArg(IsRepeatExpr::No));
            }
            TyKind::Typeof(ct) => {
                self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
            }
            _ => visit::walk_ty(self, ty),
        }
        self.diag_metadata.current_trait_object = prev;
        self.diag_metadata.current_type_path = prev_ty;
    }
    fn visit_poly_trait_ref(&mut self, tref: &'ast PolyTraitRef) {
        let span = tref.span.shrink_to_lo().to(tref.trait_ref.path.span.shrink_to_lo());
        self.with_generic_param_rib(
            &tref.bound_generic_params,
            RibKind::Normal,
            LifetimeRibKind::Generics {
                binder: tref.trait_ref.ref_id,
                kind: LifetimeBinderKind::PolyTrait,
                span,
            },
            |this| {
                this.visit_generic_params(&tref.bound_generic_params, false);
                this.smart_resolve_path(
                    tref.trait_ref.ref_id,
                    &None,
                    &tref.trait_ref.path,
                    PathSource::Trait(AliasPossibility::Maybe),
                );
                this.visit_trait_ref(&tref.trait_ref);
            },
        );
    }
    fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) {
        self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id));
        let def_kind = self.r.local_def_kind(foreign_item.id);
        match foreign_item.kind {
            ForeignItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
                    LifetimeRibKind::Generics {
                        binder: foreign_item.id,
                        kind: LifetimeBinderKind::Item,
                        span: generics.span,
                    },
                    |this| visit::walk_item(this, foreign_item),
                );
            }
            ForeignItemKind::Fn(box Fn { ref generics, .. }) => {
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
                    LifetimeRibKind::Generics {
                        binder: foreign_item.id,
                        kind: LifetimeBinderKind::Function,
                        span: generics.span,
                    },
                    |this| visit::walk_item(this, foreign_item),
                );
            }
            ForeignItemKind::Static(..) => {
                self.with_static_rib(def_kind, |this| visit::walk_item(this, foreign_item))
            }
            ForeignItemKind::MacCall(..) => {
                panic!("unexpanded macro in resolve!")
            }
        }
    }
    fn visit_fn(&mut self, fn_kind: FnKind<'ast>, sp: Span, fn_id: NodeId) {
        let previous_value = self.diag_metadata.current_function;
        match fn_kind {
            // Bail if the function is foreign, and thus cannot validly have
            // a body, or if there's no body for some other reason.
            FnKind::Fn(FnCtxt::Foreign, _, sig, _, generics, _)
            | FnKind::Fn(_, _, sig, _, generics, None) => {
                self.visit_fn_header(&sig.header);
                self.visit_generics(generics);
                self.with_lifetime_rib(
                    LifetimeRibKind::AnonymousCreateParameter {
                        binder: fn_id,
                        report_in_path: false,
                    },
                    |this| {
                        this.resolve_fn_signature(
                            fn_id,
                            sig.decl.has_self(),
                            sig.decl.inputs.iter().map(|Param { ty, .. }| (None, &**ty)),
                            &sig.decl.output,
                        );

                        if let Some((coro_node_id, _)) = sig
                            .header
                            .coroutine_kind
                            .map(|coroutine_kind| coroutine_kind.return_id())
                        {
                            this.record_lifetime_params_for_impl_trait(coro_node_id);
                        }
                    },
                );
                return;
            }
            FnKind::Fn(..) => {
                self.diag_metadata.current_function = Some((fn_kind, sp));
            }
            // Do not update `current_function` for closures: it suggests `self` parameters.
            FnKind::Closure(..) => {}
        };
        debug!("(resolving function) entering function");

        // Create a value rib for the function.
        self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
            // Create a label rib for the function.
            this.with_label_rib(RibKind::FnOrCoroutine, |this| {
                match fn_kind {
                    FnKind::Fn(_, _, sig, _, generics, body) => {
                        this.visit_generics(generics);

                        let declaration = &sig.decl;
                        let coro_node_id = sig
                            .header
                            .coroutine_kind
                            .map(|coroutine_kind| coroutine_kind.return_id());

                        this.with_lifetime_rib(
                            LifetimeRibKind::AnonymousCreateParameter {
                                binder: fn_id,
                                report_in_path: coro_node_id.is_some(),
                            },
                            |this| {
                                this.resolve_fn_signature(
                                    fn_id,
                                    declaration.has_self(),
                                    declaration
                                        .inputs
                                        .iter()
                                        .map(|Param { pat, ty, .. }| (Some(&**pat), &**ty)),
                                    &declaration.output,
                                );

                                if let Some((async_node_id, _)) = coro_node_id {
                                    this.record_lifetime_params_for_impl_trait(async_node_id);
                                }
                            },
                        );

                        if let Some(body) = body {
                            // Ignore errors in function bodies if this is rustdoc
                            // Be sure not to set this until the function signature has been resolved.
                            let previous_state = replace(&mut this.in_func_body, true);
                            // We only care block in the same function
                            this.last_block_rib = None;
                            // Resolve the function body, potentially inside the body of an async closure
                            this.with_lifetime_rib(
                                LifetimeRibKind::Elided(LifetimeRes::Infer),
                                |this| this.visit_block(body),
                            );

                            debug!("(resolving function) leaving function");
                            this.in_func_body = previous_state;
                        }
                    }
                    FnKind::Closure(binder, _, declaration, body) => {
                        this.visit_closure_binder(binder);

                        this.with_lifetime_rib(
                            match binder {
                                // We do not have any explicit generic lifetime parameter.
                                ClosureBinder::NotPresent => {
                                    LifetimeRibKind::AnonymousCreateParameter {
                                        binder: fn_id,
                                        report_in_path: false,
                                    }
                                }
                                ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
                            },
                            // Add each argument to the rib.
                            |this| this.resolve_params(&declaration.inputs),
                        );
                        this.with_lifetime_rib(
                            match binder {
                                ClosureBinder::NotPresent => {
                                    LifetimeRibKind::Elided(LifetimeRes::Infer)
                                }
                                ClosureBinder::For { .. } => LifetimeRibKind::AnonymousReportError,
                            },
                            |this| visit::walk_fn_ret_ty(this, &declaration.output),
                        );

                        // Ignore errors in function bodies if this is rustdoc
                        // Be sure not to set this until the function signature has been resolved.
                        let previous_state = replace(&mut this.in_func_body, true);
                        // Resolve the function body, potentially inside the body of an async closure
                        this.with_lifetime_rib(
                            LifetimeRibKind::Elided(LifetimeRes::Infer),
                            |this| this.visit_expr(body),
                        );

                        debug!("(resolving function) leaving function");
                        this.in_func_body = previous_state;
                    }
                }
            })
        });
        self.diag_metadata.current_function = previous_value;
    }

    fn visit_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
        self.resolve_lifetime(lifetime, use_ctxt)
    }

    fn visit_precise_capturing_arg(&mut self, arg: &'ast PreciseCapturingArg) {
        match arg {
            // Lower the lifetime regularly; we'll resolve the lifetime and check
            // it's a parameter later on in HIR lowering.
            PreciseCapturingArg::Lifetime(_) => {}

            PreciseCapturingArg::Arg(path, id) => {
                // we want `impl use<C>` to try to resolve `C` as both a type parameter or
                // a const parameter. Since the resolver specifically doesn't allow having
                // two generic params with the same name, even if they're a different namespace,
                // it doesn't really matter which we try resolving first, but just like
                // `Ty::Param` we just fall back to the value namespace only if it's missing
                // from the type namespace.
                let mut check_ns = |ns| {
                    self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns).is_some()
                };
                // Like `Ty::Param`, we try resolving this as both a const and a type.
                if !check_ns(TypeNS) && check_ns(ValueNS) {
                    self.smart_resolve_path(
                        *id,
                        &None,
                        path,
                        PathSource::PreciseCapturingArg(ValueNS),
                    );
                } else {
                    self.smart_resolve_path(
                        *id,
                        &None,
                        path,
                        PathSource::PreciseCapturingArg(TypeNS),
                    );
                }
            }
        }

        visit::walk_precise_capturing_arg(self, arg)
    }

    fn visit_generics(&mut self, generics: &'ast Generics) {
        self.visit_generic_params(&generics.params, self.diag_metadata.current_self_item.is_some());
        for p in &generics.where_clause.predicates {
            self.visit_where_predicate(p);
        }
    }

    fn visit_closure_binder(&mut self, b: &'ast ClosureBinder) {
        match b {
            ClosureBinder::NotPresent => {}
            ClosureBinder::For { generic_params, .. } => {
                self.visit_generic_params(
                    generic_params,
                    self.diag_metadata.current_self_item.is_some(),
                );
            }
        }
    }

    fn visit_generic_arg(&mut self, arg: &'ast GenericArg) {
        debug!("visit_generic_arg({:?})", arg);
        let prev = replace(&mut self.diag_metadata.currently_processing_generic_args, true);
        match arg {
            GenericArg::Type(ref ty) => {
                // We parse const arguments as path types as we cannot distinguish them during
                // parsing. We try to resolve that ambiguity by attempting resolution the type
                // namespace first, and if that fails we try again in the value namespace. If
                // resolution in the value namespace succeeds, we have an generic const argument on
                // our hands.
                if let TyKind::Path(None, ref path) = ty.kind {
                    // We cannot disambiguate multi-segment paths right now as that requires type
                    // checking.
                    if path.is_potential_trivial_const_arg() {
                        let mut check_ns = |ns| {
                            self.maybe_resolve_ident_in_lexical_scope(path.segments[0].ident, ns)
                                .is_some()
                        };
                        if !check_ns(TypeNS) && check_ns(ValueNS) {
                            self.resolve_anon_const_manual(
                                true,
                                AnonConstKind::ConstArg(IsRepeatExpr::No),
                                |this| {
                                    this.smart_resolve_path(
                                        ty.id,
                                        &None,
                                        path,
                                        PathSource::Expr(None),
                                    );
                                    this.visit_path(path, ty.id);
                                },
                            );

                            self.diag_metadata.currently_processing_generic_args = prev;
                            return;
                        }
                    }
                }

                self.visit_ty(ty);
            }
            GenericArg::Lifetime(lt) => self.visit_lifetime(lt, visit::LifetimeCtxt::GenericArg),
            GenericArg::Const(ct) => {
                self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::No))
            }
        }
        self.diag_metadata.currently_processing_generic_args = prev;
    }

    fn visit_assoc_item_constraint(&mut self, constraint: &'ast AssocItemConstraint) {
        self.visit_ident(constraint.ident);
        if let Some(ref gen_args) = constraint.gen_args {
            // Forbid anonymous lifetimes in GAT parameters until proper semantics are decided.
            self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
                this.visit_generic_args(gen_args)
            });
        }
        match constraint.kind {
            AssocItemConstraintKind::Equality { ref term } => match term {
                Term::Ty(ty) => self.visit_ty(ty),
                Term::Const(c) => {
                    self.resolve_anon_const(c, AnonConstKind::ConstArg(IsRepeatExpr::No))
                }
            },
            AssocItemConstraintKind::Bound { ref bounds } => {
                self.record_lifetime_params_for_impl_trait(constraint.id);
                walk_list!(self, visit_param_bound, bounds, BoundKind::Bound);
            }
        }
    }

    fn visit_path_segment(&mut self, path_segment: &'ast PathSegment) {
        if let Some(ref args) = path_segment.args {
            match &**args {
                GenericArgs::AngleBracketed(..) => visit::walk_generic_args(self, args),
                GenericArgs::Parenthesized(p_args) => {
                    // Probe the lifetime ribs to know how to behave.
                    for rib in self.lifetime_ribs.iter().rev() {
                        match rib.kind {
                            // We are inside a `PolyTraitRef`. The lifetimes are
                            // to be introduced in that (maybe implicit) `for<>` binder.
                            LifetimeRibKind::Generics {
                                binder,
                                kind: LifetimeBinderKind::PolyTrait,
                                ..
                            } => {
                                self.with_lifetime_rib(
                                    LifetimeRibKind::AnonymousCreateParameter {
                                        binder,
                                        report_in_path: false,
                                    },
                                    |this| {
                                        this.resolve_fn_signature(
                                            binder,
                                            false,
                                            p_args.inputs.iter().map(|ty| (None, &**ty)),
                                            &p_args.output,
                                        )
                                    },
                                );
                                break;
                            }
                            // We have nowhere to introduce generics. Code is malformed,
                            // so use regular lifetime resolution to avoid spurious errors.
                            LifetimeRibKind::Item | LifetimeRibKind::Generics { .. } => {
                                visit::walk_generic_args(self, args);
                                break;
                            }
                            LifetimeRibKind::AnonymousCreateParameter { .. }
                            | LifetimeRibKind::AnonymousReportError
                            | LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
                            | LifetimeRibKind::Elided(_)
                            | LifetimeRibKind::ElisionFailure
                            | LifetimeRibKind::ConcreteAnonConst(_)
                            | LifetimeRibKind::ConstParamTy => {}
                        }
                    }
                }
                GenericArgs::ParenthesizedElided(_) => {}
            }
        }
    }

    fn visit_where_predicate(&mut self, p: &'ast WherePredicate) {
        debug!("visit_where_predicate {:?}", p);
        let previous_value = replace(&mut self.diag_metadata.current_where_predicate, Some(p));
        self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
            if let WherePredicate::BoundPredicate(WhereBoundPredicate {
                ref bounded_ty,
                ref bounds,
                ref bound_generic_params,
                span: predicate_span,
                ..
            }) = p
            {
                let span = predicate_span.shrink_to_lo().to(bounded_ty.span.shrink_to_lo());
                this.with_generic_param_rib(
                    bound_generic_params,
                    RibKind::Normal,
                    LifetimeRibKind::Generics {
                        binder: bounded_ty.id,
                        kind: LifetimeBinderKind::WhereBound,
                        span,
                    },
                    |this| {
                        this.visit_generic_params(bound_generic_params, false);
                        this.visit_ty(bounded_ty);
                        for bound in bounds {
                            this.visit_param_bound(bound, BoundKind::Bound)
                        }
                    },
                );
            } else {
                visit::walk_where_predicate(this, p);
            }
        });
        self.diag_metadata.current_where_predicate = previous_value;
    }

    fn visit_inline_asm(&mut self, asm: &'ast InlineAsm) {
        for (op, _) in &asm.operands {
            match op {
                InlineAsmOperand::In { expr, .. }
                | InlineAsmOperand::Out { expr: Some(expr), .. }
                | InlineAsmOperand::InOut { expr, .. } => self.visit_expr(expr),
                InlineAsmOperand::Out { expr: None, .. } => {}
                InlineAsmOperand::SplitInOut { in_expr, out_expr, .. } => {
                    self.visit_expr(in_expr);
                    if let Some(out_expr) = out_expr {
                        self.visit_expr(out_expr);
                    }
                }
                InlineAsmOperand::Const { anon_const, .. } => {
                    // Although this is `DefKind::AnonConst`, it is allowed to reference outer
                    // generic parameters like an inline const.
                    self.resolve_anon_const(anon_const, AnonConstKind::InlineConst);
                }
                InlineAsmOperand::Sym { sym } => self.visit_inline_asm_sym(sym),
                InlineAsmOperand::Label { block } => self.visit_block(block),
            }
        }
    }

    fn visit_inline_asm_sym(&mut self, sym: &'ast InlineAsmSym) {
        // This is similar to the code for AnonConst.
        self.with_rib(ValueNS, RibKind::InlineAsmSym, |this| {
            this.with_rib(TypeNS, RibKind::InlineAsmSym, |this| {
                this.with_label_rib(RibKind::InlineAsmSym, |this| {
                    this.smart_resolve_path(sym.id, &sym.qself, &sym.path, PathSource::Expr(None));
                    visit::walk_inline_asm_sym(this, sym);
                });
            })
        });
    }

    fn visit_variant(&mut self, v: &'ast Variant) {
        self.resolve_doc_links(&v.attrs, MaybeExported::Ok(v.id));
        visit::walk_variant(self, v)
    }

    fn visit_variant_discr(&mut self, discr: &'ast AnonConst) {
        self.resolve_anon_const(discr, AnonConstKind::EnumDiscriminant);
    }

    fn visit_field_def(&mut self, f: &'ast FieldDef) {
        self.resolve_doc_links(&f.attrs, MaybeExported::Ok(f.id));
        visit::walk_field_def(self, f)
    }
}

impl<'a, 'ast, 'ra: 'ast, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
    fn new(resolver: &'a mut Resolver<'ra, 'tcx>) -> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
        // During late resolution we only track the module component of the parent scope,
        // although it may be useful to track other components as well for diagnostics.
        let graph_root = resolver.graph_root;
        let parent_scope = ParentScope::module(graph_root, resolver);
        let start_rib_kind = RibKind::Module(graph_root);
        LateResolutionVisitor {
            r: resolver,
            parent_scope,
            ribs: PerNS {
                value_ns: vec![Rib::new(start_rib_kind)],
                type_ns: vec![Rib::new(start_rib_kind)],
                macro_ns: vec![Rib::new(start_rib_kind)],
            },
            last_block_rib: None,
            label_ribs: Vec::new(),
            lifetime_ribs: Vec::new(),
            lifetime_elision_candidates: None,
            current_trait_ref: None,
            diag_metadata: Default::default(),
            // errors at module scope should always be reported
            in_func_body: false,
            lifetime_uses: Default::default(),
        }
    }

    fn maybe_resolve_ident_in_lexical_scope(
        &mut self,
        ident: Ident,
        ns: Namespace,
    ) -> Option<LexicalScopeBinding<'ra>> {
        self.r.resolve_ident_in_lexical_scope(
            ident,
            ns,
            &self.parent_scope,
            None,
            &self.ribs[ns],
            None,
        )
    }

    fn resolve_ident_in_lexical_scope(
        &mut self,
        ident: Ident,
        ns: Namespace,
        finalize: Option<Finalize>,
        ignore_binding: Option<NameBinding<'ra>>,
    ) -> Option<LexicalScopeBinding<'ra>> {
        self.r.resolve_ident_in_lexical_scope(
            ident,
            ns,
            &self.parent_scope,
            finalize,
            &self.ribs[ns],
            ignore_binding,
        )
    }

    fn resolve_path(
        &mut self,
        path: &[Segment],
        opt_ns: Option<Namespace>, // `None` indicates a module path in import
        finalize: Option<Finalize>,
    ) -> PathResult<'ra> {
        self.r.resolve_path_with_ribs(
            path,
            opt_ns,
            &self.parent_scope,
            finalize,
            Some(&self.ribs),
            None,
            None,
        )
    }

    // AST resolution
    //
    // We maintain a list of value ribs and type ribs.
    //
    // Simultaneously, we keep track of the current position in the module
    // graph in the `parent_scope.module` pointer. When we go to resolve a name in
    // the value or type namespaces, we first look through all the ribs and
    // then query the module graph. When we resolve a name in the module
    // namespace, we can skip all the ribs (since nested modules are not
    // allowed within blocks in Rust) and jump straight to the current module
    // graph node.
    //
    // Named implementations are handled separately. When we find a method
    // call, we consult the module node to find all of the implementations in
    // scope. This information is lazily cached in the module node. We then
    // generate a fake "implementation scope" containing all the
    // implementations thus found, for compatibility with old resolve pass.

    /// Do some `work` within a new innermost rib of the given `kind` in the given namespace (`ns`).
    fn with_rib<T>(
        &mut self,
        ns: Namespace,
        kind: RibKind<'ra>,
        work: impl FnOnce(&mut Self) -> T,
    ) -> T {
        self.ribs[ns].push(Rib::new(kind));
        let ret = work(self);
        self.ribs[ns].pop();
        ret
    }

    fn with_scope<T>(&mut self, id: NodeId, f: impl FnOnce(&mut Self) -> T) -> T {
        if let Some(module) = self.r.get_module(self.r.local_def_id(id).to_def_id()) {
            // Move down in the graph.
            let orig_module = replace(&mut self.parent_scope.module, module);
            self.with_rib(ValueNS, RibKind::Module(module), |this| {
                this.with_rib(TypeNS, RibKind::Module(module), |this| {
                    let ret = f(this);
                    this.parent_scope.module = orig_module;
                    ret
                })
            })
        } else {
            f(self)
        }
    }

    fn visit_generic_params(&mut self, params: &'ast [GenericParam], add_self_upper: bool) {
        // For type parameter defaults, we have to ban access
        // to following type parameters, as the GenericArgs can only
        // provide previous type parameters as they're built. We
        // put all the parameters on the ban list and then remove
        // them one by one as they are processed and become available.
        let mut forward_ty_ban_rib = Rib::new(RibKind::ForwardGenericParamBan);
        let mut forward_const_ban_rib = Rib::new(RibKind::ForwardGenericParamBan);
        for param in params.iter() {
            match param.kind {
                GenericParamKind::Type { .. } => {
                    forward_ty_ban_rib
                        .bindings
                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
                }
                GenericParamKind::Const { .. } => {
                    forward_const_ban_rib
                        .bindings
                        .insert(Ident::with_dummy_span(param.ident.name), Res::Err);
                }
                GenericParamKind::Lifetime => {}
            }
        }

        // rust-lang/rust#61631: The type `Self` is essentially
        // another type parameter. For ADTs, we consider it
        // well-defined only after all of the ADT type parameters have
        // been provided. Therefore, we do not allow use of `Self`
        // anywhere in ADT type parameter defaults.
        //
        // (We however cannot ban `Self` for defaults on *all* generic
        // lists; e.g. trait generics can usefully refer to `Self`,
        // such as in the case of `trait Add<Rhs = Self>`.)
        if add_self_upper {
            // (`Some` if + only if we are in ADT's generics.)
            forward_ty_ban_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), Res::Err);
        }

        self.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
            for param in params {
                match param.kind {
                    GenericParamKind::Lifetime => {
                        for bound in &param.bounds {
                            this.visit_param_bound(bound, BoundKind::Bound);
                        }
                    }
                    GenericParamKind::Type { ref default } => {
                        for bound in &param.bounds {
                            this.visit_param_bound(bound, BoundKind::Bound);
                        }

                        if let Some(ref ty) = default {
                            this.ribs[TypeNS].push(forward_ty_ban_rib);
                            this.ribs[ValueNS].push(forward_const_ban_rib);
                            this.visit_ty(ty);
                            forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
                            forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
                        }

                        // Allow all following defaults to refer to this type parameter.
                        forward_ty_ban_rib
                            .bindings
                            .remove(&Ident::with_dummy_span(param.ident.name));
                    }
                    GenericParamKind::Const { ref ty, kw_span: _, ref default } => {
                        // Const parameters can't have param bounds.
                        assert!(param.bounds.is_empty());

                        this.ribs[TypeNS].push(Rib::new(RibKind::ConstParamTy));
                        this.ribs[ValueNS].push(Rib::new(RibKind::ConstParamTy));
                        this.with_lifetime_rib(LifetimeRibKind::ConstParamTy, |this| {
                            this.visit_ty(ty)
                        });
                        this.ribs[TypeNS].pop().unwrap();
                        this.ribs[ValueNS].pop().unwrap();

                        if let Some(ref expr) = default {
                            this.ribs[TypeNS].push(forward_ty_ban_rib);
                            this.ribs[ValueNS].push(forward_const_ban_rib);
                            this.resolve_anon_const(
                                expr,
                                AnonConstKind::ConstArg(IsRepeatExpr::No),
                            );
                            forward_const_ban_rib = this.ribs[ValueNS].pop().unwrap();
                            forward_ty_ban_rib = this.ribs[TypeNS].pop().unwrap();
                        }

                        // Allow all following defaults to refer to this const parameter.
                        forward_const_ban_rib
                            .bindings
                            .remove(&Ident::with_dummy_span(param.ident.name));
                    }
                }
            }
        })
    }

    #[instrument(level = "debug", skip(self, work))]
    fn with_lifetime_rib<T>(
        &mut self,
        kind: LifetimeRibKind,
        work: impl FnOnce(&mut Self) -> T,
    ) -> T {
        self.lifetime_ribs.push(LifetimeRib::new(kind));
        let outer_elision_candidates = self.lifetime_elision_candidates.take();
        let ret = work(self);
        self.lifetime_elision_candidates = outer_elision_candidates;
        self.lifetime_ribs.pop();
        ret
    }

    #[instrument(level = "debug", skip(self))]
    fn resolve_lifetime(&mut self, lifetime: &'ast Lifetime, use_ctxt: visit::LifetimeCtxt) {
        let ident = lifetime.ident;

        if ident.name == kw::StaticLifetime {
            self.record_lifetime_res(
                lifetime.id,
                LifetimeRes::Static { suppress_elision_warning: false },
                LifetimeElisionCandidate::Named,
            );
            return;
        }

        if ident.name == kw::UnderscoreLifetime {
            return self.resolve_anonymous_lifetime(lifetime, lifetime.id, false);
        }

        let mut lifetime_rib_iter = self.lifetime_ribs.iter().rev();
        while let Some(rib) = lifetime_rib_iter.next() {
            let normalized_ident = ident.normalize_to_macros_2_0();
            if let Some(&(_, res)) = rib.bindings.get(&normalized_ident) {
                self.record_lifetime_res(lifetime.id, res, LifetimeElisionCandidate::Named);

                if let LifetimeRes::Param { param, binder } = res {
                    match self.lifetime_uses.entry(param) {
                        Entry::Vacant(v) => {
                            debug!("First use of {:?} at {:?}", res, ident.span);
                            let use_set = self
                                .lifetime_ribs
                                .iter()
                                .rev()
                                .find_map(|rib| match rib.kind {
                                    // Do not suggest eliding a lifetime where an anonymous
                                    // lifetime would be illegal.
                                    LifetimeRibKind::Item
                                    | LifetimeRibKind::AnonymousReportError
                                    | LifetimeRibKind::StaticIfNoLifetimeInScope { .. }
                                    | LifetimeRibKind::ElisionFailure => Some(LifetimeUseSet::Many),
                                    // An anonymous lifetime is legal here, and bound to the right
                                    // place, go ahead.
                                    LifetimeRibKind::AnonymousCreateParameter {
                                        binder: anon_binder,
                                        ..
                                    } => Some(if binder == anon_binder {
                                        LifetimeUseSet::One { use_span: ident.span, use_ctxt }
                                    } else {
                                        LifetimeUseSet::Many
                                    }),
                                    // Only report if eliding the lifetime would have the same
                                    // semantics.
                                    LifetimeRibKind::Elided(r) => Some(if res == r {
                                        LifetimeUseSet::One { use_span: ident.span, use_ctxt }
                                    } else {
                                        LifetimeUseSet::Many
                                    }),
                                    LifetimeRibKind::Generics { .. }
                                    | LifetimeRibKind::ConstParamTy => None,
                                    LifetimeRibKind::ConcreteAnonConst(_) => {
                                        span_bug!(ident.span, "unexpected rib kind: {:?}", rib.kind)
                                    }
                                })
                                .unwrap_or(LifetimeUseSet::Many);
                            debug!(?use_ctxt, ?use_set);
                            v.insert(use_set);
                        }
                        Entry::Occupied(mut o) => {
                            debug!("Many uses of {:?} at {:?}", res, ident.span);
                            *o.get_mut() = LifetimeUseSet::Many;
                        }
                    }
                }
                return;
            }

            match rib.kind {
                LifetimeRibKind::Item => break,
                LifetimeRibKind::ConstParamTy => {
                    self.emit_non_static_lt_in_const_param_ty_error(lifetime);
                    self.record_lifetime_res(
                        lifetime.id,
                        LifetimeRes::Error,
                        LifetimeElisionCandidate::Ignore,
                    );
                    return;
                }
                LifetimeRibKind::ConcreteAnonConst(cause) => {
                    self.emit_forbidden_non_static_lifetime_error(cause, lifetime);
                    self.record_lifetime_res(
                        lifetime.id,
                        LifetimeRes::Error,
                        LifetimeElisionCandidate::Ignore,
                    );
                    return;
                }
                LifetimeRibKind::AnonymousCreateParameter { .. }
                | LifetimeRibKind::Elided(_)
                | LifetimeRibKind::Generics { .. }
                | LifetimeRibKind::ElisionFailure
                | LifetimeRibKind::AnonymousReportError
                | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {}
            }
        }

        let mut outer_res = None;
        for rib in lifetime_rib_iter {
            let normalized_ident = ident.normalize_to_macros_2_0();
            if let Some((&outer, _)) = rib.bindings.get_key_value(&normalized_ident) {
                outer_res = Some(outer);
                break;
            }
        }

        self.emit_undeclared_lifetime_error(lifetime, outer_res);
        self.record_lifetime_res(lifetime.id, LifetimeRes::Error, LifetimeElisionCandidate::Named);
    }

    #[instrument(level = "debug", skip(self))]
    fn resolve_anonymous_lifetime(
        &mut self,
        lifetime: &Lifetime,
        id_for_lint: NodeId,
        elided: bool,
    ) {
        debug_assert_eq!(lifetime.ident.name, kw::UnderscoreLifetime);

        let kind =
            if elided { MissingLifetimeKind::Ampersand } else { MissingLifetimeKind::Underscore };
        let missing_lifetime = MissingLifetime {
            id: lifetime.id,
            span: lifetime.ident.span,
            kind,
            count: 1,
            id_for_lint,
        };
        let elision_candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
        for (i, rib) in self.lifetime_ribs.iter().enumerate().rev() {
            debug!(?rib.kind);
            match rib.kind {
                LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
                    let res = self.create_fresh_lifetime(lifetime.ident, binder, kind);
                    self.record_lifetime_res(lifetime.id, res, elision_candidate);
                    return;
                }
                LifetimeRibKind::StaticIfNoLifetimeInScope { lint_id: node_id, emit_lint } => {
                    let mut lifetimes_in_scope = vec![];
                    for rib in &self.lifetime_ribs[..i] {
                        lifetimes_in_scope.extend(rib.bindings.iter().map(|(ident, _)| ident.span));
                        // Consider any anonymous lifetimes, too
                        if let LifetimeRibKind::AnonymousCreateParameter { binder, .. } = rib.kind
                            && let Some(extra) = self.r.extra_lifetime_params_map.get(&binder)
                        {
                            lifetimes_in_scope.extend(extra.iter().map(|(ident, _, _)| ident.span));
                        }
                    }
                    if lifetimes_in_scope.is_empty() {
                        self.record_lifetime_res(
                            lifetime.id,
                            // We are inside a const item, so do not warn.
                            LifetimeRes::Static { suppress_elision_warning: true },
                            elision_candidate,
                        );
                        return;
                    } else if emit_lint {
                        self.r.lint_buffer.buffer_lint(
                            lint::builtin::ELIDED_LIFETIMES_IN_ASSOCIATED_CONSTANT,
                            node_id,
                            lifetime.ident.span,
                            lint::BuiltinLintDiag::AssociatedConstElidedLifetime {
                                elided,
                                span: lifetime.ident.span,
                                lifetimes_in_scope: lifetimes_in_scope.into(),
                            },
                        );
                    }
                }
                LifetimeRibKind::AnonymousReportError => {
                    if elided {
                        let mut suggestion = None;
                        for rib in self.lifetime_ribs[i..].iter().rev() {
                            if let LifetimeRibKind::Generics {
                                span,
                                kind: LifetimeBinderKind::PolyTrait | LifetimeBinderKind::WhereBound,
                                ..
                            } = &rib.kind
                            {
                                suggestion =
                                    Some(errors::ElidedAnonymousLivetimeReportErrorSuggestion {
                                        lo: span.shrink_to_lo(),
                                        hi: lifetime.ident.span.shrink_to_hi(),
                                    });
                                break;
                            }
                        }

                        // are we trying to use an anonymous lifetime
                        // on a non GAT associated trait type?
                        if !self.in_func_body
                            && let Some((module, _)) = &self.current_trait_ref
                            && let Some(ty) = &self.diag_metadata.current_self_type
                            && Some(true) == self.diag_metadata.in_non_gat_assoc_type
                            && let crate::ModuleKind::Def(DefKind::Trait, trait_id, _) = module.kind
                        {
                            if def_id_matches_path(self.r.tcx, trait_id, &[
                                "core", "iter", "traits", "iterator", "Iterator",
                            ]) {
                                self.r.dcx().emit_err(errors::LendingIteratorReportError {
                                    lifetime: lifetime.ident.span,
                                    ty: ty.span,
                                });
                            } else {
                                self.r.dcx().emit_err(errors::AnonymousLivetimeNonGatReportError {
                                    lifetime: lifetime.ident.span,
                                });
                            }
                        } else {
                            self.r.dcx().emit_err(errors::ElidedAnonymousLivetimeReportError {
                                span: lifetime.ident.span,
                                suggestion,
                            });
                        }
                    } else {
                        self.r.dcx().emit_err(errors::ExplicitAnonymousLivetimeReportError {
                            span: lifetime.ident.span,
                        });
                    };
                    self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
                    return;
                }
                LifetimeRibKind::Elided(res) => {
                    self.record_lifetime_res(lifetime.id, res, elision_candidate);
                    return;
                }
                LifetimeRibKind::ElisionFailure => {
                    self.diag_metadata.current_elision_failures.push(missing_lifetime);
                    self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
                    return;
                }
                LifetimeRibKind::Item => break,
                LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
                LifetimeRibKind::ConcreteAnonConst(_) => {
                    // There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`.
                    span_bug!(lifetime.ident.span, "unexpected rib kind: {:?}", rib.kind)
                }
            }
        }
        self.record_lifetime_res(lifetime.id, LifetimeRes::Error, elision_candidate);
        self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
    }

    #[instrument(level = "debug", skip(self))]
    fn resolve_elided_lifetime(&mut self, anchor_id: NodeId, span: Span) {
        let id = self.r.next_node_id();
        let lt = Lifetime { id, ident: Ident::new(kw::UnderscoreLifetime, span) };

        self.record_lifetime_res(
            anchor_id,
            LifetimeRes::ElidedAnchor { start: id, end: NodeId::from_u32(id.as_u32() + 1) },
            LifetimeElisionCandidate::Ignore,
        );
        self.resolve_anonymous_lifetime(&lt, anchor_id, true);
    }

    #[instrument(level = "debug", skip(self))]
    fn create_fresh_lifetime(
        &mut self,
        ident: Ident,
        binder: NodeId,
        kind: MissingLifetimeKind,
    ) -> LifetimeRes {
        debug_assert_eq!(ident.name, kw::UnderscoreLifetime);
        debug!(?ident.span);

        // Leave the responsibility to create the `LocalDefId` to lowering.
        let param = self.r.next_node_id();
        let res = LifetimeRes::Fresh { param, binder, kind };
        self.record_lifetime_param(param, res);

        // Record the created lifetime parameter so lowering can pick it up and add it to HIR.
        self.r
            .extra_lifetime_params_map
            .entry(binder)
            .or_insert_with(Vec::new)
            .push((ident, param, res));
        res
    }

    #[instrument(level = "debug", skip(self))]
    fn resolve_elided_lifetimes_in_path(
        &mut self,
        partial_res: PartialRes,
        path: &[Segment],
        source: PathSource<'_>,
        path_span: Span,
    ) {
        let proj_start = path.len() - partial_res.unresolved_segments();
        for (i, segment) in path.iter().enumerate() {
            if segment.has_lifetime_args {
                continue;
            }
            let Some(segment_id) = segment.id else {
                continue;
            };

            // Figure out if this is a type/trait segment,
            // which may need lifetime elision performed.
            let type_def_id = match partial_res.base_res() {
                Res::Def(DefKind::AssocTy, def_id) if i + 2 == proj_start => {
                    self.r.tcx.parent(def_id)
                }
                Res::Def(DefKind::Variant, def_id) if i + 1 == proj_start => {
                    self.r.tcx.parent(def_id)
                }
                Res::Def(DefKind::Struct, def_id)
                | Res::Def(DefKind::Union, def_id)
                | Res::Def(DefKind::Enum, def_id)
                | Res::Def(DefKind::TyAlias, def_id)
                | Res::Def(DefKind::Trait, def_id)
                    if i + 1 == proj_start =>
                {
                    def_id
                }
                _ => continue,
            };

            let expected_lifetimes = self.r.item_generics_num_lifetimes(type_def_id);
            if expected_lifetimes == 0 {
                continue;
            }

            let node_ids = self.r.next_node_ids(expected_lifetimes);
            self.record_lifetime_res(
                segment_id,
                LifetimeRes::ElidedAnchor { start: node_ids.start, end: node_ids.end },
                LifetimeElisionCandidate::Ignore,
            );

            let inferred = match source {
                PathSource::Trait(..)
                | PathSource::TraitItem(..)
                | PathSource::Type
                | PathSource::PreciseCapturingArg(..)
                | PathSource::ReturnTypeNotation => false,
                PathSource::Expr(..)
                | PathSource::Pat
                | PathSource::Struct
                | PathSource::TupleStruct(..)
                | PathSource::Delegation => true,
            };
            if inferred {
                // Do not create a parameter for patterns and expressions: type checking can infer
                // the appropriate lifetime for us.
                for id in node_ids {
                    self.record_lifetime_res(
                        id,
                        LifetimeRes::Infer,
                        LifetimeElisionCandidate::Named,
                    );
                }
                continue;
            }

            let elided_lifetime_span = if segment.has_generic_args {
                // If there are brackets, but not generic arguments, then use the opening bracket
                segment.args_span.with_hi(segment.args_span.lo() + BytePos(1))
            } else {
                // If there are no brackets, use the identifier span.
                // HACK: we use find_ancestor_inside to properly suggest elided spans in paths
                // originating from macros, since the segment's span might be from a macro arg.
                segment.ident.span.find_ancestor_inside(path_span).unwrap_or(path_span)
            };
            let ident = Ident::new(kw::UnderscoreLifetime, elided_lifetime_span);

            let kind = if segment.has_generic_args {
                MissingLifetimeKind::Comma
            } else {
                MissingLifetimeKind::Brackets
            };
            let missing_lifetime = MissingLifetime {
                id: node_ids.start,
                id_for_lint: segment_id,
                span: elided_lifetime_span,
                kind,
                count: expected_lifetimes,
            };
            let mut should_lint = true;
            for rib in self.lifetime_ribs.iter().rev() {
                match rib.kind {
                    // In create-parameter mode we error here because we don't want to support
                    // deprecated impl elision in new features like impl elision and `async fn`,
                    // both of which work using the `CreateParameter` mode:
                    //
                    //     impl Foo for std::cell::Ref<u32> // note lack of '_
                    //     async fn foo(_: std::cell::Ref<u32>) { ... }
                    LifetimeRibKind::AnonymousCreateParameter { report_in_path: true, .. }
                    | LifetimeRibKind::StaticIfNoLifetimeInScope { .. } => {
                        let sess = self.r.tcx.sess;
                        let subdiag = rustc_errors::elided_lifetime_in_path_suggestion(
                            sess.source_map(),
                            expected_lifetimes,
                            path_span,
                            !segment.has_generic_args,
                            elided_lifetime_span,
                        );
                        self.r.dcx().emit_err(errors::ImplicitElidedLifetimeNotAllowedHere {
                            span: path_span,
                            subdiag,
                        });
                        should_lint = false;

                        for id in node_ids {
                            self.record_lifetime_res(
                                id,
                                LifetimeRes::Error,
                                LifetimeElisionCandidate::Named,
                            );
                        }
                        break;
                    }
                    // Do not create a parameter for patterns and expressions.
                    LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
                        // Group all suggestions into the first record.
                        let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
                        for id in node_ids {
                            let res = self.create_fresh_lifetime(ident, binder, kind);
                            self.record_lifetime_res(
                                id,
                                res,
                                replace(&mut candidate, LifetimeElisionCandidate::Named),
                            );
                        }
                        break;
                    }
                    LifetimeRibKind::Elided(res) => {
                        let mut candidate = LifetimeElisionCandidate::Missing(missing_lifetime);
                        for id in node_ids {
                            self.record_lifetime_res(
                                id,
                                res,
                                replace(&mut candidate, LifetimeElisionCandidate::Ignore),
                            );
                        }
                        break;
                    }
                    LifetimeRibKind::ElisionFailure => {
                        self.diag_metadata.current_elision_failures.push(missing_lifetime);
                        for id in node_ids {
                            self.record_lifetime_res(
                                id,
                                LifetimeRes::Error,
                                LifetimeElisionCandidate::Ignore,
                            );
                        }
                        break;
                    }
                    // `LifetimeRes::Error`, which would usually be used in the case of
                    // `ReportError`, is unsuitable here, as we don't emit an error yet. Instead,
                    // we simply resolve to an implicit lifetime, which will be checked later, at
                    // which point a suitable error will be emitted.
                    LifetimeRibKind::AnonymousReportError | LifetimeRibKind::Item => {
                        for id in node_ids {
                            self.record_lifetime_res(
                                id,
                                LifetimeRes::Error,
                                LifetimeElisionCandidate::Ignore,
                            );
                        }
                        self.report_missing_lifetime_specifiers(vec![missing_lifetime], None);
                        break;
                    }
                    LifetimeRibKind::Generics { .. } | LifetimeRibKind::ConstParamTy => {}
                    LifetimeRibKind::ConcreteAnonConst(_) => {
                        // There is always an `Elided(LifetimeRes::Infer)` inside an `AnonConst`.
                        span_bug!(elided_lifetime_span, "unexpected rib kind: {:?}", rib.kind)
                    }
                }
            }

            if should_lint {
                self.r.lint_buffer.buffer_lint(
                    lint::builtin::ELIDED_LIFETIMES_IN_PATHS,
                    segment_id,
                    elided_lifetime_span,
                    lint::BuiltinLintDiag::ElidedLifetimesInPaths(
                        expected_lifetimes,
                        path_span,
                        !segment.has_generic_args,
                        elided_lifetime_span,
                    ),
                );
            }
        }
    }

    #[instrument(level = "debug", skip(self))]
    fn record_lifetime_res(
        &mut self,
        id: NodeId,
        res: LifetimeRes,
        candidate: LifetimeElisionCandidate,
    ) {
        if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
            panic!("lifetime {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)")
        }

        match candidate {
            LifetimeElisionCandidate::Missing(missing @ MissingLifetime { .. }) => {
                debug_assert_eq!(id, missing.id);
                match res {
                    LifetimeRes::Static { suppress_elision_warning } => {
                        if !suppress_elision_warning {
                            self.r.lint_buffer.buffer_lint(
                                lint::builtin::ELIDED_NAMED_LIFETIMES,
                                missing.id_for_lint,
                                missing.span,
                                BuiltinLintDiag::ElidedNamedLifetimes {
                                    elided: (missing.span, missing.kind),
                                    resolution: lint::ElidedLifetimeResolution::Static,
                                },
                            );
                        }
                    }
                    LifetimeRes::Param { param, binder: _ } => {
                        let tcx = self.r.tcx();
                        self.r.lint_buffer.buffer_lint(
                            lint::builtin::ELIDED_NAMED_LIFETIMES,
                            missing.id_for_lint,
                            missing.span,
                            BuiltinLintDiag::ElidedNamedLifetimes {
                                elided: (missing.span, missing.kind),
                                resolution: lint::ElidedLifetimeResolution::Param(
                                    tcx.item_name(param.into()),
                                    tcx.source_span(param),
                                ),
                            },
                        );
                    }
                    LifetimeRes::Fresh { .. }
                    | LifetimeRes::Infer
                    | LifetimeRes::Error
                    | LifetimeRes::ElidedAnchor { .. } => {}
                }
            }
            LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {}
        }

        match res {
            LifetimeRes::Param { .. } | LifetimeRes::Fresh { .. } | LifetimeRes::Static { .. } => {
                if let Some(ref mut candidates) = self.lifetime_elision_candidates {
                    candidates.push((res, candidate));
                }
            }
            LifetimeRes::Infer | LifetimeRes::Error | LifetimeRes::ElidedAnchor { .. } => {}
        }
    }

    #[instrument(level = "debug", skip(self))]
    fn record_lifetime_param(&mut self, id: NodeId, res: LifetimeRes) {
        if let Some(prev_res) = self.r.lifetimes_res_map.insert(id, res) {
            panic!(
                "lifetime parameter {id:?} resolved multiple times ({prev_res:?} before, {res:?} now)"
            )
        }
    }

    /// Perform resolution of a function signature, accounting for lifetime elision.
    #[instrument(level = "debug", skip(self, inputs))]
    fn resolve_fn_signature(
        &mut self,
        fn_id: NodeId,
        has_self: bool,
        inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)> + Clone,
        output_ty: &'ast FnRetTy,
    ) {
        // Add each argument to the rib.
        let elision_lifetime = self.resolve_fn_params(has_self, inputs);
        debug!(?elision_lifetime);

        let outer_failures = take(&mut self.diag_metadata.current_elision_failures);
        let output_rib = if let Ok(res) = elision_lifetime.as_ref() {
            self.r.lifetime_elision_allowed.insert(fn_id);
            LifetimeRibKind::Elided(*res)
        } else {
            LifetimeRibKind::ElisionFailure
        };
        self.with_lifetime_rib(output_rib, |this| visit::walk_fn_ret_ty(this, output_ty));
        let elision_failures =
            replace(&mut self.diag_metadata.current_elision_failures, outer_failures);
        if !elision_failures.is_empty() {
            let Err(failure_info) = elision_lifetime else { bug!() };
            self.report_missing_lifetime_specifiers(elision_failures, Some(failure_info));
        }
    }

    /// Resolve inside function parameters and parameter types.
    /// Returns the lifetime for elision in fn return type,
    /// or diagnostic information in case of elision failure.
    fn resolve_fn_params(
        &mut self,
        has_self: bool,
        inputs: impl Iterator<Item = (Option<&'ast Pat>, &'ast Ty)>,
    ) -> Result<LifetimeRes, (Vec<MissingLifetime>, Vec<ElisionFnParameter>)> {
        enum Elision {
            /// We have not found any candidate.
            None,
            /// We have a candidate bound to `self`.
            Self_(LifetimeRes),
            /// We have a candidate bound to a parameter.
            Param(LifetimeRes),
            /// We failed elision.
            Err,
        }

        // Save elision state to reinstate it later.
        let outer_candidates = self.lifetime_elision_candidates.take();

        // Result of elision.
        let mut elision_lifetime = Elision::None;
        // Information for diagnostics.
        let mut parameter_info = Vec::new();
        let mut all_candidates = Vec::new();

        let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
        for (index, (pat, ty)) in inputs.enumerate() {
            debug!(?pat, ?ty);
            self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
                if let Some(pat) = pat {
                    this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
                }
            });

            // Record elision candidates only for this parameter.
            debug_assert_matches!(self.lifetime_elision_candidates, None);
            self.lifetime_elision_candidates = Some(Default::default());
            self.visit_ty(ty);
            let local_candidates = self.lifetime_elision_candidates.take();

            if let Some(candidates) = local_candidates {
                let distinct: FxHashSet<_> = candidates.iter().map(|(res, _)| *res).collect();
                let lifetime_count = distinct.len();
                if lifetime_count != 0 {
                    parameter_info.push(ElisionFnParameter {
                        index,
                        ident: if let Some(pat) = pat
                            && let PatKind::Ident(_, ident, _) = pat.kind
                        {
                            Some(ident)
                        } else {
                            None
                        },
                        lifetime_count,
                        span: ty.span,
                    });
                    all_candidates.extend(candidates.into_iter().filter_map(|(_, candidate)| {
                        match candidate {
                            LifetimeElisionCandidate::Ignore | LifetimeElisionCandidate::Named => {
                                None
                            }
                            LifetimeElisionCandidate::Missing(missing) => Some(missing),
                        }
                    }));
                }
                let mut distinct_iter = distinct.into_iter();
                if let Some(res) = distinct_iter.next() {
                    match elision_lifetime {
                        // We are the first parameter to bind lifetimes.
                        Elision::None => {
                            if distinct_iter.next().is_none() {
                                // We have a single lifetime => success.
                                elision_lifetime = Elision::Param(res)
                            } else {
                                // We have multiple lifetimes => error.
                                elision_lifetime = Elision::Err;
                            }
                        }
                        // We have 2 parameters that bind lifetimes => error.
                        Elision::Param(_) => elision_lifetime = Elision::Err,
                        // `self` elision takes precedence over everything else.
                        Elision::Self_(_) | Elision::Err => {}
                    }
                }
            }

            // Handle `self` specially.
            if index == 0 && has_self {
                let self_lifetime = self.find_lifetime_for_self(ty);
                elision_lifetime = match self_lifetime {
                    // We found `self` elision.
                    Set1::One(lifetime) => Elision::Self_(lifetime),
                    // `self` itself had ambiguous lifetimes, e.g.
                    // &Box<&Self>. In this case we won't consider
                    // taking an alternative parameter lifetime; just avoid elision
                    // entirely.
                    Set1::Many => Elision::Err,
                    // We do not have `self` elision: disregard the `Elision::Param` that we may
                    // have found.
                    Set1::Empty => Elision::None,
                }
            }
            debug!("(resolving function / closure) recorded parameter");
        }

        // Reinstate elision state.
        debug_assert_matches!(self.lifetime_elision_candidates, None);
        self.lifetime_elision_candidates = outer_candidates;

        if let Elision::Param(res) | Elision::Self_(res) = elision_lifetime {
            return Ok(res);
        }

        // We do not have a candidate.
        Err((all_candidates, parameter_info))
    }

    /// List all the lifetimes that appear in the provided type.
    fn find_lifetime_for_self(&self, ty: &'ast Ty) -> Set1<LifetimeRes> {
        /// Visits a type to find all the &references, and determines the
        /// set of lifetimes for all of those references where the referent
        /// contains Self.
        struct FindReferenceVisitor<'a, 'ra, 'tcx> {
            r: &'a Resolver<'ra, 'tcx>,
            impl_self: Option<Res>,
            lifetime: Set1<LifetimeRes>,
        }

        impl<'ra> Visitor<'ra> for FindReferenceVisitor<'_, '_, '_> {
            fn visit_ty(&mut self, ty: &'ra Ty) {
                trace!("FindReferenceVisitor considering ty={:?}", ty);
                if let TyKind::Ref(lt, _) | TyKind::PinnedRef(lt, _) = ty.kind {
                    // See if anything inside the &thing contains Self
                    let mut visitor =
                        SelfVisitor { r: self.r, impl_self: self.impl_self, self_found: false };
                    visitor.visit_ty(ty);
                    trace!("FindReferenceVisitor: SelfVisitor self_found={:?}", visitor.self_found);
                    if visitor.self_found {
                        let lt_id = if let Some(lt) = lt {
                            lt.id
                        } else {
                            let res = self.r.lifetimes_res_map[&ty.id];
                            let LifetimeRes::ElidedAnchor { start, .. } = res else { bug!() };
                            start
                        };
                        let lt_res = self.r.lifetimes_res_map[&lt_id];
                        trace!("FindReferenceVisitor inserting res={:?}", lt_res);
                        self.lifetime.insert(lt_res);
                    }
                }
                visit::walk_ty(self, ty)
            }

            // A type may have an expression as a const generic argument.
            // We do not want to recurse into those.
            fn visit_expr(&mut self, _: &'ra Expr) {}
        }

        /// Visitor which checks the referent of a &Thing to see if the
        /// Thing contains Self
        struct SelfVisitor<'a, 'ra, 'tcx> {
            r: &'a Resolver<'ra, 'tcx>,
            impl_self: Option<Res>,
            self_found: bool,
        }

        impl SelfVisitor<'_, '_, '_> {
            // Look for `self: &'a Self` - also desugared from `&'a self`
            fn is_self_ty(&self, ty: &Ty) -> bool {
                match ty.kind {
                    TyKind::ImplicitSelf => true,
                    TyKind::Path(None, _) => {
                        let path_res = self.r.partial_res_map[&ty.id].full_res();
                        if let Some(Res::SelfTyParam { .. } | Res::SelfTyAlias { .. }) = path_res {
                            return true;
                        }
                        self.impl_self.is_some() && path_res == self.impl_self
                    }
                    _ => false,
                }
            }
        }

        impl<'ra> Visitor<'ra> for SelfVisitor<'_, '_, '_> {
            fn visit_ty(&mut self, ty: &'ra Ty) {
                trace!("SelfVisitor considering ty={:?}", ty);
                if self.is_self_ty(ty) {
                    trace!("SelfVisitor found Self");
                    self.self_found = true;
                }
                visit::walk_ty(self, ty)
            }

            // A type may have an expression as a const generic argument.
            // We do not want to recurse into those.
            fn visit_expr(&mut self, _: &'ra Expr) {}
        }

        let impl_self = self
            .diag_metadata
            .current_self_type
            .as_ref()
            .and_then(|ty| {
                if let TyKind::Path(None, _) = ty.kind {
                    self.r.partial_res_map.get(&ty.id)
                } else {
                    None
                }
            })
            .and_then(|res| res.full_res())
            .filter(|res| {
                // Permit the types that unambiguously always
                // result in the same type constructor being used
                // (it can't differ between `Self` and `self`).
                matches!(
                    res,
                    Res::Def(DefKind::Struct | DefKind::Union | DefKind::Enum, _,) | Res::PrimTy(_)
                )
            });
        let mut visitor = FindReferenceVisitor { r: self.r, impl_self, lifetime: Set1::Empty };
        visitor.visit_ty(ty);
        trace!("FindReferenceVisitor found={:?}", visitor.lifetime);
        visitor.lifetime
    }

    /// Searches the current set of local scopes for labels. Returns the `NodeId` of the resolved
    /// label and reports an error if the label is not found or is unreachable.
    fn resolve_label(&mut self, mut label: Ident) -> Result<(NodeId, Span), ResolutionError<'ra>> {
        let mut suggestion = None;

        for i in (0..self.label_ribs.len()).rev() {
            let rib = &self.label_ribs[i];

            if let RibKind::MacroDefinition(def) = rib.kind {
                // If an invocation of this macro created `ident`, give up on `ident`
                // and switch to `ident`'s source from the macro definition.
                if def == self.r.macro_def(label.span.ctxt()) {
                    label.span.remove_mark();
                }
            }

            let ident = label.normalize_to_macro_rules();
            if let Some((ident, id)) = rib.bindings.get_key_value(&ident) {
                let definition_span = ident.span;
                return if self.is_label_valid_from_rib(i) {
                    Ok((*id, definition_span))
                } else {
                    Err(ResolutionError::UnreachableLabel {
                        name: label.name,
                        definition_span,
                        suggestion,
                    })
                };
            }

            // Diagnostics: Check if this rib contains a label with a similar name, keep track of
            // the first such label that is encountered.
            suggestion = suggestion.or_else(|| self.suggestion_for_label_in_rib(i, label));
        }

        Err(ResolutionError::UndeclaredLabel { name: label.name, suggestion })
    }

    /// Determine whether or not a label from the `rib_index`th label rib is reachable.
    fn is_label_valid_from_rib(&self, rib_index: usize) -> bool {
        let ribs = &self.label_ribs[rib_index + 1..];

        for rib in ribs {
            if rib.kind.is_label_barrier() {
                return false;
            }
        }

        true
    }

    fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) {
        debug!("resolve_adt");
        let kind = self.r.local_def_kind(item.id);
        self.with_current_self_item(item, |this| {
            this.with_generic_param_rib(
                &generics.params,
                RibKind::Item(HasGenericParams::Yes(generics.span), kind),
                LifetimeRibKind::Generics {
                    binder: item.id,
                    kind: LifetimeBinderKind::Item,
                    span: generics.span,
                },
                |this| {
                    let item_def_id = this.r.local_def_id(item.id).to_def_id();
                    this.with_self_rib(
                        Res::SelfTyAlias {
                            alias_to: item_def_id,
                            forbid_generic: false,
                            is_trait_impl: false,
                        },
                        |this| {
                            visit::walk_item(this, item);
                        },
                    );
                },
            );
        });
    }

    fn future_proof_import(&mut self, use_tree: &UseTree) {
        if let [segment, rest @ ..] = use_tree.prefix.segments.as_slice() {
            let ident = segment.ident;
            if ident.is_path_segment_keyword() || ident.span.is_rust_2015() {
                return;
            }

            let nss = match use_tree.kind {
                UseTreeKind::Simple(..) if rest.is_empty() => &[TypeNS, ValueNS][..],
                _ => &[TypeNS],
            };
            let report_error = |this: &Self, ns| {
                if this.should_report_errs() {
                    let what = if ns == TypeNS { "type parameters" } else { "local variables" };
                    this.r.dcx().emit_err(errors::ImportsCannotReferTo { span: ident.span, what });
                }
            };

            for &ns in nss {
                match self.maybe_resolve_ident_in_lexical_scope(ident, ns) {
                    Some(LexicalScopeBinding::Res(..)) => {
                        report_error(self, ns);
                    }
                    Some(LexicalScopeBinding::Item(binding)) => {
                        if let Some(LexicalScopeBinding::Res(..)) =
                            self.resolve_ident_in_lexical_scope(ident, ns, None, Some(binding))
                        {
                            report_error(self, ns);
                        }
                    }
                    None => {}
                }
            }
        } else if let UseTreeKind::Nested { items, .. } = &use_tree.kind {
            for (use_tree, _) in items {
                self.future_proof_import(use_tree);
            }
        }
    }

    fn resolve_item(&mut self, item: &'ast Item) {
        let mod_inner_docs =
            matches!(item.kind, ItemKind::Mod(..)) && rustdoc::inner_docs(&item.attrs);
        if !mod_inner_docs && !matches!(item.kind, ItemKind::Impl(..) | ItemKind::Use(..)) {
            self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
        }

        let name = item.ident.name;
        debug!("(resolving item) resolving {} ({:?})", name, item.kind);

        let def_kind = self.r.local_def_kind(item.id);
        match item.kind {
            ItemKind::TyAlias(box TyAlias { ref generics, .. }) => {
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        kind: LifetimeBinderKind::Item,
                        span: generics.span,
                    },
                    |this| visit::walk_item(this, item),
                );
            }

            ItemKind::Fn(box Fn { ref generics, .. }) => {
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        kind: LifetimeBinderKind::Function,
                        span: generics.span,
                    },
                    |this| visit::walk_item(this, item),
                );
            }

            ItemKind::Enum(_, ref generics)
            | ItemKind::Struct(_, ref generics)
            | ItemKind::Union(_, ref generics) => {
                self.resolve_adt(item, generics);
            }

            ItemKind::Impl(box Impl {
                ref generics,
                ref of_trait,
                ref self_ty,
                items: ref impl_items,
                ..
            }) => {
                self.diag_metadata.current_impl_items = Some(impl_items);
                self.resolve_implementation(
                    &item.attrs,
                    generics,
                    of_trait,
                    self_ty,
                    item.id,
                    impl_items,
                );
                self.diag_metadata.current_impl_items = None;
            }

            ItemKind::Trait(box Trait { ref generics, ref bounds, ref items, .. }) => {
                // Create a new rib for the trait-wide type parameters.
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        kind: LifetimeBinderKind::Item,
                        span: generics.span,
                    },
                    |this| {
                        let local_def_id = this.r.local_def_id(item.id).to_def_id();
                        this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
                            this.visit_generics(generics);
                            walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits);
                            this.resolve_trait_items(items);
                        });
                    },
                );
            }

            ItemKind::TraitAlias(ref generics, ref bounds) => {
                // Create a new rib for the trait-wide type parameters.
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::Item(HasGenericParams::Yes(generics.span), def_kind),
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        kind: LifetimeBinderKind::Item,
                        span: generics.span,
                    },
                    |this| {
                        let local_def_id = this.r.local_def_id(item.id).to_def_id();
                        this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| {
                            this.visit_generics(generics);
                            walk_list!(this, visit_param_bound, bounds, BoundKind::Bound);
                        });
                    },
                );
            }

            ItemKind::Mod(..) => {
                self.with_scope(item.id, |this| {
                    if mod_inner_docs {
                        this.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
                    }
                    let old_macro_rules = this.parent_scope.macro_rules;
                    visit::walk_item(this, item);
                    // Maintain macro_rules scopes in the same way as during early resolution
                    // for diagnostics and doc links.
                    if item.attrs.iter().all(|attr| {
                        !attr.has_name(sym::macro_use) && !attr.has_name(sym::macro_escape)
                    }) {
                        this.parent_scope.macro_rules = old_macro_rules;
                    }
                });
            }

            ItemKind::Static(box ast::StaticItem { ref ty, ref expr, .. }) => {
                self.with_static_rib(def_kind, |this| {
                    this.with_lifetime_rib(
                        LifetimeRibKind::Elided(LifetimeRes::Static {
                            suppress_elision_warning: true,
                        }),
                        |this| {
                            this.visit_ty(ty);
                        },
                    );
                    if let Some(expr) = expr {
                        // We already forbid generic params because of the above item rib,
                        // so it doesn't matter whether this is a trivial constant.
                        this.resolve_const_body(expr, Some((item.ident, ConstantItemKind::Static)));
                    }
                });
            }

            ItemKind::Const(box ast::ConstItem { ref generics, ref ty, ref expr, .. }) => {
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::Item(
                        if self.r.tcx.features().generic_const_items {
                            HasGenericParams::Yes(generics.span)
                        } else {
                            HasGenericParams::No
                        },
                        def_kind,
                    ),
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        kind: LifetimeBinderKind::ConstItem,
                        span: generics.span,
                    },
                    |this| {
                        this.visit_generics(generics);

                        this.with_lifetime_rib(
                            LifetimeRibKind::Elided(LifetimeRes::Static {
                                suppress_elision_warning: true,
                            }),
                            |this| this.visit_ty(ty),
                        );

                        if let Some(expr) = expr {
                            this.resolve_const_body(
                                expr,
                                Some((item.ident, ConstantItemKind::Const)),
                            );
                        }
                    },
                );
            }

            ItemKind::Use(ref use_tree) => {
                let maybe_exported = match use_tree.kind {
                    UseTreeKind::Simple(_) | UseTreeKind::Glob => MaybeExported::Ok(item.id),
                    UseTreeKind::Nested { .. } => MaybeExported::NestedUse(&item.vis),
                };
                self.resolve_doc_links(&item.attrs, maybe_exported);

                self.future_proof_import(use_tree);
            }

            ItemKind::MacroDef(ref macro_def) => {
                // Maintain macro_rules scopes in the same way as during early resolution
                // for diagnostics and doc links.
                if macro_def.macro_rules {
                    let def_id = self.r.local_def_id(item.id);
                    self.parent_scope.macro_rules = self.r.macro_rules_scopes[&def_id];
                }
            }

            ItemKind::ForeignMod(_) | ItemKind::GlobalAsm(_) => {
                visit::walk_item(self, item);
            }

            ItemKind::Delegation(ref delegation) => {
                let span = delegation.path.segments.last().unwrap().ident.span;
                self.with_generic_param_rib(
                    &[],
                    RibKind::Item(HasGenericParams::Yes(span), def_kind),
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        kind: LifetimeBinderKind::Function,
                        span,
                    },
                    |this| this.resolve_delegation(delegation),
                );
            }

            ItemKind::ExternCrate(..) => {}

            ItemKind::MacCall(_) | ItemKind::DelegationMac(..) => {
                panic!("unexpanded macro in resolve!")
            }
        }
    }

    fn with_generic_param_rib<'c, F>(
        &'c mut self,
        params: &'c [GenericParam],
        kind: RibKind<'ra>,
        lifetime_kind: LifetimeRibKind,
        f: F,
    ) where
        F: FnOnce(&mut Self),
    {
        debug!("with_generic_param_rib");
        let LifetimeRibKind::Generics { binder, span: generics_span, kind: generics_kind, .. } =
            lifetime_kind
        else {
            panic!()
        };

        let mut function_type_rib = Rib::new(kind);
        let mut function_value_rib = Rib::new(kind);
        let mut function_lifetime_rib = LifetimeRib::new(lifetime_kind);

        // Only check for shadowed bindings if we're declaring new params.
        if !params.is_empty() {
            let mut seen_bindings = FxHashMap::default();
            // Store all seen lifetimes names from outer scopes.
            let mut seen_lifetimes = FxHashSet::default();

            // We also can't shadow bindings from associated parent items.
            for ns in [ValueNS, TypeNS] {
                for parent_rib in self.ribs[ns].iter().rev() {
                    // Break at mod level, to account for nested items which are
                    // allowed to shadow generic param names.
                    if matches!(parent_rib.kind, RibKind::Module(..)) {
                        break;
                    }

                    seen_bindings
                        .extend(parent_rib.bindings.keys().map(|ident| (*ident, ident.span)));
                }
            }

            // Forbid shadowing lifetime bindings
            for rib in self.lifetime_ribs.iter().rev() {
                seen_lifetimes.extend(rib.bindings.iter().map(|(ident, _)| *ident));
                if let LifetimeRibKind::Item = rib.kind {
                    break;
                }
            }

            for param in params {
                let ident = param.ident.normalize_to_macros_2_0();
                debug!("with_generic_param_rib: {}", param.id);

                if let GenericParamKind::Lifetime = param.kind
                    && let Some(&original) = seen_lifetimes.get(&ident)
                {
                    diagnostics::signal_lifetime_shadowing(self.r.tcx.sess, original, param.ident);
                    // Record lifetime res, so lowering knows there is something fishy.
                    self.record_lifetime_param(param.id, LifetimeRes::Error);
                    continue;
                }

                match seen_bindings.entry(ident) {
                    Entry::Occupied(entry) => {
                        let span = *entry.get();
                        let err = ResolutionError::NameAlreadyUsedInParameterList(ident.name, span);
                        self.report_error(param.ident.span, err);
                        let rib = match param.kind {
                            GenericParamKind::Lifetime => {
                                // Record lifetime res, so lowering knows there is something fishy.
                                self.record_lifetime_param(param.id, LifetimeRes::Error);
                                continue;
                            }
                            GenericParamKind::Type { .. } => &mut function_type_rib,
                            GenericParamKind::Const { .. } => &mut function_value_rib,
                        };

                        // Taint the resolution in case of errors to prevent follow up errors in typeck
                        self.r.record_partial_res(param.id, PartialRes::new(Res::Err));
                        rib.bindings.insert(ident, Res::Err);
                        continue;
                    }
                    Entry::Vacant(entry) => {
                        entry.insert(param.ident.span);
                    }
                }

                if param.ident.name == kw::UnderscoreLifetime {
                    self.r
                        .dcx()
                        .emit_err(errors::UnderscoreLifetimeIsReserved { span: param.ident.span });
                    // Record lifetime res, so lowering knows there is something fishy.
                    self.record_lifetime_param(param.id, LifetimeRes::Error);
                    continue;
                }

                if param.ident.name == kw::StaticLifetime {
                    self.r.dcx().emit_err(errors::StaticLifetimeIsReserved {
                        span: param.ident.span,
                        lifetime: param.ident,
                    });
                    // Record lifetime res, so lowering knows there is something fishy.
                    self.record_lifetime_param(param.id, LifetimeRes::Error);
                    continue;
                }

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

                // Plain insert (no renaming).
                let (rib, def_kind) = match param.kind {
                    GenericParamKind::Type { .. } => (&mut function_type_rib, DefKind::TyParam),
                    GenericParamKind::Const { .. } => {
                        (&mut function_value_rib, DefKind::ConstParam)
                    }
                    GenericParamKind::Lifetime => {
                        let res = LifetimeRes::Param { param: def_id, binder };
                        self.record_lifetime_param(param.id, res);
                        function_lifetime_rib.bindings.insert(ident, (param.id, res));
                        continue;
                    }
                };

                let res = match kind {
                    RibKind::Item(..) | RibKind::AssocItem => {
                        Res::Def(def_kind, def_id.to_def_id())
                    }
                    RibKind::Normal => {
                        // FIXME(non_lifetime_binders): Stop special-casing
                        // const params to error out here.
                        if self.r.tcx.features().non_lifetime_binders
                            && matches!(param.kind, GenericParamKind::Type { .. })
                        {
                            Res::Def(def_kind, def_id.to_def_id())
                        } else {
                            Res::Err
                        }
                    }
                    _ => span_bug!(param.ident.span, "Unexpected rib kind {:?}", kind),
                };
                self.r.record_partial_res(param.id, PartialRes::new(res));
                rib.bindings.insert(ident, res);
            }
        }

        self.lifetime_ribs.push(function_lifetime_rib);
        self.ribs[ValueNS].push(function_value_rib);
        self.ribs[TypeNS].push(function_type_rib);

        f(self);

        self.ribs[TypeNS].pop();
        self.ribs[ValueNS].pop();
        let function_lifetime_rib = self.lifetime_ribs.pop().unwrap();

        // Do not account for the parameters we just bound for function lifetime elision.
        if let Some(ref mut candidates) = self.lifetime_elision_candidates {
            for (_, res) in function_lifetime_rib.bindings.values() {
                candidates.retain(|(r, _)| r != res);
            }
        }

        if let LifetimeBinderKind::BareFnType
        | LifetimeBinderKind::WhereBound
        | LifetimeBinderKind::Function
        | LifetimeBinderKind::ImplBlock = generics_kind
        {
            self.maybe_report_lifetime_uses(generics_span, params)
        }
    }

    fn with_label_rib(&mut self, kind: RibKind<'ra>, f: impl FnOnce(&mut Self)) {
        self.label_ribs.push(Rib::new(kind));
        f(self);
        self.label_ribs.pop();
    }

    fn with_static_rib(&mut self, def_kind: DefKind, f: impl FnOnce(&mut Self)) {
        let kind = RibKind::Item(HasGenericParams::No, def_kind);
        self.with_rib(ValueNS, kind, |this| this.with_rib(TypeNS, kind, f))
    }

    // HACK(min_const_generics, generic_const_exprs): We
    // want to keep allowing `[0; std::mem::size_of::<*mut T>()]`
    // with a future compat lint for now. We do this by adding an
    // additional special case for repeat expressions.
    //
    // Note that we intentionally still forbid `[0; N + 1]` during
    // name resolution so that we don't extend the future
    // compat lint to new cases.
    #[instrument(level = "debug", skip(self, f))]
    fn with_constant_rib(
        &mut self,
        is_repeat: IsRepeatExpr,
        may_use_generics: ConstantHasGenerics,
        item: Option<(Ident, ConstantItemKind)>,
        f: impl FnOnce(&mut Self),
    ) {
        let f = |this: &mut Self| {
            this.with_rib(ValueNS, RibKind::ConstantItem(may_use_generics, item), |this| {
                this.with_rib(
                    TypeNS,
                    RibKind::ConstantItem(
                        may_use_generics.force_yes_if(is_repeat == IsRepeatExpr::Yes),
                        item,
                    ),
                    |this| {
                        this.with_label_rib(RibKind::ConstantItem(may_use_generics, item), f);
                    },
                )
            })
        };

        if let ConstantHasGenerics::No(cause) = may_use_generics {
            self.with_lifetime_rib(LifetimeRibKind::ConcreteAnonConst(cause), f)
        } else {
            f(self)
        }
    }

    fn with_current_self_type<T>(&mut self, self_type: &Ty, f: impl FnOnce(&mut Self) -> T) -> T {
        // Handle nested impls (inside fn bodies)
        let previous_value =
            replace(&mut self.diag_metadata.current_self_type, Some(self_type.clone()));
        let result = f(self);
        self.diag_metadata.current_self_type = previous_value;
        result
    }

    fn with_current_self_item<T>(&mut self, self_item: &Item, f: impl FnOnce(&mut Self) -> T) -> T {
        let previous_value = replace(&mut self.diag_metadata.current_self_item, Some(self_item.id));
        let result = f(self);
        self.diag_metadata.current_self_item = previous_value;
        result
    }

    /// When evaluating a `trait` use its associated types' idents for suggestions in E0412.
    fn resolve_trait_items(&mut self, trait_items: &'ast [P<AssocItem>]) {
        let trait_assoc_items =
            replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items));

        let walk_assoc_item =
            |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| {
                this.with_generic_param_rib(
                    &generics.params,
                    RibKind::AssocItem,
                    LifetimeRibKind::Generics { binder: item.id, span: generics.span, kind },
                    |this| visit::walk_assoc_item(this, item, AssocCtxt::Trait),
                );
            };

        for item in trait_items {
            self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id));
            match &item.kind {
                AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
                    self.with_generic_param_rib(
                        &generics.params,
                        RibKind::AssocItem,
                        LifetimeRibKind::Generics {
                            binder: item.id,
                            span: generics.span,
                            kind: LifetimeBinderKind::ConstItem,
                        },
                        |this| {
                            this.with_lifetime_rib(
                                LifetimeRibKind::StaticIfNoLifetimeInScope {
                                    lint_id: item.id,
                                    emit_lint: false,
                                },
                                |this| {
                                    this.visit_generics(generics);
                                    this.visit_ty(ty);

                                    // Only impose the restrictions of `ConstRibKind` for an
                                    // actual constant expression in a provided default.
                                    if let Some(expr) = expr {
                                        // We allow arbitrary const expressions inside of associated consts,
                                        // even if they are potentially not const evaluatable.
                                        //
                                        // Type parameters can already be used and as associated consts are
                                        // not used as part of the type system, this is far less surprising.
                                        this.resolve_const_body(expr, None);
                                    }
                                },
                            )
                        },
                    );
                }
                AssocItemKind::Fn(box Fn { generics, .. }) => {
                    walk_assoc_item(self, generics, LifetimeBinderKind::Function, item);
                }
                AssocItemKind::Delegation(delegation) => {
                    self.with_generic_param_rib(
                        &[],
                        RibKind::AssocItem,
                        LifetimeRibKind::Generics {
                            binder: item.id,
                            kind: LifetimeBinderKind::Function,
                            span: delegation.path.segments.last().unwrap().ident.span,
                        },
                        |this| this.resolve_delegation(delegation),
                    );
                }
                AssocItemKind::Type(box TyAlias { generics, .. }) => self
                    .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
                        walk_assoc_item(this, generics, LifetimeBinderKind::Item, item)
                    }),
                AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
                    panic!("unexpanded macro in resolve!")
                }
            };
        }

        self.diag_metadata.current_trait_assoc_items = trait_assoc_items;
    }

    /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`).
    fn with_optional_trait_ref<T>(
        &mut self,
        opt_trait_ref: Option<&TraitRef>,
        self_type: &'ast Ty,
        f: impl FnOnce(&mut Self, Option<DefId>) -> T,
    ) -> T {
        let mut new_val = None;
        let mut new_id = None;
        if let Some(trait_ref) = opt_trait_ref {
            let path: Vec<_> = Segment::from_path(&trait_ref.path);
            self.diag_metadata.currently_processing_impl_trait =
                Some((trait_ref.clone(), self_type.clone()));
            let res = self.smart_resolve_path_fragment(
                &None,
                &path,
                PathSource::Trait(AliasPossibility::No),
                Finalize::new(trait_ref.ref_id, trait_ref.path.span),
                RecordPartialRes::Yes,
            );
            self.diag_metadata.currently_processing_impl_trait = None;
            if let Some(def_id) = res.expect_full_res().opt_def_id() {
                new_id = Some(def_id);
                new_val = Some((self.r.expect_module(def_id), trait_ref.clone()));
            }
        }
        let original_trait_ref = replace(&mut self.current_trait_ref, new_val);
        let result = f(self, new_id);
        self.current_trait_ref = original_trait_ref;
        result
    }

    fn with_self_rib_ns(&mut self, ns: Namespace, self_res: Res, f: impl FnOnce(&mut Self)) {
        let mut self_type_rib = Rib::new(RibKind::Normal);

        // Plain insert (no renaming, since types are not currently hygienic)
        self_type_rib.bindings.insert(Ident::with_dummy_span(kw::SelfUpper), self_res);
        self.ribs[ns].push(self_type_rib);
        f(self);
        self.ribs[ns].pop();
    }

    fn with_self_rib(&mut self, self_res: Res, f: impl FnOnce(&mut Self)) {
        self.with_self_rib_ns(TypeNS, self_res, f)
    }

    fn resolve_implementation(
        &mut self,
        attrs: &[ast::Attribute],
        generics: &'ast Generics,
        opt_trait_reference: &'ast Option<TraitRef>,
        self_type: &'ast Ty,
        item_id: NodeId,
        impl_items: &'ast [P<AssocItem>],
    ) {
        debug!("resolve_implementation");
        // If applicable, create a rib for the type parameters.
        self.with_generic_param_rib(
            &generics.params,
            RibKind::Item(HasGenericParams::Yes(generics.span), self.r.local_def_kind(item_id)),
            LifetimeRibKind::Generics {
                span: generics.span,
                binder: item_id,
                kind: LifetimeBinderKind::ImplBlock,
            },
            |this| {
                // Dummy self type for better errors if `Self` is used in the trait path.
                this.with_self_rib(Res::SelfTyParam { trait_: LOCAL_CRATE.as_def_id() }, |this| {
                    this.with_lifetime_rib(
                        LifetimeRibKind::AnonymousCreateParameter {
                            binder: item_id,
                            report_in_path: true
                        },
                        |this| {
                            // Resolve the trait reference, if necessary.
                            this.with_optional_trait_ref(
                                opt_trait_reference.as_ref(),
                                self_type,
                                |this, trait_id| {
                                    this.resolve_doc_links(attrs, MaybeExported::Impl(trait_id));

                                    let item_def_id = this.r.local_def_id(item_id);

                                    // Register the trait definitions from here.
                                    if let Some(trait_id) = trait_id {
                                        this.r
                                            .trait_impls
                                            .entry(trait_id)
                                            .or_default()
                                            .push(item_def_id);
                                    }

                                    let item_def_id = item_def_id.to_def_id();
                                    let res = Res::SelfTyAlias {
                                        alias_to: item_def_id,
                                        forbid_generic: false,
                                        is_trait_impl: trait_id.is_some()
                                    };
                                    this.with_self_rib(res, |this| {
                                        if let Some(trait_ref) = opt_trait_reference.as_ref() {
                                            // Resolve type arguments in the trait path.
                                            visit::walk_trait_ref(this, trait_ref);
                                        }
                                        // Resolve the self type.
                                        this.visit_ty(self_type);
                                        // Resolve the generic parameters.
                                        this.visit_generics(generics);

                                        // Resolve the items within the impl.
                                        this.with_current_self_type(self_type, |this| {
                                            this.with_self_rib_ns(ValueNS, Res::SelfCtor(item_def_id), |this| {
                                                debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)");
                                                let mut seen_trait_items = Default::default();
                                                for item in impl_items {
                                                    this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id);
                                                }
                                            });
                                        });
                                    });
                                },
                            )
                        },
                    );
                });
            },
        );
    }

    fn resolve_impl_item(
        &mut self,
        item: &'ast AssocItem,
        seen_trait_items: &mut FxHashMap<DefId, Span>,
        trait_id: Option<DefId>,
    ) {
        use crate::ResolutionError::*;
        self.resolve_doc_links(&item.attrs, MaybeExported::ImplItem(trait_id.ok_or(&item.vis)));
        match &item.kind {
            AssocItemKind::Const(box ast::ConstItem { generics, ty, expr, .. }) => {
                debug!("resolve_implementation AssocItemKind::Const");
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::AssocItem,
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        span: generics.span,
                        kind: LifetimeBinderKind::ConstItem,
                    },
                    |this| {
                        this.with_lifetime_rib(
                            LifetimeRibKind::StaticIfNoLifetimeInScope {
                                lint_id: item.id,
                                // In impls, it's not a hard error yet due to backcompat.
                                emit_lint: true,
                            },
                            |this| {
                                // If this is a trait impl, ensure the const
                                // exists in trait
                                this.check_trait_item(
                                    item.id,
                                    item.ident,
                                    &item.kind,
                                    ValueNS,
                                    item.span,
                                    seen_trait_items,
                                    |i, s, c| ConstNotMemberOfTrait(i, s, c),
                                );

                                this.visit_generics(generics);
                                this.visit_ty(ty);
                                if let Some(expr) = expr {
                                    // We allow arbitrary const expressions inside of associated consts,
                                    // even if they are potentially not const evaluatable.
                                    //
                                    // Type parameters can already be used and as associated consts are
                                    // not used as part of the type system, this is far less surprising.
                                    this.resolve_const_body(expr, None);
                                }
                            },
                        );
                    },
                );
            }
            AssocItemKind::Fn(box Fn { generics, .. }) => {
                debug!("resolve_implementation AssocItemKind::Fn");
                // We also need a new scope for the impl item type parameters.
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::AssocItem,
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        span: generics.span,
                        kind: LifetimeBinderKind::Function,
                    },
                    |this| {
                        // If this is a trait impl, ensure the method
                        // exists in trait
                        this.check_trait_item(
                            item.id,
                            item.ident,
                            &item.kind,
                            ValueNS,
                            item.span,
                            seen_trait_items,
                            |i, s, c| MethodNotMemberOfTrait(i, s, c),
                        );

                        visit::walk_assoc_item(this, item, AssocCtxt::Impl)
                    },
                );
            }
            AssocItemKind::Type(box TyAlias { generics, .. }) => {
                self.diag_metadata.in_non_gat_assoc_type = Some(generics.params.is_empty());
                debug!("resolve_implementation AssocItemKind::Type");
                // We also need a new scope for the impl item type parameters.
                self.with_generic_param_rib(
                    &generics.params,
                    RibKind::AssocItem,
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        span: generics.span,
                        kind: LifetimeBinderKind::Item,
                    },
                    |this| {
                        this.with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| {
                            // If this is a trait impl, ensure the type
                            // exists in trait
                            this.check_trait_item(
                                item.id,
                                item.ident,
                                &item.kind,
                                TypeNS,
                                item.span,
                                seen_trait_items,
                                |i, s, c| TypeNotMemberOfTrait(i, s, c),
                            );

                            visit::walk_assoc_item(this, item, AssocCtxt::Impl)
                        });
                    },
                );
                self.diag_metadata.in_non_gat_assoc_type = None;
            }
            AssocItemKind::Delegation(box delegation) => {
                debug!("resolve_implementation AssocItemKind::Delegation");
                self.with_generic_param_rib(
                    &[],
                    RibKind::AssocItem,
                    LifetimeRibKind::Generics {
                        binder: item.id,
                        kind: LifetimeBinderKind::Function,
                        span: delegation.path.segments.last().unwrap().ident.span,
                    },
                    |this| {
                        this.check_trait_item(
                            item.id,
                            item.ident,
                            &item.kind,
                            ValueNS,
                            item.span,
                            seen_trait_items,
                            |i, s, c| MethodNotMemberOfTrait(i, s, c),
                        );

                        this.resolve_delegation(delegation)
                    },
                );
            }
            AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => {
                panic!("unexpanded macro in resolve!")
            }
        }
    }

    fn check_trait_item<F>(
        &mut self,
        id: NodeId,
        mut ident: Ident,
        kind: &AssocItemKind,
        ns: Namespace,
        span: Span,
        seen_trait_items: &mut FxHashMap<DefId, Span>,
        err: F,
    ) where
        F: FnOnce(Ident, String, Option<Symbol>) -> ResolutionError<'ra>,
    {
        // If there is a TraitRef in scope for an impl, then the method must be in the trait.
        let Some((module, _)) = self.current_trait_ref else {
            return;
        };
        ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
        let key = BindingKey::new(ident, ns);
        let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
        debug!(?binding);
        if binding.is_none() {
            // We could not find the trait item in the correct namespace.
            // Check the other namespace to report an error.
            let ns = match ns {
                ValueNS => TypeNS,
                TypeNS => ValueNS,
                _ => ns,
            };
            let key = BindingKey::new(ident, ns);
            binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
            debug!(?binding);
        }

        let feed_visibility = |this: &mut Self, def_id| {
            let vis = this.r.tcx.visibility(def_id);
            let vis = if vis.is_visible_locally() {
                vis.expect_local()
            } else {
                this.r.dcx().span_delayed_bug(
                    span,
                    "error should be emitted when an unexpected trait item is used",
                );
                rustc_middle::ty::Visibility::Public
            };
            this.r.feed_visibility(this.r.feed(id), vis);
        };

        let Some(binding) = binding else {
            // We could not find the method: report an error.
            let candidate = self.find_similarly_named_assoc_item(ident.name, kind);
            let path = &self.current_trait_ref.as_ref().unwrap().1.path;
            let path_names = path_names_to_string(path);
            self.report_error(span, err(ident, path_names, candidate));
            feed_visibility(self, module.def_id());
            return;
        };

        let res = binding.res();
        let Res::Def(def_kind, id_in_trait) = res else { bug!() };
        feed_visibility(self, id_in_trait);

        match seen_trait_items.entry(id_in_trait) {
            Entry::Occupied(entry) => {
                self.report_error(span, ResolutionError::TraitImplDuplicate {
                    name: ident.name,
                    old_span: *entry.get(),
                    trait_item_span: binding.span,
                });
                return;
            }
            Entry::Vacant(entry) => {
                entry.insert(span);
            }
        };

        match (def_kind, kind) {
            (DefKind::AssocTy, AssocItemKind::Type(..))
            | (DefKind::AssocFn, AssocItemKind::Fn(..))
            | (DefKind::AssocConst, AssocItemKind::Const(..))
            | (DefKind::AssocFn, AssocItemKind::Delegation(..)) => {
                self.r.record_partial_res(id, PartialRes::new(res));
                return;
            }
            _ => {}
        }

        // The method kind does not correspond to what appeared in the trait, report.
        let path = &self.current_trait_ref.as_ref().unwrap().1.path;
        let (code, kind) = match kind {
            AssocItemKind::Const(..) => (E0323, "const"),
            AssocItemKind::Fn(..) => (E0324, "method"),
            AssocItemKind::Type(..) => (E0325, "type"),
            AssocItemKind::Delegation(..) => (E0324, "method"),
            AssocItemKind::MacCall(..) | AssocItemKind::DelegationMac(..) => {
                span_bug!(span, "unexpanded macro")
            }
        };
        let trait_path = path_names_to_string(path);
        self.report_error(span, ResolutionError::TraitImplMismatch {
            name: ident.name,
            kind,
            code,
            trait_path,
            trait_item_span: binding.span,
        });
    }

    fn resolve_const_body(&mut self, expr: &'ast Expr, item: Option<(Ident, ConstantItemKind)>) {
        self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
            this.with_constant_rib(IsRepeatExpr::No, ConstantHasGenerics::Yes, item, |this| {
                this.visit_expr(expr)
            });
        })
    }

    fn resolve_delegation(&mut self, delegation: &'ast Delegation) {
        self.smart_resolve_path(
            delegation.id,
            &delegation.qself,
            &delegation.path,
            PathSource::Delegation,
        );
        if let Some(qself) = &delegation.qself {
            self.visit_ty(&qself.ty);
        }
        self.visit_path(&delegation.path, delegation.id);
        if let Some(body) = &delegation.body {
            self.with_rib(ValueNS, RibKind::FnOrCoroutine, |this| {
                // `PatBoundCtx` is not necessary in this context
                let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];

                let span = delegation.path.segments.last().unwrap().ident.span;
                this.fresh_binding(
                    Ident::new(kw::SelfLower, span),
                    delegation.id,
                    PatternSource::FnParam,
                    &mut bindings,
                );
                this.visit_block(body);
            });
        }
    }

    fn resolve_params(&mut self, params: &'ast [Param]) {
        let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
        self.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
            for Param { pat, .. } in params {
                this.resolve_pattern(pat, PatternSource::FnParam, &mut bindings);
            }
        });
        for Param { ty, .. } in params {
            self.visit_ty(ty);
        }
    }

    fn resolve_local(&mut self, local: &'ast Local) {
        debug!("resolving local ({:?})", local);
        // Resolve the type.
        visit_opt!(self, visit_ty, &local.ty);

        // Resolve the initializer.
        if let Some((init, els)) = local.kind.init_else_opt() {
            self.visit_expr(init);

            // Resolve the `else` block
            if let Some(els) = els {
                self.visit_block(els);
            }
        }

        // Resolve the pattern.
        self.resolve_pattern_top(&local.pat, PatternSource::Let);
    }

    /// Build a map from pattern identifiers to binding-info's, and check the bindings are
    /// consistent when encountering or-patterns and never patterns.
    /// This is done hygienically: this could arise for a macro that expands into an or-pattern
    /// where one 'x' was from the user and one 'x' came from the macro.
    ///
    /// A never pattern by definition indicates an unreachable case. For example, matching on
    /// `Result<T, &!>` could look like:
    /// ```rust
    /// # #![feature(never_type)]
    /// # #![feature(never_patterns)]
    /// # fn bar(_x: u32) {}
    /// let foo: Result<u32, &!> = Ok(0);
    /// match foo {
    ///     Ok(x) => bar(x),
    ///     Err(&!),
    /// }
    /// ```
    /// This extends to product types: `(x, !)` is likewise unreachable. So it doesn't make sense to
    /// have a binding here, and we tell the user to use `_` instead.
    fn compute_and_check_binding_map(
        &mut self,
        pat: &Pat,
    ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
        let mut binding_map = FxIndexMap::default();
        let mut is_never_pat = false;

        pat.walk(&mut |pat| {
            match pat.kind {
                PatKind::Ident(annotation, ident, ref sub_pat)
                    if sub_pat.is_some() || self.is_base_res_local(pat.id) =>
                {
                    binding_map.insert(ident, BindingInfo { span: ident.span, annotation });
                }
                PatKind::Or(ref ps) => {
                    // Check the consistency of this or-pattern and
                    // then add all bindings to the larger map.
                    match self.compute_and_check_or_pat_binding_map(ps) {
                        Ok(bm) => binding_map.extend(bm),
                        Err(IsNeverPattern) => is_never_pat = true,
                    }
                    return false;
                }
                PatKind::Never => is_never_pat = true,
                _ => {}
            }

            true
        });

        if is_never_pat {
            for (_, binding) in binding_map {
                self.report_error(binding.span, ResolutionError::BindingInNeverPattern);
            }
            Err(IsNeverPattern)
        } else {
            Ok(binding_map)
        }
    }

    fn is_base_res_local(&self, nid: NodeId) -> bool {
        matches!(
            self.r.partial_res_map.get(&nid).map(|res| res.expect_full_res()),
            Some(Res::Local(..))
        )
    }

    /// Compute the binding map for an or-pattern. Checks that all of the arms in the or-pattern
    /// have exactly the same set of bindings, with the same binding modes for each.
    /// Returns the computed binding map and a boolean indicating whether the pattern is a never
    /// pattern.
    ///
    /// A never pattern by definition indicates an unreachable case. For example, destructuring a
    /// `Result<T, &!>` could look like:
    /// ```rust
    /// # #![feature(never_type)]
    /// # #![feature(never_patterns)]
    /// # fn foo() -> Result<bool, &'static !> { Ok(true) }
    /// let (Ok(x) | Err(&!)) = foo();
    /// # let _ = x;
    /// ```
    /// Because the `Err(&!)` branch is never reached, it does not need to have the same bindings as
    /// the other branches of the or-pattern. So we must ignore never pattern when checking the
    /// bindings of an or-pattern.
    /// Moreover, if all the subpatterns are never patterns (e.g. `Ok(!) | Err(!)`), then the
    /// pattern as a whole counts as a never pattern (since it's definitionallly unreachable).
    fn compute_and_check_or_pat_binding_map(
        &mut self,
        pats: &[P<Pat>],
    ) -> Result<FxIndexMap<Ident, BindingInfo>, IsNeverPattern> {
        let mut missing_vars = FxIndexMap::default();
        let mut inconsistent_vars = FxIndexMap::default();

        // 1) Compute the binding maps of all arms; we must ignore never patterns here.
        let not_never_pats = pats
            .iter()
            .filter_map(|pat| {
                let binding_map = self.compute_and_check_binding_map(pat).ok()?;
                Some((binding_map, pat))
            })
            .collect::<Vec<_>>();

        // 2) Record any missing bindings or binding mode inconsistencies.
        for (map_outer, pat_outer) in not_never_pats.iter() {
            // Check against all arms except for the same pattern which is always self-consistent.
            let inners = not_never_pats
                .iter()
                .filter(|(_, pat)| pat.id != pat_outer.id)
                .flat_map(|(map, _)| map);

            for (key, binding_inner) in inners {
                let name = key.name;
                match map_outer.get(key) {
                    None => {
                        // The inner binding is missing in the outer.
                        let binding_error =
                            missing_vars.entry(name).or_insert_with(|| BindingError {
                                name,
                                origin: BTreeSet::new(),
                                target: BTreeSet::new(),
                                could_be_path: name.as_str().starts_with(char::is_uppercase),
                            });
                        binding_error.origin.insert(binding_inner.span);
                        binding_error.target.insert(pat_outer.span);
                    }
                    Some(binding_outer) => {
                        if binding_outer.annotation != binding_inner.annotation {
                            // The binding modes in the outer and inner bindings differ.
                            inconsistent_vars
                                .entry(name)
                                .or_insert((binding_inner.span, binding_outer.span));
                        }
                    }
                }
            }
        }

        // 3) Report all missing variables we found.
        for (name, mut v) in missing_vars {
            if inconsistent_vars.contains_key(&name) {
                v.could_be_path = false;
            }
            self.report_error(
                *v.origin.iter().next().unwrap(),
                ResolutionError::VariableNotBoundInPattern(v, self.parent_scope),
            );
        }

        // 4) Report all inconsistencies in binding modes we found.
        for (name, v) in inconsistent_vars {
            self.report_error(v.0, ResolutionError::VariableBoundWithDifferentMode(name, v.1));
        }

        // 5) Bubble up the final binding map.
        if not_never_pats.is_empty() {
            // All the patterns are never patterns, so the whole or-pattern is one too.
            Err(IsNeverPattern)
        } else {
            let mut binding_map = FxIndexMap::default();
            for (bm, _) in not_never_pats {
                binding_map.extend(bm);
            }
            Ok(binding_map)
        }
    }

    /// Check the consistency of bindings wrt or-patterns and never patterns.
    fn check_consistent_bindings(&mut self, pat: &'ast Pat) {
        let mut is_or_or_never = false;
        pat.walk(&mut |pat| match pat.kind {
            PatKind::Or(..) | PatKind::Never => {
                is_or_or_never = true;
                false
            }
            _ => true,
        });
        if is_or_or_never {
            let _ = self.compute_and_check_binding_map(pat);
        }
    }

    fn resolve_arm(&mut self, arm: &'ast Arm) {
        self.with_rib(ValueNS, RibKind::Normal, |this| {
            this.resolve_pattern_top(&arm.pat, PatternSource::Match);
            visit_opt!(this, visit_expr, &arm.guard);
            visit_opt!(this, visit_expr, &arm.body);
        });
    }

    /// Arising from `source`, resolve a top level pattern.
    fn resolve_pattern_top(&mut self, pat: &'ast Pat, pat_src: PatternSource) {
        let mut bindings = smallvec![(PatBoundCtx::Product, Default::default())];
        self.resolve_pattern(pat, pat_src, &mut bindings);
    }

    fn resolve_pattern(
        &mut self,
        pat: &'ast Pat,
        pat_src: PatternSource,
        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
    ) {
        // We walk the pattern before declaring the pattern's inner bindings,
        // so that we avoid resolving a literal expression to a binding defined
        // by the pattern.
        visit::walk_pat(self, pat);
        self.resolve_pattern_inner(pat, pat_src, bindings);
        // This has to happen *after* we determine which pat_idents are variants:
        self.check_consistent_bindings(pat);
    }

    /// Resolve bindings in a pattern. This is a helper to `resolve_pattern`.
    ///
    /// ### `bindings`
    ///
    /// A stack of sets of bindings accumulated.
    ///
    /// In each set, `PatBoundCtx::Product` denotes that a found binding in it should
    /// be interpreted as re-binding an already bound binding. This results in an error.
    /// Meanwhile, `PatBound::Or` denotes that a found binding in the set should result
    /// in reusing this binding rather than creating a fresh one.
    ///
    /// When called at the top level, the stack must have a single element
    /// with `PatBound::Product`. Otherwise, pushing to the stack happens as
    /// or-patterns (`p_0 | ... | p_n`) are encountered and the context needs
    /// to be switched to `PatBoundCtx::Or` and then `PatBoundCtx::Product` for each `p_i`.
    /// When each `p_i` has been dealt with, the top set is merged with its parent.
    /// When a whole or-pattern has been dealt with, the thing happens.
    ///
    /// See the implementation and `fresh_binding` for more details.
    fn resolve_pattern_inner(
        &mut self,
        pat: &Pat,
        pat_src: PatternSource,
        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
    ) {
        // Visit all direct subpatterns of this pattern.
        pat.walk(&mut |pat| {
            debug!("resolve_pattern pat={:?} node={:?}", pat, pat.kind);
            match pat.kind {
                PatKind::Ident(bmode, ident, ref sub) => {
                    // First try to resolve the identifier as some existing entity,
                    // then fall back to a fresh binding.
                    let has_sub = sub.is_some();
                    let res = self
                        .try_resolve_as_non_binding(pat_src, bmode, ident, has_sub)
                        .unwrap_or_else(|| self.fresh_binding(ident, pat.id, pat_src, bindings));
                    self.r.record_partial_res(pat.id, PartialRes::new(res));
                    self.r.record_pat_span(pat.id, pat.span);
                }
                PatKind::TupleStruct(ref qself, ref path, ref sub_patterns) => {
                    self.smart_resolve_path(
                        pat.id,
                        qself,
                        path,
                        PathSource::TupleStruct(
                            pat.span,
                            self.r.arenas.alloc_pattern_spans(sub_patterns.iter().map(|p| p.span)),
                        ),
                    );
                }
                PatKind::Path(ref qself, ref path) => {
                    self.smart_resolve_path(pat.id, qself, path, PathSource::Pat);
                }
                PatKind::Struct(ref qself, ref path, ..) => {
                    self.smart_resolve_path(pat.id, qself, path, PathSource::Struct);
                }
                PatKind::Or(ref ps) => {
                    // Add a new set of bindings to the stack. `Or` here records that when a
                    // binding already exists in this set, it should not result in an error because
                    // `V1(a) | V2(a)` must be allowed and are checked for consistency later.
                    bindings.push((PatBoundCtx::Or, Default::default()));
                    for p in ps {
                        // Now we need to switch back to a product context so that each
                        // part of the or-pattern internally rejects already bound names.
                        // For example, `V1(a) | V2(a, a)` and `V1(a, a) | V2(a)` are bad.
                        bindings.push((PatBoundCtx::Product, Default::default()));
                        self.resolve_pattern_inner(p, pat_src, bindings);
                        // Move up the non-overlapping bindings to the or-pattern.
                        // Existing bindings just get "merged".
                        let collected = bindings.pop().unwrap().1;
                        bindings.last_mut().unwrap().1.extend(collected);
                    }
                    // This or-pattern itself can itself be part of a product,
                    // e.g. `(V1(a) | V2(a), a)` or `(a, V1(a) | V2(a))`.
                    // Both cases bind `a` again in a product pattern and must be rejected.
                    let collected = bindings.pop().unwrap().1;
                    bindings.last_mut().unwrap().1.extend(collected);

                    // Prevent visiting `ps` as we've already done so above.
                    return false;
                }
                _ => {}
            }
            true
        });
    }

    fn fresh_binding(
        &mut self,
        ident: Ident,
        pat_id: NodeId,
        pat_src: PatternSource,
        bindings: &mut SmallVec<[(PatBoundCtx, FxHashSet<Ident>); 1]>,
    ) -> Res {
        // Add the binding to the local ribs, if it doesn't already exist in the bindings map.
        // (We must not add it if it's in the bindings map because that breaks the assumptions
        // later passes make about or-patterns.)
        let ident = ident.normalize_to_macro_rules();

        let mut bound_iter = bindings.iter().filter(|(_, set)| set.contains(&ident));
        // Already bound in a product pattern? e.g. `(a, a)` which is not allowed.
        let already_bound_and = bound_iter.clone().any(|(ctx, _)| *ctx == PatBoundCtx::Product);
        // Already bound in an or-pattern? e.g. `V1(a) | V2(a)`.
        // This is *required* for consistency which is checked later.
        let already_bound_or = bound_iter.any(|(ctx, _)| *ctx == PatBoundCtx::Or);

        if already_bound_and {
            // Overlap in a product pattern somewhere; report an error.
            use ResolutionError::*;
            let error = match pat_src {
                // `fn f(a: u8, a: u8)`:
                PatternSource::FnParam => IdentifierBoundMoreThanOnceInParameterList,
                // `Variant(a, a)`:
                _ => IdentifierBoundMoreThanOnceInSamePattern,
            };
            self.report_error(ident.span, error(ident.name));
        }

        // Record as bound if it's valid:
        let ident_valid = ident.name != kw::Empty;
        if ident_valid {
            bindings.last_mut().unwrap().1.insert(ident);
        }

        if already_bound_or {
            // `Variant1(a) | Variant2(a)`, ok
            // Reuse definition from the first `a`.
            self.innermost_rib_bindings(ValueNS)[&ident]
        } else {
            let res = Res::Local(pat_id);
            if ident_valid {
                // A completely fresh binding add to the set if it's valid.
                self.innermost_rib_bindings(ValueNS).insert(ident, res);
            }
            res
        }
    }

    fn innermost_rib_bindings(&mut self, ns: Namespace) -> &mut IdentMap<Res> {
        &mut self.ribs[ns].last_mut().unwrap().bindings
    }

    fn try_resolve_as_non_binding(
        &mut self,
        pat_src: PatternSource,
        ann: BindingMode,
        ident: Ident,
        has_sub: bool,
    ) -> Option<Res> {
        // An immutable (no `mut`) by-value (no `ref`) binding pattern without
        // a sub pattern (no `@ $pat`) is syntactically ambiguous as it could
        // also be interpreted as a path to e.g. a constant, variant, etc.
        let is_syntactic_ambiguity = !has_sub && ann == BindingMode::NONE;

        let ls_binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS)?;
        let (res, binding) = match ls_binding {
            LexicalScopeBinding::Item(binding)
                if is_syntactic_ambiguity && binding.is_ambiguity_recursive() =>
            {
                // For ambiguous bindings we don't know all their definitions and cannot check
                // whether they can be shadowed by fresh bindings or not, so force an error.
                // issues/33118#issuecomment-233962221 (see below) still applies here,
                // but we have to ignore it for backward compatibility.
                self.r.record_use(ident, binding, Used::Other);
                return None;
            }
            LexicalScopeBinding::Item(binding) => (binding.res(), Some(binding)),
            LexicalScopeBinding::Res(res) => (res, None),
        };

        match res {
            Res::SelfCtor(_) // See #70549.
            | Res::Def(
                DefKind::Ctor(_, CtorKind::Const) | DefKind::Const | DefKind::ConstParam,
                _,
            ) if is_syntactic_ambiguity => {
                // Disambiguate in favor of a unit struct/variant or constant pattern.
                if let Some(binding) = binding {
                    self.r.record_use(ident, binding, Used::Other);
                }
                Some(res)
            }
            Res::Def(DefKind::Ctor(..) | DefKind::Const | DefKind::Static { .. }, _) => {
                // This is unambiguously a fresh binding, either syntactically
                // (e.g., `IDENT @ PAT` or `ref IDENT`) or because `IDENT` resolves
                // to something unusable as a pattern (e.g., constructor function),
                // but we still conservatively report an error, see
                // issues/33118#issuecomment-233962221 for one reason why.
                let binding = binding.expect("no binding for a ctor or static");
                self.report_error(
                    ident.span,
                    ResolutionError::BindingShadowsSomethingUnacceptable {
                        shadowing_binding: pat_src,
                        name: ident.name,
                        participle: if binding.is_import() { "imported" } else { "defined" },
                        article: binding.res().article(),
                        shadowed_binding: binding.res(),
                        shadowed_binding_span: binding.span,
                    },
                );
                None
            }
            Res::Def(DefKind::ConstParam, def_id) => {
                // Same as for DefKind::Const above, but here, `binding` is `None`, so we
                // have to construct the error differently
                self.report_error(
                    ident.span,
                    ResolutionError::BindingShadowsSomethingUnacceptable {
                        shadowing_binding: pat_src,
                        name: ident.name,
                        participle: "defined",
                        article: res.article(),
                        shadowed_binding: res,
                        shadowed_binding_span: self.r.def_span(def_id),
                    }
                );
                None
            }
            Res::Def(DefKind::Fn, _) | Res::Local(..) | Res::Err => {
                // These entities are explicitly allowed to be shadowed by fresh bindings.
                None
            }
            Res::SelfCtor(_) => {
                // We resolve `Self` in pattern position as an ident sometimes during recovery,
                // so delay a bug instead of ICEing. (Note: is this no longer true? We now ICE. If
                // this triggers, please convert to a delayed bug and add a test.)
                self.r.dcx().span_bug(
                    ident.span,
                    "unexpected `SelfCtor` in pattern, expected identifier"
                );
            }
            _ => span_bug!(
                ident.span,
                "unexpected resolution for an identifier in pattern: {:?}",
                res,
            ),
        }
    }

    // High-level and context dependent path resolution routine.
    // Resolves the path and records the resolution into definition map.
    // If resolution fails tries several techniques to find likely
    // resolution candidates, suggest imports or other help, and report
    // errors in user friendly way.
    fn smart_resolve_path(
        &mut self,
        id: NodeId,
        qself: &Option<P<QSelf>>,
        path: &Path,
        source: PathSource<'ast>,
    ) {
        self.smart_resolve_path_fragment(
            qself,
            &Segment::from_path(path),
            source,
            Finalize::new(id, path.span),
            RecordPartialRes::Yes,
        );
    }

    #[instrument(level = "debug", skip(self))]
    fn smart_resolve_path_fragment(
        &mut self,
        qself: &Option<P<QSelf>>,
        path: &[Segment],
        source: PathSource<'ast>,
        finalize: Finalize,
        record_partial_res: RecordPartialRes,
    ) -> PartialRes {
        let ns = source.namespace();

        let Finalize { node_id, path_span, .. } = finalize;
        let report_errors = |this: &mut Self, res: Option<Res>| {
            if this.should_report_errs() {
                let (err, candidates) =
                    this.smart_resolve_report_errors(path, None, path_span, source, res);

                let def_id = this.parent_scope.module.nearest_parent_mod();
                let instead = res.is_some();
                let suggestion = if let Some((start, end)) = this.diag_metadata.in_range
                    && path[0].ident.span.lo() == end.span.lo()
                    && !matches!(start.kind, ExprKind::Lit(_))
                {
                    let mut sugg = ".";
                    let mut span = start.span.between(end.span);
                    if span.lo() + BytePos(2) == span.hi() {
                        // There's no space between the start, the range op and the end, suggest
                        // removal which will look better.
                        span = span.with_lo(span.lo() + BytePos(1));
                        sugg = "";
                    }
                    Some((
                        span,
                        "you might have meant to write `.` instead of `..`",
                        sugg.to_string(),
                        Applicability::MaybeIncorrect,
                    ))
                } else if res.is_none()
                    && let PathSource::Type
                    | PathSource::Expr(_)
                    | PathSource::PreciseCapturingArg(..) = source
                {
                    this.suggest_adding_generic_parameter(path, source)
                } else {
                    None
                };

                let ue = UseError {
                    err,
                    candidates,
                    def_id,
                    instead,
                    suggestion,
                    path: path.into(),
                    is_call: source.is_call(),
                };

                this.r.use_injections.push(ue);
            }

            PartialRes::new(Res::Err)
        };

        // For paths originating from calls (like in `HashMap::new()`), tries
        // to enrich the plain `failed to resolve: ...` message with hints
        // about possible missing imports.
        //
        // Similar thing, for types, happens in `report_errors` above.
        let report_errors_for_call =
            |this: &mut Self, parent_err: Spanned<ResolutionError<'ra>>| {
                // Before we start looking for candidates, we have to get our hands
                // on the type user is trying to perform invocation on; basically:
                // we're transforming `HashMap::new` into just `HashMap`.
                let (following_seg, prefix_path) = match path.split_last() {
                    Some((last, path)) if !path.is_empty() => (Some(last), path),
                    _ => return Some(parent_err),
                };

                let (mut err, candidates) = this.smart_resolve_report_errors(
                    prefix_path,
                    following_seg,
                    path_span,
                    PathSource::Type,
                    None,
                );

                // There are two different error messages user might receive at
                // this point:
                // - E0412 cannot find type `{}` in this scope
                // - E0433 failed to resolve: use of undeclared type or module `{}`
                //
                // The first one is emitted for paths in type-position, and the
                // latter one - for paths in expression-position.
                //
                // Thus (since we're in expression-position at this point), not to
                // confuse the user, we want to keep the *message* from E0433 (so
                // `parent_err`), but we want *hints* from E0412 (so `err`).
                //
                // And that's what happens below - we're just mixing both messages
                // into a single one.
                let mut parent_err = this.r.into_struct_error(parent_err.span, parent_err.node);

                // overwrite all properties with the parent's error message
                err.messages = take(&mut parent_err.messages);
                err.code = take(&mut parent_err.code);
                swap(&mut err.span, &mut parent_err.span);
                err.children = take(&mut parent_err.children);
                err.sort_span = parent_err.sort_span;
                err.is_lint = parent_err.is_lint.clone();

                // merge the parent_err's suggestions with the typo (err's) suggestions
                match &mut err.suggestions {
                    Suggestions::Enabled(typo_suggestions) => match &mut parent_err.suggestions {
                        Suggestions::Enabled(parent_suggestions) => {
                            // If both suggestions are enabled, append parent_err's suggestions to err's suggestions.
                            typo_suggestions.append(parent_suggestions)
                        }
                        Suggestions::Sealed(_) | Suggestions::Disabled => {
                            // If the parent's suggestions are either sealed or disabled, it signifies that
                            // new suggestions cannot be added or removed from the diagnostic. Therefore,
                            // we assign both types of suggestions to err's suggestions and discard the
                            // existing suggestions in err.
                            err.suggestions = std::mem::take(&mut parent_err.suggestions);
                        }
                    },
                    Suggestions::Sealed(_) | Suggestions::Disabled => (),
                }

                parent_err.cancel();

                let def_id = this.parent_scope.module.nearest_parent_mod();

                if this.should_report_errs() {
                    if candidates.is_empty() {
                        if path.len() == 2
                            && let [segment] = prefix_path
                        {
                            // Delay to check whether methond name is an associated function or not
                            // ```
                            // let foo = Foo {};
                            // foo::bar(); // possibly suggest to foo.bar();
                            //```
                            err.stash(segment.ident.span, rustc_errors::StashKey::CallAssocMethod);
                        } else {
                            // When there is no suggested imports, we can just emit the error
                            // and suggestions immediately. Note that we bypass the usually error
                            // reporting routine (ie via `self.r.report_error`) because we need
                            // to post-process the `ResolutionError` above.
                            err.emit();
                        }
                    } else {
                        // If there are suggested imports, the error reporting is delayed
                        this.r.use_injections.push(UseError {
                            err,
                            candidates,
                            def_id,
                            instead: false,
                            suggestion: None,
                            path: prefix_path.into(),
                            is_call: source.is_call(),
                        });
                    }
                } else {
                    err.cancel();
                }

                // We don't return `Some(parent_err)` here, because the error will
                // be already printed either immediately or as part of the `use` injections
                None
            };

        let partial_res = match self.resolve_qpath_anywhere(
            qself,
            path,
            ns,
            path_span,
            source.defer_to_typeck(),
            finalize,
        ) {
            Ok(Some(partial_res)) if let Some(res) = partial_res.full_res() => {
                // if we also have an associated type that matches the ident, stash a suggestion
                if let Some(items) = self.diag_metadata.current_trait_assoc_items
                    && let [Segment { ident, .. }] = path
                    && items.iter().any(|item| {
                        item.ident == *ident && matches!(item.kind, AssocItemKind::Type(_))
                    })
                {
                    let mut diag = self.r.tcx.dcx().struct_allow("");
                    diag.span_suggestion_verbose(
                        path_span.shrink_to_lo(),
                        "there is an associated type with the same name",
                        "Self::",
                        Applicability::MaybeIncorrect,
                    );
                    diag.stash(path_span, StashKey::AssociatedTypeSuggestion);
                }

                if source.is_expected(res) || res == Res::Err {
                    partial_res
                } else {
                    report_errors(self, Some(res))
                }
            }

            Ok(Some(partial_res)) if source.defer_to_typeck() => {
                // Not fully resolved associated item `T::A::B` or `<T as Tr>::A::B`
                // or `<T>::A::B`. If `B` should be resolved in value namespace then
                // it needs to be added to the trait map.
                if ns == ValueNS {
                    let item_name = path.last().unwrap().ident;
                    let traits = self.traits_in_scope(item_name, ns);
                    self.r.trait_map.insert(node_id, traits);
                }

                if PrimTy::from_name(path[0].ident.name).is_some() {
                    let mut std_path = Vec::with_capacity(1 + path.len());

                    std_path.push(Segment::from_ident(Ident::with_dummy_span(sym::std)));
                    std_path.extend(path);
                    if let PathResult::Module(_) | PathResult::NonModule(_) =
                        self.resolve_path(&std_path, Some(ns), None)
                    {
                        // Check if we wrote `str::from_utf8` instead of `std::str::from_utf8`
                        let item_span =
                            path.iter().last().map_or(path_span, |segment| segment.ident.span);

                        self.r.confused_type_with_std_module.insert(item_span, path_span);
                        self.r.confused_type_with_std_module.insert(path_span, path_span);
                    }
                }

                partial_res
            }

            Err(err) => {
                if let Some(err) = report_errors_for_call(self, err) {
                    self.report_error(err.span, err.node);
                }

                PartialRes::new(Res::Err)
            }

            _ => report_errors(self, None),
        };

        if record_partial_res == RecordPartialRes::Yes {
            // Avoid recording definition of `A::B` in `<T as A>::B::C`.
            self.r.record_partial_res(node_id, partial_res);
            self.resolve_elided_lifetimes_in_path(partial_res, path, source, path_span);
            self.lint_unused_qualifications(path, ns, finalize);
        }

        partial_res
    }

    fn self_type_is_available(&mut self) -> bool {
        let binding = self
            .maybe_resolve_ident_in_lexical_scope(Ident::with_dummy_span(kw::SelfUpper), TypeNS);
        if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
    }

    fn self_value_is_available(&mut self, self_span: Span) -> bool {
        let ident = Ident::new(kw::SelfLower, self_span);
        let binding = self.maybe_resolve_ident_in_lexical_scope(ident, ValueNS);
        if let Some(LexicalScopeBinding::Res(res)) = binding { res != Res::Err } else { false }
    }

    /// A wrapper around [`Resolver::report_error`].
    ///
    /// This doesn't emit errors for function bodies if this is rustdoc.
    fn report_error(&mut self, span: Span, resolution_error: ResolutionError<'ra>) {
        if self.should_report_errs() {
            self.r.report_error(span, resolution_error);
        }
    }

    #[inline]
    /// If we're actually rustdoc then avoid giving a name resolution error for `cfg()` items or
    // an invalid `use foo::*;` was found, which can cause unbounded ammounts of "item not found"
    // errors. We silence them all.
    fn should_report_errs(&self) -> bool {
        !(self.r.tcx.sess.opts.actually_rustdoc && self.in_func_body)
            && !self.r.glob_error.is_some()
    }

    // Resolve in alternative namespaces if resolution in the primary namespace fails.
    fn resolve_qpath_anywhere(
        &mut self,
        qself: &Option<P<QSelf>>,
        path: &[Segment],
        primary_ns: Namespace,
        span: Span,
        defer_to_typeck: bool,
        finalize: Finalize,
    ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> {
        let mut fin_res = None;

        for (i, &ns) in [primary_ns, TypeNS, ValueNS].iter().enumerate() {
            if i == 0 || ns != primary_ns {
                match self.resolve_qpath(qself, path, ns, finalize)? {
                    Some(partial_res)
                        if partial_res.unresolved_segments() == 0 || defer_to_typeck =>
                    {
                        return Ok(Some(partial_res));
                    }
                    partial_res => {
                        if fin_res.is_none() {
                            fin_res = partial_res;
                        }
                    }
                }
            }
        }

        assert!(primary_ns != MacroNS);

        if qself.is_none() {
            let path_seg = |seg: &Segment| PathSegment::from_ident(seg.ident);
            let path = Path { segments: path.iter().map(path_seg).collect(), span, tokens: None };
            if let Ok((_, res)) =
                self.r.resolve_macro_path(&path, None, &self.parent_scope, false, false, None)
            {
                return Ok(Some(PartialRes::new(res)));
            }
        }

        Ok(fin_res)
    }

    /// Handles paths that may refer to associated items.
    fn resolve_qpath(
        &mut self,
        qself: &Option<P<QSelf>>,
        path: &[Segment],
        ns: Namespace,
        finalize: Finalize,
    ) -> Result<Option<PartialRes>, Spanned<ResolutionError<'ra>>> {
        debug!(
            "resolve_qpath(qself={:?}, path={:?}, ns={:?}, finalize={:?})",
            qself, path, ns, finalize,
        );

        if let Some(qself) = qself {
            if qself.position == 0 {
                // This is a case like `<T>::B`, where there is no
                // trait to resolve. In that case, we leave the `B`
                // segment to be resolved by type-check.
                return Ok(Some(PartialRes::with_unresolved_segments(
                    Res::Def(DefKind::Mod, CRATE_DEF_ID.to_def_id()),
                    path.len(),
                )));
            }

            let num_privacy_errors = self.r.privacy_errors.len();
            // Make sure that `A` in `<T as A>::B::C` is a trait.
            let trait_res = self.smart_resolve_path_fragment(
                &None,
                &path[..qself.position],
                PathSource::Trait(AliasPossibility::No),
                Finalize::new(finalize.node_id, qself.path_span),
                RecordPartialRes::No,
            );

            if trait_res.expect_full_res() == Res::Err {
                return Ok(Some(trait_res));
            }

            // Truncate additional privacy errors reported above,
            // because they'll be recomputed below.
            self.r.privacy_errors.truncate(num_privacy_errors);

            // Make sure `A::B` in `<T as A>::B::C` is a trait item.
            //
            // Currently, `path` names the full item (`A::B::C`, in
            // our example). so we extract the prefix of that that is
            // the trait (the slice upto and including
            // `qself.position`). And then we recursively resolve that,
            // but with `qself` set to `None`.
            let ns = if qself.position + 1 == path.len() { ns } else { TypeNS };
            let partial_res = self.smart_resolve_path_fragment(
                &None,
                &path[..=qself.position],
                PathSource::TraitItem(ns),
                Finalize::with_root_span(finalize.node_id, finalize.path_span, qself.path_span),
                RecordPartialRes::No,
            );

            // The remaining segments (the `C` in our example) will
            // have to be resolved by type-check, since that requires doing
            // trait resolution.
            return Ok(Some(PartialRes::with_unresolved_segments(
                partial_res.base_res(),
                partial_res.unresolved_segments() + path.len() - qself.position - 1,
            )));
        }

        let result = match self.resolve_path(path, Some(ns), Some(finalize)) {
            PathResult::NonModule(path_res) => path_res,
            PathResult::Module(ModuleOrUniformRoot::Module(module)) if !module.is_normal() => {
                PartialRes::new(module.res().unwrap())
            }
            // In `a(::assoc_item)*` `a` cannot be a module. If `a` does resolve to a module we
            // don't report an error right away, but try to fallback to a primitive type.
            // So, we are still able to successfully resolve something like
            //
            // use std::u8; // bring module u8 in scope
            // fn f() -> u8 { // OK, resolves to primitive u8, not to std::u8
            //     u8::max_value() // OK, resolves to associated function <u8>::max_value,
            //                     // not to nonexistent std::u8::max_value
            // }
            //
            // Such behavior is required for backward compatibility.
            // The same fallback is used when `a` resolves to nothing.
            PathResult::Module(ModuleOrUniformRoot::Module(_)) | PathResult::Failed { .. }
                if (ns == TypeNS || path.len() > 1)
                    && PrimTy::from_name(path[0].ident.name).is_some() =>
            {
                let prim = PrimTy::from_name(path[0].ident.name).unwrap();
                let tcx = self.r.tcx();

                let gate_err_sym_msg = match prim {
                    PrimTy::Float(FloatTy::F16) if !tcx.features().f16 => {
                        Some((sym::f16, "the type `f16` is unstable"))
                    }
                    PrimTy::Float(FloatTy::F128) if !tcx.features().f128 => {
                        Some((sym::f128, "the type `f128` is unstable"))
                    }
                    _ => None,
                };

                if let Some((sym, msg)) = gate_err_sym_msg {
                    let span = path[0].ident.span;
                    if !span.allows_unstable(sym) {
                        feature_err(tcx.sess, sym, span, msg).emit();
                    }
                };

                PartialRes::with_unresolved_segments(Res::PrimTy(prim), path.len() - 1)
            }
            PathResult::Module(ModuleOrUniformRoot::Module(module)) => {
                PartialRes::new(module.res().unwrap())
            }
            PathResult::Failed {
                is_error_from_last_segment: false,
                span,
                label,
                suggestion,
                module,
                segment_name,
            } => {
                return Err(respan(span, ResolutionError::FailedToResolve {
                    segment: Some(segment_name),
                    label,
                    suggestion,
                    module,
                }));
            }
            PathResult::Module(..) | PathResult::Failed { .. } => return Ok(None),
            PathResult::Indeterminate => bug!("indeterminate path result in resolve_qpath"),
        };

        Ok(Some(result))
    }

    fn with_resolved_label(&mut self, label: Option<Label>, id: NodeId, f: impl FnOnce(&mut Self)) {
        if let Some(label) = label {
            if label.ident.as_str().as_bytes()[1] != b'_' {
                self.diag_metadata.unused_labels.insert(id, label.ident.span);
            }

            if let Ok((_, orig_span)) = self.resolve_label(label.ident) {
                diagnostics::signal_label_shadowing(self.r.tcx.sess, orig_span, label.ident)
            }

            self.with_label_rib(RibKind::Normal, |this| {
                let ident = label.ident.normalize_to_macro_rules();
                this.label_ribs.last_mut().unwrap().bindings.insert(ident, id);
                f(this);
            });
        } else {
            f(self);
        }
    }

    fn resolve_labeled_block(&mut self, label: Option<Label>, id: NodeId, block: &'ast Block) {
        self.with_resolved_label(label, id, |this| this.visit_block(block));
    }

    fn resolve_block(&mut self, block: &'ast Block) {
        debug!("(resolving block) entering block");
        // Move down in the graph, if there's an anonymous module rooted here.
        let orig_module = self.parent_scope.module;
        let anonymous_module = self.r.block_map.get(&block.id).cloned(); // clones a reference

        let mut num_macro_definition_ribs = 0;
        if let Some(anonymous_module) = anonymous_module {
            debug!("(resolving block) found anonymous module, moving down");
            self.ribs[ValueNS].push(Rib::new(RibKind::Module(anonymous_module)));
            self.ribs[TypeNS].push(Rib::new(RibKind::Module(anonymous_module)));
            self.parent_scope.module = anonymous_module;
        } else {
            self.ribs[ValueNS].push(Rib::new(RibKind::Normal));
        }

        let prev = self.diag_metadata.current_block_could_be_bare_struct_literal.take();
        if let (true, [Stmt { kind: StmtKind::Expr(expr), .. }]) =
            (block.could_be_bare_literal, &block.stmts[..])
            && let ExprKind::Type(..) = expr.kind
        {
            self.diag_metadata.current_block_could_be_bare_struct_literal = Some(block.span);
        }
        // Descend into the block.
        for stmt in &block.stmts {
            if let StmtKind::Item(ref item) = stmt.kind
                && let ItemKind::MacroDef(..) = item.kind
            {
                num_macro_definition_ribs += 1;
                let res = self.r.local_def_id(item.id).to_def_id();
                self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res)));
                self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res)));
            }

            self.visit_stmt(stmt);
        }
        self.diag_metadata.current_block_could_be_bare_struct_literal = prev;

        // Move back up.
        self.parent_scope.module = orig_module;
        for _ in 0..num_macro_definition_ribs {
            self.ribs[ValueNS].pop();
            self.label_ribs.pop();
        }
        self.last_block_rib = self.ribs[ValueNS].pop();
        if anonymous_module.is_some() {
            self.ribs[TypeNS].pop();
        }
        debug!("(resolving block) leaving block");
    }

    fn resolve_anon_const(&mut self, constant: &'ast AnonConst, anon_const_kind: AnonConstKind) {
        debug!(
            "resolve_anon_const(constant: {:?}, anon_const_kind: {:?})",
            constant, anon_const_kind
        );

        self.resolve_anon_const_manual(
            constant.value.is_potential_trivial_const_arg(true),
            anon_const_kind,
            |this| this.resolve_expr(&constant.value, None),
        )
    }

    /// There are a few places that we need to resolve an anon const but we did not parse an
    /// anon const so cannot provide an `&'ast AnonConst`. Right now this is just unbraced
    /// const arguments that were parsed as type arguments, and `legacy_const_generics` which
    /// parse as normal function argument expressions. To avoid duplicating the code for resolving
    /// an anon const we have this function which lets the caller manually call `resolve_expr` or
    /// `smart_resolve_path`.
    fn resolve_anon_const_manual(
        &mut self,
        is_trivial_const_arg: bool,
        anon_const_kind: AnonConstKind,
        resolve_expr: impl FnOnce(&mut Self),
    ) {
        let is_repeat_expr = match anon_const_kind {
            AnonConstKind::ConstArg(is_repeat_expr) => is_repeat_expr,
            _ => IsRepeatExpr::No,
        };

        let may_use_generics = match anon_const_kind {
            AnonConstKind::EnumDiscriminant => {
                ConstantHasGenerics::No(NoConstantGenericsReason::IsEnumDiscriminant)
            }
            AnonConstKind::InlineConst => ConstantHasGenerics::Yes,
            AnonConstKind::ConstArg(_) => {
                if self.r.tcx.features().generic_const_exprs || is_trivial_const_arg {
                    ConstantHasGenerics::Yes
                } else {
                    ConstantHasGenerics::No(NoConstantGenericsReason::NonTrivialConstArg)
                }
            }
        };

        self.with_constant_rib(is_repeat_expr, may_use_generics, None, |this| {
            this.with_lifetime_rib(LifetimeRibKind::Elided(LifetimeRes::Infer), |this| {
                resolve_expr(this);
            });
        });
    }

    fn resolve_expr_field(&mut self, f: &'ast ExprField, e: &'ast Expr) {
        self.resolve_expr(&f.expr, Some(e));
        self.visit_ident(f.ident);
        walk_list!(self, visit_attribute, f.attrs.iter());
    }

    fn resolve_expr(&mut self, expr: &'ast Expr, parent: Option<&'ast Expr>) {
        // First, record candidate traits for this expression if it could
        // result in the invocation of a method call.

        self.record_candidate_traits_for_expr_if_necessary(expr);

        // Next, resolve the node.
        match expr.kind {
            ExprKind::Path(ref qself, ref path) => {
                self.smart_resolve_path(expr.id, qself, path, PathSource::Expr(parent));
                visit::walk_expr(self, expr);
            }

            ExprKind::Struct(ref se) => {
                self.smart_resolve_path(expr.id, &se.qself, &se.path, PathSource::Struct);
                // This is the same as `visit::walk_expr(self, expr);`, but we want to pass the
                // parent in for accurate suggestions when encountering `Foo { bar }` that should
                // have been `Foo { bar: self.bar }`.
                if let Some(qself) = &se.qself {
                    self.visit_ty(&qself.ty);
                }
                self.visit_path(&se.path, expr.id);
                walk_list!(self, resolve_expr_field, &se.fields, expr);
                match &se.rest {
                    StructRest::Base(expr) => self.visit_expr(expr),
                    StructRest::Rest(_span) => {}
                    StructRest::None => {}
                }
            }

            ExprKind::Break(Some(label), _) | ExprKind::Continue(Some(label)) => {
                match self.resolve_label(label.ident) {
                    Ok((node_id, _)) => {
                        // Since this res is a label, it is never read.
                        self.r.label_res_map.insert(expr.id, node_id);
                        self.diag_metadata.unused_labels.remove(&node_id);
                    }
                    Err(error) => {
                        self.report_error(label.ident.span, error);
                    }
                }

                // visit `break` argument if any
                visit::walk_expr(self, expr);
            }

            ExprKind::Break(None, Some(ref e)) => {
                // We use this instead of `visit::walk_expr` to keep the parent expr around for
                // better diagnostics.
                self.resolve_expr(e, Some(expr));
            }

            ExprKind::Let(ref pat, ref scrutinee, _, _) => {
                self.visit_expr(scrutinee);
                self.resolve_pattern_top(pat, PatternSource::Let);
            }

            ExprKind::If(ref cond, ref then, ref opt_else) => {
                self.with_rib(ValueNS, RibKind::Normal, |this| {
                    let old = this.diag_metadata.in_if_condition.replace(cond);
                    this.visit_expr(cond);
                    this.diag_metadata.in_if_condition = old;
                    this.visit_block(then);
                });
                if let Some(expr) = opt_else {
                    self.visit_expr(expr);
                }
            }

            ExprKind::Loop(ref block, label, _) => {
                self.resolve_labeled_block(label, expr.id, block)
            }

            ExprKind::While(ref cond, ref block, label) => {
                self.with_resolved_label(label, expr.id, |this| {
                    this.with_rib(ValueNS, RibKind::Normal, |this| {
                        let old = this.diag_metadata.in_if_condition.replace(cond);
                        this.visit_expr(cond);
                        this.diag_metadata.in_if_condition = old;
                        this.visit_block(block);
                    })
                });
            }

            ExprKind::ForLoop { ref pat, ref iter, ref body, label, kind: _ } => {
                self.visit_expr(iter);
                self.with_rib(ValueNS, RibKind::Normal, |this| {
                    this.resolve_pattern_top(pat, PatternSource::For);
                    this.resolve_labeled_block(label, expr.id, body);
                });
            }

            ExprKind::Block(ref block, label) => self.resolve_labeled_block(label, block.id, block),

            // Equivalent to `visit::walk_expr` + passing some context to children.
            ExprKind::Field(ref subexpression, _) => {
                self.resolve_expr(subexpression, Some(expr));
            }
            ExprKind::MethodCall(box MethodCall { ref seg, ref receiver, ref args, .. }) => {
                self.resolve_expr(receiver, Some(expr));
                for arg in args {
                    self.resolve_expr(arg, None);
                }
                self.visit_path_segment(seg);
            }

            ExprKind::Call(ref callee, ref arguments) => {
                self.resolve_expr(callee, Some(expr));
                let const_args = self.r.legacy_const_generic_args(callee).unwrap_or_default();
                for (idx, argument) in arguments.iter().enumerate() {
                    // Constant arguments need to be treated as AnonConst since
                    // that is how they will be later lowered to HIR.
                    if const_args.contains(&idx) {
                        self.resolve_anon_const_manual(
                            argument.is_potential_trivial_const_arg(true),
                            AnonConstKind::ConstArg(IsRepeatExpr::No),
                            |this| this.resolve_expr(argument, None),
                        );
                    } else {
                        self.resolve_expr(argument, None);
                    }
                }
            }
            ExprKind::Type(ref _type_expr, ref _ty) => {
                visit::walk_expr(self, expr);
            }
            // For closures, RibKind::FnOrCoroutine is added in visit_fn
            ExprKind::Closure(box ast::Closure {
                binder: ClosureBinder::For { ref generic_params, span },
                ..
            }) => {
                self.with_generic_param_rib(
                    generic_params,
                    RibKind::Normal,
                    LifetimeRibKind::Generics {
                        binder: expr.id,
                        kind: LifetimeBinderKind::Closure,
                        span,
                    },
                    |this| visit::walk_expr(this, expr),
                );
            }
            ExprKind::Closure(..) => visit::walk_expr(self, expr),
            ExprKind::Gen(..) => {
                self.with_label_rib(RibKind::FnOrCoroutine, |this| visit::walk_expr(this, expr));
            }
            ExprKind::Repeat(ref elem, ref ct) => {
                self.visit_expr(elem);
                self.resolve_anon_const(ct, AnonConstKind::ConstArg(IsRepeatExpr::Yes));
            }
            ExprKind::ConstBlock(ref ct) => {
                self.resolve_anon_const(ct, AnonConstKind::InlineConst);
            }
            ExprKind::Index(ref elem, ref idx, _) => {
                self.resolve_expr(elem, Some(expr));
                self.visit_expr(idx);
            }
            ExprKind::Assign(ref lhs, ref rhs, _) => {
                if !self.diag_metadata.is_assign_rhs {
                    self.diag_metadata.in_assignment = Some(expr);
                }
                self.visit_expr(lhs);
                self.diag_metadata.is_assign_rhs = true;
                self.diag_metadata.in_assignment = None;
                self.visit_expr(rhs);
                self.diag_metadata.is_assign_rhs = false;
            }
            ExprKind::Range(Some(ref start), Some(ref end), RangeLimits::HalfOpen) => {
                self.diag_metadata.in_range = Some((start, end));
                self.resolve_expr(start, Some(expr));
                self.resolve_expr(end, Some(expr));
                self.diag_metadata.in_range = None;
            }
            _ => {
                visit::walk_expr(self, expr);
            }
        }
    }

    fn record_candidate_traits_for_expr_if_necessary(&mut self, expr: &'ast Expr) {
        match expr.kind {
            ExprKind::Field(_, ident) => {
                // #6890: Even though you can't treat a method like a field,
                // we need to add any trait methods we find that match the
                // field name so that we can do some nice error reporting
                // later on in typeck.
                let traits = self.traits_in_scope(ident, ValueNS);
                self.r.trait_map.insert(expr.id, traits);
            }
            ExprKind::MethodCall(ref call) => {
                debug!("(recording candidate traits for expr) recording traits for {}", expr.id);
                let traits = self.traits_in_scope(call.seg.ident, ValueNS);
                self.r.trait_map.insert(expr.id, traits);
            }
            _ => {
                // Nothing to do.
            }
        }
    }

    fn traits_in_scope(&mut self, ident: Ident, ns: Namespace) -> Vec<TraitCandidate> {
        self.r.traits_in_scope(
            self.current_trait_ref.as_ref().map(|(module, _)| *module),
            &self.parent_scope,
            ident.span.ctxt(),
            Some((ident.name, ns)),
        )
    }

    /// Construct the list of in-scope lifetime parameters for impl trait lowering.
    /// We include all lifetime parameters, either named or "Fresh".
    /// The order of those parameters does not matter, as long as it is
    /// deterministic.
    fn record_lifetime_params_for_impl_trait(&mut self, impl_trait_node_id: NodeId) {
        let mut extra_lifetime_params = vec![];

        for rib in self.lifetime_ribs.iter().rev() {
            extra_lifetime_params
                .extend(rib.bindings.iter().map(|(&ident, &(node_id, res))| (ident, node_id, res)));
            match rib.kind {
                LifetimeRibKind::Item => break,
                LifetimeRibKind::AnonymousCreateParameter { binder, .. } => {
                    if let Some(earlier_fresh) = self.r.extra_lifetime_params_map.get(&binder) {
                        extra_lifetime_params.extend(earlier_fresh);
                    }
                }
                _ => {}
            }
        }

        self.r.extra_lifetime_params_map.insert(impl_trait_node_id, extra_lifetime_params);
    }

    fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option<Res> {
        // FIXME: This caching may be incorrect in case of multiple `macro_rules`
        // items with the same name in the same module.
        // Also hygiene is not considered.
        let mut doc_link_resolutions = std::mem::take(&mut self.r.doc_link_resolutions);
        let res = *doc_link_resolutions
            .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
            .or_default()
            .entry((Symbol::intern(path_str), ns))
            .or_insert_with_key(|(path, ns)| {
                let res = self.r.resolve_rustdoc_path(path.as_str(), *ns, self.parent_scope);
                if let Some(res) = res
                    && let Some(def_id) = res.opt_def_id()
                    && !def_id.is_local()
                    && self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
                    && matches!(
                        self.r.tcx.sess.opts.resolve_doc_links,
                        ResolveDocLinks::ExportedMetadata
                    )
                {
                    // Encoding foreign def ids in proc macro crate metadata will ICE.
                    return None;
                }
                res
            });
        self.r.doc_link_resolutions = doc_link_resolutions;
        res
    }

    fn resolve_doc_links(&mut self, attrs: &[Attribute], maybe_exported: MaybeExported<'_>) {
        match self.r.tcx.sess.opts.resolve_doc_links {
            ResolveDocLinks::None => return,
            ResolveDocLinks::ExportedMetadata
                if !self.r.tcx.crate_types().iter().copied().any(CrateType::has_metadata)
                    || !maybe_exported.eval(self.r) =>
            {
                return;
            }
            ResolveDocLinks::Exported
                if !maybe_exported.eval(self.r)
                    && !rustdoc::has_primitive_or_keyword_docs(attrs) =>
            {
                return;
            }
            ResolveDocLinks::ExportedMetadata
            | ResolveDocLinks::Exported
            | ResolveDocLinks::All => {}
        }

        if !attrs.iter().any(|attr| attr.may_have_doc_links()) {
            return;
        }

        let mut need_traits_in_scope = false;
        for path_str in rustdoc::attrs_to_preprocessed_links(attrs) {
            // Resolve all namespaces due to no disambiguator or for diagnostics.
            let mut any_resolved = false;
            let mut need_assoc = false;
            for ns in [TypeNS, ValueNS, MacroNS] {
                if let Some(res) = self.resolve_and_cache_rustdoc_path(&path_str, ns) {
                    // Rustdoc ignores tool attribute resolutions and attempts
                    // to resolve their prefixes for diagnostics.
                    any_resolved = !matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Tool));
                } else if ns != MacroNS {
                    need_assoc = true;
                }
            }

            // Resolve all prefixes for type-relative resolution or for diagnostics.
            if need_assoc || !any_resolved {
                let mut path = &path_str[..];
                while let Some(idx) = path.rfind("::") {
                    path = &path[..idx];
                    need_traits_in_scope = true;
                    for ns in [TypeNS, ValueNS, MacroNS] {
                        self.resolve_and_cache_rustdoc_path(path, ns);
                    }
                }
            }
        }

        if need_traits_in_scope {
            // FIXME: hygiene is not considered.
            let mut doc_link_traits_in_scope = std::mem::take(&mut self.r.doc_link_traits_in_scope);
            doc_link_traits_in_scope
                .entry(self.parent_scope.module.nearest_parent_mod().expect_local())
                .or_insert_with(|| {
                    self.r
                        .traits_in_scope(None, &self.parent_scope, SyntaxContext::root(), None)
                        .into_iter()
                        .filter_map(|tr| {
                            if !tr.def_id.is_local()
                                && self.r.tcx.crate_types().contains(&CrateType::ProcMacro)
                                && matches!(
                                    self.r.tcx.sess.opts.resolve_doc_links,
                                    ResolveDocLinks::ExportedMetadata
                                )
                            {
                                // Encoding foreign def ids in proc macro crate metadata will ICE.
                                return None;
                            }
                            Some(tr.def_id)
                        })
                        .collect()
                });
            self.r.doc_link_traits_in_scope = doc_link_traits_in_scope;
        }
    }

    fn lint_unused_qualifications(&mut self, path: &[Segment], ns: Namespace, finalize: Finalize) {
        // Don't lint on global paths because the user explicitly wrote out the full path.
        if let Some(seg) = path.first()
            && seg.ident.name == kw::PathRoot
        {
            return;
        }

        if finalize.path_span.from_expansion()
            || path.iter().any(|seg| seg.ident.span.from_expansion())
        {
            return;
        }

        let end_pos =
            path.iter().position(|seg| seg.has_generic_args).map_or(path.len(), |pos| pos + 1);
        let unqualified = path[..end_pos].iter().enumerate().skip(1).rev().find_map(|(i, seg)| {
            // Preserve the current namespace for the final path segment, but use the type
            // namespace for all preceding segments
            //
            // e.g. for `std::env::args` check the `ValueNS` for `args` but the `TypeNS` for
            // `std` and `env`
            //
            // If the final path segment is beyond `end_pos` all the segments to check will
            // use the type namespace
            let ns = if i + 1 == path.len() { ns } else { TypeNS };
            let res = self.r.partial_res_map.get(&seg.id?)?.full_res()?;
            let binding = self.resolve_ident_in_lexical_scope(seg.ident, ns, None, None)?;
            (res == binding.res()).then_some((seg, binding))
        });

        if let Some((seg, binding)) = unqualified {
            self.r.potentially_unnecessary_qualifications.push(UnnecessaryQualification {
                binding,
                node_id: finalize.node_id,
                path_span: finalize.path_span,
                removal_span: path[0].ident.span.until(seg.ident.span),
            });
        }
    }
}

/// Walks the whole crate in DFS order, visiting each item, counting the declared number of
/// lifetime generic parameters and function parameters.
struct ItemInfoCollector<'a, 'ra, 'tcx> {
    r: &'a mut Resolver<'ra, 'tcx>,
}

impl ItemInfoCollector<'_, '_, '_> {
    fn collect_fn_info(&mut self, sig: &FnSig, id: NodeId) {
        let sig = DelegationFnSig {
            header: sig.header,
            param_count: sig.decl.inputs.len(),
            has_self: sig.decl.has_self(),
            c_variadic: sig.decl.c_variadic(),
        };
        self.r.delegation_fn_sigs.insert(self.r.local_def_id(id), sig);
    }
}

impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> {
    fn visit_item(&mut self, item: &'ast Item) {
        match &item.kind {
            ItemKind::TyAlias(box TyAlias { ref generics, .. })
            | ItemKind::Const(box ConstItem { ref generics, .. })
            | ItemKind::Fn(box Fn { ref generics, .. })
            | ItemKind::Enum(_, ref generics)
            | ItemKind::Struct(_, ref generics)
            | ItemKind::Union(_, ref generics)
            | ItemKind::Impl(box Impl { ref generics, .. })
            | ItemKind::Trait(box Trait { ref generics, .. })
            | ItemKind::TraitAlias(ref generics, _) => {
                if let ItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
                    self.collect_fn_info(sig, item.id);
                }

                let def_id = self.r.local_def_id(item.id);
                let count = generics
                    .params
                    .iter()
                    .filter(|param| matches!(param.kind, ast::GenericParamKind::Lifetime { .. }))
                    .count();
                self.r.item_generics_num_lifetimes.insert(def_id, count);
            }

            ItemKind::Mod(..)
            | ItemKind::ForeignMod(..)
            | ItemKind::Static(..)
            | ItemKind::Use(..)
            | ItemKind::ExternCrate(..)
            | ItemKind::MacroDef(..)
            | ItemKind::GlobalAsm(..)
            | ItemKind::MacCall(..)
            | ItemKind::DelegationMac(..) => {}
            ItemKind::Delegation(..) => {
                // Delegated functions have lifetimes, their count is not necessarily zero.
                // But skipping the delegation items here doesn't mean that the count will be considered zero,
                // it means there will be a panic when retrieving the count,
                // but for delegation items we are never actually retrieving that count in practice.
            }
        }
        visit::walk_item(self, item)
    }

    fn visit_assoc_item(&mut self, item: &'ast AssocItem, ctxt: AssocCtxt) {
        if let AssocItemKind::Fn(box Fn { ref sig, .. }) = &item.kind {
            self.collect_fn_info(sig, item.id);
        }
        visit::walk_assoc_item(self, item, ctxt);
    }
}

impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
    pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) {
        visit::walk_crate(&mut ItemInfoCollector { r: self }, krate);
        let mut late_resolution_visitor = LateResolutionVisitor::new(self);
        late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID));
        visit::walk_crate(&mut late_resolution_visitor, krate);
        for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() {
            self.lint_buffer.buffer_lint(
                lint::builtin::UNUSED_LABELS,
                *id,
                *span,
                BuiltinLintDiag::UnusedLabel,
            );
        }
    }
}

/// Check if definition matches a path
fn def_id_matches_path(tcx: TyCtxt<'_>, mut def_id: DefId, expected_path: &[&str]) -> bool {
    let mut path = expected_path.iter().rev();
    while let (Some(parent), Some(next_step)) = (tcx.opt_parent(def_id), path.next()) {
        if !tcx.opt_item_name(def_id).map_or(false, |n| n.as_str() == *next_step) {
            return false;
        }
        def_id = parent;
    }
    true
}
