//! This crate is responsible for the part of name resolution that doesn't require type checker.
//!
//! Module structure of the crate is built here.
//! Paths in macros, imports, expressions, types, patterns are resolved here.
//! Label and lifetime names are resolved here as well.
//!
//! Type-relative name resolution (methods, fields, associated items) happens in `rustc_hir_analysis`.

// tidy-alphabetical-start
#![allow(internal_features)]
#![feature(arbitrary_self_types)]
#![feature(const_default)]
#![feature(const_trait_impl)]
#![feature(control_flow_into_value)]
#![feature(default_field_values)]
#![feature(deref_patterns)]
#![feature(iter_intersperse)]
#![feature(rustc_attrs)]
#![feature(trim_prefix_suffix)]
#![recursion_limit = "256"]
// tidy-alphabetical-end

use std::cell::Ref;
use std::collections::BTreeSet;
use std::ops::ControlFlow;
use std::sync::Arc;
use std::{fmt, mem};

use diagnostics::{ImportSuggestion, LabelSuggestion, StructCtor, Suggestion};
use effective_visibilities::EffectiveVisibilitiesVisitor;
use errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use hygiene::Macros20NormalizedSyntaxContext;
use imports::{Import, ImportData, ImportKind, NameResolution, PendingDecl};
use late::{
    ForwardGenericParamBanReason, HasGenericParams, PathSource, PatternSource,
    UnnecessaryQualification,
};
use macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef};
use rustc_arena::{DroplessArena, TypedArena};
use rustc_ast::node_id::NodeMap;
use rustc_ast::{
    self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, Expr, ExprKind,
    GenericArg, GenericArgs, Generics, NodeId, Path, attr,
};
use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default};
use rustc_data_structures::intern::Interned;
use rustc_data_structures::steal::Steal;
use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard};
use rustc_data_structures::unord::{UnordItems, UnordMap, UnordSet};
use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed, LintBuffer};
use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind};
use rustc_feature::BUILTIN_ATTRIBUTES;
use rustc_hir::attrs::StrippedCfgItem;
use rustc_hir::def::Namespace::{self, *};
use rustc_hir::def::{
    self, CtorOf, DefKind, DocLinkResMap, MacroKinds, NonMacroAttrKind, PartialRes, PerNS,
};
use rustc_hir::def_id::{CRATE_DEF_ID, CrateNum, DefId, LOCAL_CRATE, LocalDefId, LocalDefIdMap};
use rustc_hir::definitions::{PerParentDisambiguatorState, PerParentDisambiguatorsMap};
use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate, find_attr};
use rustc_index::bit_set::DenseBitSet;
use rustc_metadata::creader::CStore;
use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport};
use rustc_middle::middle::privacy::EffectiveVisibilities;
use rustc_middle::query::Providers;
use rustc_middle::ty::{
    self, DelegationInfo, MainDefinition, PerOwnerResolverData, RegisteredTools,
    ResolverAstLowering, ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility,
};
use rustc_middle::{bug, span_bug};
use rustc_session::config::CrateType;
use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency};
use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym};
use smallvec::{SmallVec, smallvec};
use tracing::{debug, instrument};

type Res = def::Res<NodeId>;

mod build_reduced_graph;
mod check_unused;
mod def_collector;
mod diagnostics;
mod effective_visibilities;
mod errors;
mod ident;
mod imports;
mod late;
mod macros;
pub mod rustdoc;

pub use macros::registered_tools_ast;

use crate::ref_mut::{CmCell, CmRefCell};

#[derive(Copy, Clone, PartialEq, Debug)]
enum Determinacy {
    Determined,
    Undetermined,
}

impl Determinacy {
    fn determined(determined: bool) -> Determinacy {
        if determined { Determinacy::Determined } else { Determinacy::Undetermined }
    }
}

/// A specific scope in which a name can be looked up.
#[derive(Clone, Copy, Debug)]
enum Scope<'ra> {
    /// Inert attributes registered by derive macros.
    DeriveHelpers(LocalExpnId),
    /// Inert attributes registered by derive macros, but used before they are actually declared.
    /// This scope will exist until the compatibility lint `LEGACY_DERIVE_HELPERS`
    /// is turned into a hard error.
    DeriveHelpersCompat,
    /// Textual `let`-like scopes introduced by `macro_rules!` items.
    MacroRules(MacroRulesScopeRef<'ra>),
    /// Non-glob names declared in the given module.
    /// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK`
    /// lint if it should be reported.
    ModuleNonGlobs(Module<'ra>, Option<NodeId>),
    /// Glob names declared in the given module.
    /// The node ID is for reporting the `PROC_MACRO_DERIVE_RESOLUTION_FALLBACK`
    /// lint if it should be reported.
    ModuleGlobs(Module<'ra>, Option<NodeId>),
    /// Names introduced by `#[macro_use]` attributes on `extern crate` items.
    MacroUsePrelude,
    /// Built-in attributes.
    BuiltinAttrs,
    /// Extern prelude names introduced by `extern crate` items.
    ExternPreludeItems,
    /// Extern prelude names introduced by `--extern` flags.
    ExternPreludeFlags,
    /// Tool modules introduced with `#![register_tool]`.
    ToolPrelude,
    /// Standard library prelude introduced with an internal `#[prelude_import]` import.
    StdLibPrelude,
    /// Built-in types.
    BuiltinTypes,
}

/// Names from different contexts may want to visit different subsets of all specific scopes
/// with different restrictions when looking up the resolution.
#[derive(Clone, Copy, Debug)]
enum ScopeSet<'ra> {
    /// All scopes with the given namespace.
    All(Namespace),
    /// Two scopes inside a module, for non-glob and glob bindings.
    Module(Namespace, Module<'ra>),
    /// A module, then extern prelude (used for mixed 2015-2018 mode in macros).
    ModuleAndExternPrelude(Namespace, Module<'ra>),
    /// Just two extern prelude scopes.
    ExternPrelude,
    /// Same as `All(MacroNS)`, but with the given macro kind restriction.
    Macro(MacroKind),
}

/// Everything you need to know about a name's location to resolve it.
/// Serves as a starting point for the scope visitor.
/// This struct is currently used only for early resolution (imports and macros),
/// but not for late resolution yet.
#[derive(Clone, Copy, Debug)]
struct ParentScope<'ra> {
    module: Module<'ra>,
    expansion: LocalExpnId,
    macro_rules: MacroRulesScopeRef<'ra>,
    derives: &'ra [ast::Path],
}

impl<'ra> ParentScope<'ra> {
    /// Creates a parent scope with the passed argument used as the module scope component,
    /// and other scope components set to default empty values.
    fn module(module: LocalModule<'ra>, arenas: &'ra ResolverArenas<'ra>) -> ParentScope<'ra> {
        ParentScope {
            module: module.to_module(),
            expansion: LocalExpnId::ROOT,
            macro_rules: arenas.alloc_macro_rules_scope(MacroRulesScope::Empty),
            derives: &[],
        }
    }
}

#[derive(Copy, Debug, Clone)]
struct InvocationParent {
    parent_def: LocalDefId,
    impl_trait_context: ImplTraitContext,
    in_attr: bool,
    const_arg_context: ConstArgContext,
    owner: NodeId,
}

impl InvocationParent {
    const ROOT: Self = Self {
        parent_def: CRATE_DEF_ID,
        impl_trait_context: ImplTraitContext::Existential,
        in_attr: false,
        const_arg_context: ConstArgContext::NonDirect,
        owner: CRATE_NODE_ID,
    };
}

#[derive(Copy, Debug, Clone)]
enum ImplTraitContext {
    Existential,
    Universal,
    InBinding,
}

#[derive(Copy, Clone, Debug)]
enum ConstArgContext {
    Direct,
    /// Either inside of an `AnonConst` or not inside a const argument at all.
    NonDirect,
}

/// Used for tracking import use types which will be used for redundant import checking.
///
/// ### Used::Scope Example
///
/// ```rust,compile_fail
/// #![deny(redundant_imports)]
/// use std::mem::drop;
/// fn main() {
///     let s = Box::new(32);
///     drop(s);
/// }
/// ```
///
/// Used::Other is for other situations like module-relative uses.
#[derive(Clone, Copy, PartialEq, PartialOrd, Debug)]
enum Used {
    Scope,
    Other,
}

#[derive(Debug)]
struct BindingError {
    name: Ident,
    origin: Vec<(Span, ast::Pat)>,
    target: Vec<ast::Pat>,
    could_be_path: bool,
}

#[derive(Debug)]
enum ResolutionError<'ra> {
    /// Error E0401: can't use type or const parameters from outer item.
    GenericParamsFromOuterItem {
        outer_res: Res,
        has_generic_params: HasGenericParams,
        def_kind: DefKind,
        /// 1. label span, 2. item span, 3. item kind
        inner_item: Option<(Span, Span, ast::ItemKind)>,
        current_self_ty: Option<String>,
    },
    /// Error E0403: the name is already used for a type or const parameter in this generic
    /// parameter list.
    NameAlreadyUsedInParameterList(Ident, Span),
    /// Error E0407: method is not a member of trait.
    MethodNotMemberOfTrait(Ident, String, Option<Symbol>),
    /// Error E0437: type is not a member of trait.
    TypeNotMemberOfTrait(Ident, String, Option<Symbol>),
    /// Error E0438: const is not a member of trait.
    ConstNotMemberOfTrait(Ident, String, Option<Symbol>),
    /// Error E0408: variable `{}` is not bound in all patterns.
    VariableNotBoundInPattern(BindingError, ParentScope<'ra>),
    /// Error E0409: variable `{}` is bound in inconsistent ways within the same match arm.
    VariableBoundWithDifferentMode(Ident, Span),
    /// Error E0415: identifier is bound more than once in this parameter list.
    IdentifierBoundMoreThanOnceInParameterList(Ident),
    /// Error E0416: identifier is bound more than once in the same pattern.
    IdentifierBoundMoreThanOnceInSamePattern(Ident),
    /// Error E0426: use of undeclared label.
    UndeclaredLabel { name: Symbol, suggestion: Option<LabelSuggestion> },
    /// Error E0433: failed to resolve.
    FailedToResolve {
        segment: Symbol,
        label: String,
        suggestion: Option<Suggestion>,
        module: Option<ModuleOrUniformRoot<'ra>>,
        message: String,
    },
    /// Error E0434: can't capture dynamic environment in a fn item.
    CannotCaptureDynamicEnvironmentInFnItem,
    /// Error E0435: attempt to use a non-constant value in a constant.
    AttemptToUseNonConstantValueInConstant {
        ident: Ident,
        suggestion: &'static str,
        current: &'static str,
        type_span: Option<Span>,
    },
    /// Error E0530: `X` bindings cannot shadow `Y`s.
    BindingShadowsSomethingUnacceptable {
        shadowing_binding: PatternSource,
        name: Symbol,
        participle: &'static str,
        article: &'static str,
        shadowed_binding: Res,
        shadowed_binding_span: Span,
    },
    /// Error E0128: generic parameters with a default cannot use forward-declared identifiers.
    ForwardDeclaredGenericParam(Symbol, ForwardGenericParamBanReason),
    // FIXME(generic_const_parameter_types): This should give custom output specifying it's only
    // problematic to use *forward declared* parameters when the feature is enabled.
    /// ERROR E0770: the type of const parameters must not depend on other generic parameters.
    ParamInTyOfConstParam { name: Symbol },
    /// generic parameters must not be used inside const evaluations.
    ///
    /// This error is only emitted when using `min_const_generics`.
    ParamInNonTrivialAnonConst {
        is_gca: bool,
        name: Symbol,
        param_kind: ParamKindInNonTrivialAnonConst,
    },
    /// generic parameters must not be used inside enum discriminants.
    ///
    /// This error is emitted even with `generic_const_exprs`.
    ParamInEnumDiscriminant { name: Symbol, param_kind: ParamKindInEnumDiscriminant },
    /// Error E0735: generic parameters with a default cannot use `Self`
    ForwardDeclaredSelf(ForwardGenericParamBanReason),
    /// Error E0767: use of unreachable label
    UnreachableLabel { name: Symbol, definition_span: Span, suggestion: Option<LabelSuggestion> },
    /// Error E0323, E0324, E0325: mismatch between trait item and impl item.
    TraitImplMismatch {
        name: Ident,
        kind: &'static str,
        trait_path: String,
        trait_item_span: Span,
        code: ErrCode,
    },
    /// Error E0201: multiple impl items for the same trait item.
    TraitImplDuplicate { name: Ident, trait_item_span: Span, old_span: Span },
    /// Inline asm `sym` operand must refer to a `fn` or `static`.
    InvalidAsmSym,
    /// `self` used instead of `Self` in a generic parameter
    LowercaseSelf,
    /// A never pattern has a binding.
    BindingInNeverPattern,
}

#[derive(Debug)]
enum VisResolutionError {
    Relative2018(Span, ast::Path),
    AncestorOnly(Span),
    FailedToResolve(Span, Symbol, String, Option<Suggestion>, String),
    ExpectedFound(Span, String, Res),
    Indeterminate(Span),
    ModuleOnly(Span),
}

/// A minimal representation of a path segment. We use this in resolve because we synthesize 'path
/// segments' which don't have the rest of an AST or HIR `PathSegment`.
#[derive(Clone, Copy, Debug)]
struct Segment {
    ident: Ident,
    id: Option<NodeId>,
    /// Signals whether this `PathSegment` has generic arguments.
    has_generic_args: bool,
    /// Signals whether this `PathSegment` has lifetime arguments.
    has_lifetime_args: bool,
    args_span: Span,
}

impl Segment {
    fn from_path(path: &Path) -> Vec<Segment> {
        path.segments.iter().map(|s| s.into()).collect()
    }

    fn from_ident(ident: Ident) -> Segment {
        Segment {
            ident,
            id: None,
            has_generic_args: false,
            has_lifetime_args: false,
            args_span: DUMMY_SP,
        }
    }

    fn names_to_string(segments: &[Segment]) -> String {
        names_to_string(segments.iter().map(|seg| seg.ident.name))
    }
}

impl<'a> From<&'a ast::PathSegment> for Segment {
    fn from(seg: &'a ast::PathSegment) -> Segment {
        let has_generic_args = seg.args.is_some();
        let (args_span, has_lifetime_args) = if let Some(args) = seg.args.as_deref() {
            match args {
                GenericArgs::AngleBracketed(args) => {
                    let found_lifetimes = args
                        .args
                        .iter()
                        .any(|arg| matches!(arg, AngleBracketedArg::Arg(GenericArg::Lifetime(_))));
                    (args.span, found_lifetimes)
                }
                GenericArgs::Parenthesized(args) => (args.span, true),
                GenericArgs::ParenthesizedElided(span) => (*span, true),
            }
        } else {
            (DUMMY_SP, false)
        };
        Segment {
            ident: seg.ident,
            id: Some(seg.id),
            has_generic_args,
            has_lifetime_args,
            args_span,
        }
    }
}

/// Name declaration used during late resolution.
#[derive(Debug, Copy, Clone)]
enum LateDecl<'ra> {
    /// A regular name declaration.
    Decl(Decl<'ra>),
    /// A name definition from a rib, e.g. a local variable.
    /// Omits most of the data from regular `Decl` for performance reasons.
    RibDef(Res),
}

impl<'ra> LateDecl<'ra> {
    fn res(self) -> Res {
        match self {
            LateDecl::Decl(binding) => binding.res(),
            LateDecl::RibDef(res) => res,
        }
    }
}

#[derive(Copy, Clone, PartialEq, Debug)]
enum ModuleOrUniformRoot<'ra> {
    /// Regular module.
    Module(Module<'ra>),

    /// Virtual module that denotes resolution in a module with fallback to extern prelude.
    /// Used for paths starting with `::` coming from 2015 edition macros
    /// used in 2018+ edition crates.
    ModuleAndExternPrelude(Module<'ra>),

    /// Virtual module that denotes resolution in extern prelude.
    /// Used for paths starting with `::` on 2018 edition.
    ExternPrelude,

    /// Virtual module that denotes resolution in current scope.
    /// Used only for resolving single-segment imports. The reason it exists is that import paths
    /// are always split into two parts, the first of which should be some kind of module.
    CurrentScope,

    /// Virtual module for the resolution of base names of namespaced crates,
    /// where the base name doesn't correspond to a module in the extern prelude.
    /// E.g. `my_api::utils` is in the prelude, but `my_api` is not.
    OpenModule(Symbol),
}

#[derive(Debug)]
enum PathResult<'ra> {
    Module(ModuleOrUniformRoot<'ra>),
    NonModule(PartialRes),
    Indeterminate,
    Failed {
        span: Span,
        label: String,
        suggestion: Option<Suggestion>,
        is_error_from_last_segment: bool,
        /// The final module being resolved, for instance:
        ///
        /// ```compile_fail
        /// mod a {
        ///     mod b {
        ///         mod c {}
        ///     }
        /// }
        ///
        /// use a::not_exist::c;
        /// ```
        ///
        /// In this case, `module` will point to `a`.
        module: Option<ModuleOrUniformRoot<'ra>>,
        /// The segment of target
        segment: Ident,
        error_implied_by_parse_error: bool,
        message: String,
        note: Option<String>,
    },
}

impl<'ra> PathResult<'ra> {
    fn failed(
        ident: Ident,
        is_error_from_last_segment: bool,
        finalize: bool,
        error_implied_by_parse_error: bool,
        module: Option<ModuleOrUniformRoot<'ra>>,
        label_and_suggestion_and_note: impl FnOnce() -> (
            String,
            String,
            Option<Suggestion>,
            Option<String>,
        ),
    ) -> PathResult<'ra> {
        let (message, label, suggestion, note) = if finalize {
            label_and_suggestion_and_note()
        } else {
            // FIXME: this output isn't actually present in the test suite.
            (format!("cannot find `{ident}` in this scope"), String::new(), None, None)
        };
        PathResult::Failed {
            span: ident.span,
            segment: ident,
            label,
            suggestion,
            is_error_from_last_segment,
            module,
            error_implied_by_parse_error,
            message,
            note,
        }
    }
}

#[derive(Debug)]
enum ModuleKind {
    /// An anonymous module; e.g., just a block.
    ///
    /// ```
    /// fn main() {
    ///     fn f() {} // (1)
    ///     { // This is an anonymous module
    ///         f(); // This resolves to (2) as we are inside the block.
    ///         fn f() {} // (2)
    ///     }
    ///     f(); // Resolves to (1)
    /// }
    /// ```
    Block,
    /// Any module with a name.
    ///
    /// This could be:
    ///
    /// * A normal module – either `mod from_file;` or `mod from_block { }` –
    ///   or the crate root (which is conceptually a top-level module).
    ///   The crate root will have `None` for the symbol.
    /// * A trait or an enum (it implicitly contains associated types, methods and variant
    ///   constructors).
    Def(DefKind, DefId, NodeId, Option<Symbol>),
}

impl ModuleKind {
    fn opt_def_id(&self) -> Option<DefId> {
        match self {
            ModuleKind::Def(_, def_id, _, _) => Some(*def_id),
            _ => None,
        }
    }

    fn def_id(&self) -> DefId {
        self.opt_def_id().expect("`Module::def_id` is called on a block module")
    }

    fn is_local(&self) -> bool {
        match self {
            ModuleKind::Def(_, def_id, ..) => def_id.is_local(),
            ModuleKind::Block => true,
        }
    }
}

/// Combination of a symbol and its macros 2.0 normalized hygiene context.
/// Used as a key in various kinds of name containers, including modules (as a part of slightly
/// larger `BindingKey`) and preludes.
///
/// Often passed around together with `orig_ident_span: Span`, which is an unnormalized span
/// of the original `Ident` from which `IdentKey` was obtained. This span is not used in map keys,
/// but used in a number of other scenarios - diagnostics, edition checks, `allow_unstable` checks
/// and similar. This is required because macros 2.0 normalization is lossy and the normalized
/// spans / syntax contexts no longer contain parts of macro backtraces, while the original span
/// contains everything.
#[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
struct IdentKey {
    name: Symbol,
    ctxt: Macros20NormalizedSyntaxContext,
}

impl IdentKey {
    #[inline]
    fn new(ident: Ident) -> IdentKey {
        IdentKey { name: ident.name, ctxt: Macros20NormalizedSyntaxContext::new(ident.span.ctxt()) }
    }

    #[inline]
    fn new_adjusted(ident: Ident, expn_id: ExpnId) -> (IdentKey, Option<ExpnId>) {
        let (ctxt, def) = Macros20NormalizedSyntaxContext::new_adjusted(ident.span.ctxt(), expn_id);
        (IdentKey { name: ident.name, ctxt }, def)
    }

    #[inline]
    fn with_root_ctxt(name: Symbol) -> Self {
        let ctxt = Macros20NormalizedSyntaxContext::new_unchecked(SyntaxContext::root());
        IdentKey { name, ctxt }
    }

    #[inline]
    fn orig(self, orig_ident_span: Span) -> Ident {
        Ident::new(self.name, orig_ident_span)
    }
}

/// A key that identifies a binding in a given `Module`.
///
/// Multiple bindings in the same module can have the same key (in a valid
/// program) if all but one of them come from glob imports.
#[derive(Copy, Clone, PartialEq, Eq, Hash, Debug)]
struct BindingKey {
    /// The identifier for the binding, always the `normalize_to_macros_2_0` version of the
    /// identifier.
    ident: IdentKey,
    ns: Namespace,
    /// When we add an underscore binding (with ident `_`) to some module, this field has
    /// a non-zero value that uniquely identifies this binding in that module.
    /// For non-underscore bindings this field is zero.
    /// When a key is constructed for name lookup (as opposed to name definition), this field is
    /// also zero, even for underscore names, so for underscores the lookup will never succeed.
    disambiguator: u32,
}

impl BindingKey {
    fn new(ident: IdentKey, ns: Namespace) -> Self {
        BindingKey { ident, ns, disambiguator: 0 }
    }

    fn new_disambiguated(
        ident: IdentKey,
        ns: Namespace,
        disambiguator: impl FnOnce() -> u32,
    ) -> BindingKey {
        let disambiguator = if ident.name == kw::Underscore { disambiguator() } else { 0 };
        BindingKey { ident, ns, disambiguator }
    }
}

type Resolutions<'ra> = CmRefCell<FxIndexMap<BindingKey, &'ra CmRefCell<NameResolution<'ra>>>>;

/// One node in the tree of modules.
///
/// Note that a "module" in resolve is broader than a `mod` that you declare in Rust code. It may be one of these:
///
/// * `mod`
/// * crate root (aka, top-level anonymous module)
/// * `enum`
/// * `trait`
/// * curly-braced block with statements
///
/// You can use [`ModuleData::kind`] to determine the kind of module this is.
struct ModuleData<'ra> {
    /// The direct parent module (it may not be a `mod`, however).
    parent: Option<Module<'ra>>,
    /// What kind of module this is, because this may not be a `mod`.
    kind: ModuleKind,

    /// Mapping between names and their (possibly in-progress) resolutions in this module.
    /// Resolutions in modules from other crates are not populated until accessed.
    lazy_resolutions: Resolutions<'ra>,
    /// True if this is a module from other crate that needs to be populated on access.
    populate_on_access: CacheCell<bool>,
    /// Used to disambiguate underscore items (`const _: T = ...`) in the module.
    underscore_disambiguator: CmCell<u32>,

    /// Macro invocations that can expand into items in this module.
    unexpanded_invocations: CmRefCell<FxHashSet<LocalExpnId>>,

    /// Whether `#[no_implicit_prelude]` is active.
    no_implicit_prelude: bool,

    glob_importers: CmRefCell<Vec<Import<'ra>>>,
    globs: CmRefCell<Vec<Import<'ra>>>,

    /// Used to memoize the traits in this module for faster searches through all traits in scope.
    traits: CmRefCell<
        Option<Box<[(Symbol, Decl<'ra>, Option<Module<'ra>>, bool /* lint ambiguous */)]>>,
    >,

    /// Span of the module itself. Used for error reporting.
    span: Span,

    expansion: ExpnId,

    /// Declaration for implicitly declared names that come with a module,
    /// like `self` (not yet used), or `crate`/`$crate` (for root modules).
    self_decl: Option<Decl<'ra>>,
}

/// All modules are unique and allocated on a same arena,
/// so we can use referential equality to compare them.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[rustc_pass_by_value]
struct Module<'ra>(Interned<'ra, ModuleData<'ra>>);

/// Same as `Module`, but is guaranteed to be from the current crate.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[rustc_pass_by_value]
struct LocalModule<'ra>(Interned<'ra, ModuleData<'ra>>);

/// Same as `Module`, but is guaranteed to be from an external crate.
#[derive(Clone, Copy, PartialEq, Eq, Hash)]
#[rustc_pass_by_value]
struct ExternModule<'ra>(Interned<'ra, ModuleData<'ra>>);

// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the
// contained data.
// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees
// are upheld.
impl std::hash::Hash for ModuleData<'_> {
    fn hash<H>(&self, _: &mut H)
    where
        H: std::hash::Hasher,
    {
        unreachable!()
    }
}

impl<'ra> ModuleData<'ra> {
    fn new(
        parent: Option<Module<'ra>>,
        kind: ModuleKind,
        expansion: ExpnId,
        span: Span,
        no_implicit_prelude: bool,
        vis: Visibility<DefId>,
        arenas: &'ra ResolverArenas<'ra>,
    ) -> Self {
        let is_foreign = !kind.is_local();
        let self_decl = match kind {
            ModuleKind::Def(def_kind, def_id, ..) => {
                let expn_id = expansion.as_local().unwrap_or(LocalExpnId::ROOT);
                Some(arenas.new_def_decl(Res::Def(def_kind, def_id), vis, span, expn_id, parent))
            }
            ModuleKind::Block => None,
        };
        ModuleData {
            parent,
            kind,
            lazy_resolutions: Default::default(),
            populate_on_access: CacheCell::new(is_foreign),
            underscore_disambiguator: CmCell::new(0),
            unexpanded_invocations: Default::default(),
            no_implicit_prelude,
            glob_importers: CmRefCell::new(Vec::new()),
            globs: CmRefCell::new(Vec::new()),
            traits: CmRefCell::new(None),
            span,
            expansion,
            self_decl,
        }
    }

    /// Get name of the module.
    fn name(&self) -> Option<Symbol> {
        match self.kind {
            ModuleKind::Block => None,
            ModuleKind::Def(.., name) => name,
        }
    }

    fn opt_def_id(&self) -> Option<DefId> {
        self.kind.opt_def_id()
    }

    fn def_id(&self) -> DefId {
        self.kind.def_id()
    }

    fn is_local(&self) -> bool {
        self.kind.is_local()
    }

    fn has_unexpanded_invocations(&self) -> bool {
        !self.unexpanded_invocations.borrow().is_empty()
    }

    fn res(&self) -> Option<Res> {
        match self.kind {
            ModuleKind::Def(kind, def_id, _, _) => Some(Res::Def(kind, def_id)),
            _ => None,
        }
    }

    fn def_kind(&self) -> Option<DefKind> {
        match self.kind {
            ModuleKind::Def(def_kind, ..) => Some(def_kind),
            ModuleKind::Block => None,
        }
    }
}

impl<'ra> Module<'ra> {
    fn for_each_child<'tcx, R: AsRef<Resolver<'ra, 'tcx>>>(
        self,
        resolver: &R,
        mut f: impl FnMut(&R, IdentKey, Span, Namespace, Decl<'ra>),
    ) {
        for (key, name_resolution) in resolver.as_ref().resolutions(self).borrow().iter() {
            let name_resolution = name_resolution.borrow();
            if let Some(decl) = name_resolution.best_decl() {
                f(resolver, key.ident, name_resolution.orig_ident_span, key.ns, decl);
            }
        }
    }

    fn for_each_child_mut<'tcx, R: AsMut<Resolver<'ra, 'tcx>>>(
        self,
        resolver: &mut R,
        mut f: impl FnMut(&mut R, IdentKey, Span, Namespace, Decl<'ra>),
    ) {
        for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
            let name_resolution = name_resolution.borrow();
            if let Some(decl) = name_resolution.best_decl() {
                f(resolver, key.ident, name_resolution.orig_ident_span, key.ns, decl);
            }
        }
    }

    /// This modifies `self` in place. The traits will be stored in `self.traits`.
    fn ensure_traits<'tcx>(self, resolver: &Resolver<'ra, 'tcx>) {
        let mut traits = self.traits.borrow_mut(resolver.as_ref());
        if traits.is_none() {
            let mut collected_traits = Vec::new();
            self.for_each_child(resolver, |r, ident, _, ns, binding| {
                if ns != TypeNS {
                    return;
                }
                if let Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) = binding.res() {
                    collected_traits.push((
                        ident.name,
                        binding,
                        r.as_ref().get_module(def_id),
                        binding.is_ambiguity_recursive(),
                    ));
                }
            });
            *traits = Some(collected_traits.into_boxed_slice());
        }
    }

    // `self` resolves to the first module ancestor that `is_normal`.
    fn is_normal(self) -> bool {
        self.def_kind() == Some(DefKind::Mod)
    }

    fn is_trait(self) -> bool {
        matches!(self.def_kind(), Some(DefKind::Trait))
    }

    fn nearest_item_scope(self) -> Module<'ra> {
        match self.def_kind() {
            Some(DefKind::Enum | DefKind::Trait) => {
                self.parent.expect("enum or trait module without a parent")
            }
            _ => self,
        }
    }

    /// The [`DefId`] of the nearest `mod` item ancestor (which may be this module).
    /// This may be the crate root.
    fn nearest_parent_mod(self) -> DefId {
        match self.kind {
            ModuleKind::Def(DefKind::Mod, def_id, _, _) => def_id,
            _ => self.parent.expect("non-root module without parent").nearest_parent_mod(),
        }
    }

    /// The [`NodeId`] of the nearest `mod` item ancestor (which may be this module).
    /// This may be the crate root.
    fn nearest_parent_mod_node_id(self) -> NodeId {
        match self.kind {
            ModuleKind::Def(DefKind::Mod, _, node_id, _) => node_id,
            _ => self.parent.expect("non-root module without parent").nearest_parent_mod_node_id(),
        }
    }

    fn is_ancestor_of(self, mut other: Self) -> bool {
        while self != other {
            if let Some(parent) = other.parent {
                other = parent;
            } else {
                return false;
            }
        }
        true
    }

    #[track_caller]
    fn expect_local(self) -> LocalModule<'ra> {
        match self.kind {
            ModuleKind::Def(_, def_id, _, _) if !def_id.is_local() => {
                span_bug!(self.span, "unexpected extern module: {self:?}")
            }
            ModuleKind::Def(..) | ModuleKind::Block => LocalModule(self.0),
        }
    }

    #[track_caller]
    fn expect_extern(self) -> ExternModule<'ra> {
        match self.kind {
            ModuleKind::Def(_, def_id, _, _) if !def_id.is_local() => ExternModule(self.0),
            ModuleKind::Def(..) | ModuleKind::Block => {
                span_bug!(self.span, "unexpected local module: {self:?}")
            }
        }
    }
}

impl<'ra> LocalModule<'ra> {
    fn new(
        parent: Option<LocalModule<'ra>>,
        kind: ModuleKind,
        vis: Visibility<DefId>,
        expn_id: ExpnId,
        span: Span,
        no_implicit_prelude: bool,
        arenas: &'ra ResolverArenas<'ra>,
    ) -> LocalModule<'ra> {
        assert!(kind.is_local());
        let parent = parent.map(|m| m.to_module());
        let data = ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude, vis, arenas);
        LocalModule(Interned::new_unchecked(arenas.modules.alloc(data)))
    }

    fn to_module(self) -> Module<'ra> {
        Module(self.0)
    }
}

impl<'ra> ExternModule<'ra> {
    fn new(
        parent: Option<ExternModule<'ra>>,
        kind: ModuleKind,
        vis: Visibility<DefId>,
        expn_id: ExpnId,
        span: Span,
        no_implicit_prelude: bool,
        arenas: &'ra ResolverArenas<'ra>,
    ) -> ExternModule<'ra> {
        assert!(!kind.is_local());
        let parent = parent.map(|m| m.to_module());
        let data = ModuleData::new(parent, kind, expn_id, span, no_implicit_prelude, vis, arenas);
        ExternModule(Interned::new_unchecked(arenas.modules.alloc(data)))
    }

    fn to_module(self) -> Module<'ra> {
        Module(self.0)
    }
}

impl<'ra> std::ops::Deref for Module<'ra> {
    type Target = ModuleData<'ra>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'ra> std::ops::Deref for LocalModule<'ra> {
    type Target = ModuleData<'ra>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'ra> std::ops::Deref for ExternModule<'ra> {
    type Target = ModuleData<'ra>;

    fn deref(&self) -> &Self::Target {
        &self.0
    }
}

impl<'ra> fmt::Debug for Module<'ra> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        match self.res() {
            None => write!(f, "block"),
            Some(res) => write!(f, "{:?}", res),
        }
    }
}

impl<'ra> fmt::Debug for LocalModule<'ra> {
    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
        self.to_module().fmt(f)
    }
}

/// Data associated with any name declaration.
#[derive(Clone, Debug)]
struct DeclData<'ra> {
    kind: DeclKind<'ra>,
    ambiguity: CmCell<Option<(Decl<'ra>, bool /*warning*/)>>,
    expansion: LocalExpnId,
    span: Span,
    initial_vis: Visibility<DefId>,
    /// If the declaration refers to an ambiguous glob set, then this is the most visible
    /// declaration from the set, if its visibility is different from `initial_vis`.
    ambiguity_vis_max: CmCell<Option<Decl<'ra>>>,
    /// If the declaration refers to an ambiguous glob set, then this is the least visible
    /// declaration from the set, if its visibility is different from `initial_vis`.
    ambiguity_vis_min: CmCell<Option<Decl<'ra>>>,
    parent_module: Option<Module<'ra>>,
}

/// All name declarations are unique and allocated on a same arena,
/// so we can use referential equality to compare them.
type Decl<'ra> = Interned<'ra, DeclData<'ra>>;

// Allows us to use Interned without actually enforcing (via Hash/PartialEq/...) uniqueness of the
// contained data.
// FIXME: We may wish to actually have at least debug-level assertions that Interned's guarantees
// are upheld.
impl std::hash::Hash for DeclData<'_> {
    fn hash<H>(&self, _: &mut H)
    where
        H: std::hash::Hasher,
    {
        unreachable!()
    }
}

/// Name declaration kind.
#[derive(Clone, Copy, Debug)]
enum DeclKind<'ra> {
    /// The name declaration is a definition (possibly without a `DefId`),
    /// can be provided by source code or built into the language.
    Def(Res),
    /// The name declaration is a link to another name declaration.
    Import { source_decl: Decl<'ra>, import: Import<'ra> },
}

impl<'ra> DeclKind<'ra> {
    /// Is this an import declaration?
    fn is_import(&self) -> bool {
        matches!(*self, DeclKind::Import { .. })
    }
}

#[derive(Debug)]
struct PrivacyError<'ra> {
    ident: Ident,
    decl: Decl<'ra>,
    dedup_span: Span,
    outermost_res: Option<(Res, Ident)>,
    parent_scope: ParentScope<'ra>,
    /// Is the format `use a::{b,c}`?
    single_nested: bool,
    source: Option<ast::Expr>,
}

#[derive(Debug)]
struct UseError<'a> {
    err: Diag<'a>,
    /// Candidates which user could `use` to access the missing type.
    candidates: Vec<ImportSuggestion>,
    /// The `NodeId` of the module to place the use-statements in.
    node_id: NodeId,
    /// Whether the diagnostic should say "instead" (as in `consider importing ... instead`).
    instead: bool,
    /// Extra free-form suggestion.
    suggestion: Option<(Span, &'static str, String, Applicability)>,
    /// Path `Segment`s at the place of use that failed. Used for accurate suggestion after telling
    /// the user to import the item directly.
    path: Vec<Segment>,
    /// Whether the expected source is a call
    is_call: bool,
}

#[derive(Debug)]
struct DelayedVisResolutionError<'ra> {
    vis: ast::Visibility,
    parent_scope: ParentScope<'ra>,
    error: VisResolutionError,
}

#[derive(Clone, Copy, PartialEq, Debug)]
enum AmbiguityKind {
    BuiltinAttr,
    DeriveHelper,
    MacroRulesVsModularized,
    GlobVsOuter,
    GlobVsGlob,
    GlobVsExpanded,
    MoreExpandedVsOuter,
}

impl AmbiguityKind {
    fn descr(self) -> &'static str {
        match self {
            AmbiguityKind::BuiltinAttr => "a name conflict with a builtin attribute",
            AmbiguityKind::DeriveHelper => "a name conflict with a derive helper attribute",
            AmbiguityKind::MacroRulesVsModularized => {
                "a conflict between a `macro_rules` name and a non-`macro_rules` name from another module"
            }
            AmbiguityKind::GlobVsOuter => {
                "a conflict between a name from a glob import and an outer scope during import or macro resolution"
            }
            AmbiguityKind::GlobVsGlob => "multiple glob imports of a name in the same module",
            AmbiguityKind::GlobVsExpanded => {
                "a conflict between a name from a glob import and a macro-expanded name in the same module during import or macro resolution"
            }
            AmbiguityKind::MoreExpandedVsOuter => {
                "a conflict between a macro-expanded name and a less macro-expanded name from outer scope during import or macro resolution"
            }
        }
    }
}

#[derive(Clone, Copy, PartialEq)]
enum AmbiguityWarning {
    GlobImport,
    PanicImport,
}

struct AmbiguityError<'ra> {
    kind: AmbiguityKind,
    ambig_vis: Option<(Visibility, Visibility)>,
    ident: Ident,
    b1: Decl<'ra>,
    b2: Decl<'ra>,
    scope1: Scope<'ra>,
    scope2: Scope<'ra>,
    warning: Option<AmbiguityWarning>,
}

impl<'ra> DeclData<'ra> {
    fn vis(&self) -> Visibility<DefId> {
        // Select the maximum visibility if there are multiple ambiguous glob imports.
        self.ambiguity_vis_max.get().map(|d| d.vis()).unwrap_or_else(|| self.initial_vis)
    }

    fn min_vis(&self) -> Visibility<DefId> {
        // Select the minimum visibility if there are multiple ambiguous glob imports.
        self.ambiguity_vis_min.get().map(|d| d.vis()).unwrap_or_else(|| self.initial_vis)
    }

    fn res(&self) -> Res {
        match self.kind {
            DeclKind::Def(res) => res,
            DeclKind::Import { source_decl, .. } => source_decl.res(),
        }
    }

    fn import_source(&self) -> Decl<'ra> {
        match self.kind {
            DeclKind::Import { source_decl, .. } => source_decl,
            _ => unreachable!(),
        }
    }

    fn descent_to_ambiguity(self: Decl<'ra>) -> Option<(Decl<'ra>, Decl<'ra>)> {
        match self.ambiguity.get() {
            Some((ambig_binding, _)) => Some((self, ambig_binding)),
            None => match self.kind {
                DeclKind::Import { source_decl, .. } => source_decl.descent_to_ambiguity(),
                _ => None,
            },
        }
    }

    fn is_ambiguity_recursive(&self) -> bool {
        self.ambiguity.get().is_some()
            || match self.kind {
                DeclKind::Import { source_decl, .. } => source_decl.is_ambiguity_recursive(),
                _ => false,
            }
    }

    fn is_possibly_imported_variant(&self) -> bool {
        match self.kind {
            DeclKind::Import { source_decl, .. } => source_decl.is_possibly_imported_variant(),
            DeclKind::Def(Res::Def(DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..), _)) => {
                true
            }
            DeclKind::Def(..) => false,
        }
    }

    fn is_extern_crate(&self) -> bool {
        match self.kind {
            DeclKind::Import { import, .. } => {
                matches!(import.kind, ImportKind::ExternCrate { .. })
            }
            DeclKind::Def(Res::Def(_, def_id)) => def_id.is_crate_root(),
            _ => false,
        }
    }

    fn is_import(&self) -> bool {
        matches!(self.kind, DeclKind::Import { .. })
    }

    /// The binding introduced by `#[macro_export] macro_rules` is a public import, but it might
    /// not be perceived as such by users, so treat it as a non-import in some diagnostics.
    fn is_import_user_facing(&self) -> bool {
        matches!(self.kind, DeclKind::Import { import, .. }
            if !matches!(import.kind, ImportKind::MacroExport))
    }

    fn is_glob_import(&self) -> bool {
        match self.kind {
            DeclKind::Import { import, .. } => import.is_glob(),
            _ => false,
        }
    }

    fn is_assoc_item(&self) -> bool {
        matches!(
            self.res(),
            Res::Def(DefKind::AssocConst { .. } | DefKind::AssocFn | DefKind::AssocTy, _)
        )
    }

    fn macro_kinds(&self) -> Option<MacroKinds> {
        self.res().macro_kinds()
    }

    fn reexport_chain(self: Decl<'ra>) -> SmallVec<[Reexport; 2]> {
        let mut reexport_chain = SmallVec::new();
        let mut next_binding = self;
        while let DeclKind::Import { source_decl, import, .. } = next_binding.kind {
            reexport_chain.push(import.simplify());
            next_binding = source_decl;
        }
        reexport_chain
    }

    // Suppose that we resolved macro invocation with `invoc_parent_expansion` to binding `binding`
    // at some expansion round `max(invoc, binding)` when they both emerged from macros.
    // Then this function returns `true` if `self` may emerge from a macro *after* that
    // in some later round and screw up our previously found resolution.
    // See more detailed explanation in
    // https://github.com/rust-lang/rust/pull/53778#issuecomment-419224049
    fn may_appear_after(&self, invoc_parent_expansion: LocalExpnId, decl: Decl<'_>) -> bool {
        // self > max(invoc, decl) => !(self <= invoc || self <= decl)
        // Expansions are partially ordered, so "may appear after" is an inversion of
        // "certainly appears before or simultaneously" and includes unordered cases.
        let self_parent_expansion = self.expansion;
        let other_parent_expansion = decl.expansion;
        let certainly_before_other_or_simultaneously =
            other_parent_expansion.is_descendant_of(self_parent_expansion);
        let certainly_before_invoc_or_simultaneously =
            invoc_parent_expansion.is_descendant_of(self_parent_expansion);
        !(certainly_before_other_or_simultaneously || certainly_before_invoc_or_simultaneously)
    }

    /// Returns whether this declaration may be shadowed or overwritten by something else later.
    /// FIXME: this function considers `unexpanded_invocations`, but not `single_imports`, so
    /// the declaration may not be as "determined" as we think.
    /// FIXME: relationship between this function and similar `NameResolution::determined_decl`
    /// is unclear.
    fn determined(&self) -> bool {
        match &self.kind {
            DeclKind::Import { source_decl, import, .. } if import.is_glob() => {
                !import.parent_scope.module.has_unexpanded_invocations() && source_decl.determined()
            }
            _ => true,
        }
    }
}

#[derive(Debug)]
struct ExternPreludeEntry<'ra> {
    /// Name declaration from an `extern crate` item.
    /// The boolean flag is true is `item_decl` is non-redundant, happens either when
    /// `flag_decl` is `None`, or when `extern crate` introducing `item_decl` used renaming.
    item_decl: Option<(Decl<'ra>, Span, /* introduced by item */ bool)>,
    /// Name declaration from an `--extern` flag, lazily populated on first use.
    flag_decl: Option<
        CacheCell<(
            PendingDecl<'ra>,
            /* finalized */ bool,
            /* open flag (namespaced crate) */ bool,
        )>,
    >,
}

impl ExternPreludeEntry<'_> {
    fn introduced_by_item(&self) -> bool {
        matches!(self.item_decl, Some((.., true)))
    }

    fn flag() -> Self {
        ExternPreludeEntry {
            item_decl: None,
            flag_decl: Some(CacheCell::new((PendingDecl::Pending, false, false))),
        }
    }

    fn open_flag() -> Self {
        ExternPreludeEntry {
            item_decl: None,
            flag_decl: Some(CacheCell::new((PendingDecl::Pending, false, true))),
        }
    }

    fn span(&self) -> Span {
        match self.item_decl {
            Some((_, span, _)) => span,
            None => DUMMY_SP,
        }
    }
}

struct DeriveData {
    resolutions: Vec<DeriveResolution>,
    helper_attrs: Vec<(usize, IdentKey, Span)>,
    // if this list keeps getting extended, we could use `bitflags`,
    // something like what [`rustc_type_ir::flags::TypeFlags`] is doing.
    has_derive_copy: bool,
    has_derive_ord: bool,
}

pub struct ResolverOutputs<'tcx> {
    pub global_ctxt: ResolverGlobalCtxt,
    pub ast_lowering: ResolverAstLowering<'tcx>,
}

#[derive(Debug)]
struct DelegationFnSig {
    pub has_self: bool,
}

/// The main resolver class.
///
/// This is the visitor that walks the whole crate.
pub struct Resolver<'ra, 'tcx> {
    tcx: TyCtxt<'tcx>,

    /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`.
    expn_that_defined: UnordMap<LocalDefId, ExpnId> = Default::default(),

    graph_root: LocalModule<'ra>,

    /// Assert that we are in speculative resolution mode.
    assert_speculative: bool,

    prelude: Option<Module<'ra>> = None,
    extern_prelude: FxIndexMap<IdentKey, ExternPreludeEntry<'ra>>,

    /// N.B., this is used only for better diagnostics, not name resolution itself.
    field_names: LocalDefIdMap<Vec<Ident>> = Default::default(),
    field_defaults: LocalDefIdMap<Vec<Symbol>> = Default::default(),

    /// Span of the privacy modifier in fields of an item `DefId` accessible with dot syntax.
    /// Used for hints during error reporting.
    field_visibility_spans: FxHashMap<DefId, Vec<Span>> = default::fx_hash_map(),

    /// All imports known to succeed or fail.
    determined_imports: Vec<Import<'ra>> = Vec::new(),

    /// All non-determined imports.
    indeterminate_imports: Vec<Import<'ra>> = Vec::new(),

    // Spans for local variables found during pattern resolution.
    // Used for suggestions during error reporting.
    pat_span_map: NodeMap<Span> = Default::default(),

    /// Resolutions for nodes that have a single resolution.
    partial_res_map: NodeMap<PartialRes> = Default::default(),
    /// An import will be inserted into this map if it has been used.
    import_use_map: FxHashMap<Import<'ra>, Used> = default::fx_hash_map(),
    /// Lifetime parameters that lowering will have to introduce.
    extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, MissingLifetimeKind)>> = Default::default(),

    /// `CrateNum` resolutions of `extern crate` items.
    extern_crate_map: UnordMap<LocalDefId, CrateNum> = Default::default(),
    module_children: LocalDefIdMap<Vec<ModChild>> = Default::default(),
    ambig_module_children: LocalDefIdMap<Vec<AmbigModChild>> = Default::default(),

    /// A map from nodes to anonymous modules.
    /// Anonymous modules are pseudo-modules that are implicitly created around items
    /// contained within blocks.
    ///
    /// For example, if we have this:
    ///
    ///  fn f() {
    ///      fn g() {
    ///          ...
    ///      }
    ///  }
    ///
    /// There will be an anonymous module created around `g` with the ID of the
    /// entry block for `f`.
    block_map: NodeMap<LocalModule<'ra>> = Default::default(),
    /// A fake module that contains no definition and no prelude. Used so that
    /// some AST passes can generate identifiers that only resolve to local or
    /// lang items.
    empty_module: LocalModule<'ra>,
    /// All local modules, including blocks.
    local_modules: Vec<LocalModule<'ra>>,
    /// Eagerly populated map of all local non-block modules.
    local_module_map: FxIndexMap<LocalDefId, LocalModule<'ra>>,
    /// Lazily populated cache of modules loaded from external crates.
    extern_module_map: CacheRefCell<FxIndexMap<DefId, ExternModule<'ra>>>,

    /// Maps glob imports to the names of items actually imported.
    glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
    glob_error: Option<ErrorGuaranteed> = None,
    visibilities_for_hashing: Vec<(LocalDefId, Visibility)> = Vec::new(),
    used_imports: FxHashSet<NodeId> = default::fx_hash_set(),
    maybe_unused_trait_imports: FxIndexSet<LocalDefId>,

    /// Privacy errors are delayed until the end in order to deduplicate them.
    privacy_errors: Vec<PrivacyError<'ra>> = Vec::new(),
    /// Ambiguity errors are delayed for deduplication.
    ambiguity_errors: Vec<AmbiguityError<'ra>> = Vec::new(),
    issue_145575_hack_applied: bool = false,
    /// `use` injections are delayed for better placement and deduplication.
    use_injections: Vec<UseError<'tcx>> = Vec::new(),
    /// Visibility path resolution failures are delayed until all modules are collected.
    delayed_vis_resolution_errors: Vec<DelayedVisResolutionError<'ra>> = Vec::new(),
    /// Crate-local macro expanded `macro_export` referred to by a module-relative path.
    macro_expanded_macro_export_errors: BTreeSet<(Span, Span)> = BTreeSet::new(),

    arenas: &'ra ResolverArenas<'ra>,
    dummy_decl: Decl<'ra>,
    builtin_type_decls: FxHashMap<Symbol, Decl<'ra>>,
    builtin_attr_decls: FxHashMap<Symbol, Decl<'ra>>,
    registered_tool_decls: FxHashMap<IdentKey, Decl<'ra>>,
    macro_names: FxHashSet<IdentKey> = default::fx_hash_set(),
    builtin_macros: FxHashMap<Symbol, SyntaxExtensionKind> = default::fx_hash_map(),
    registered_tools: &'tcx RegisteredTools,
    macro_use_prelude: FxIndexMap<Symbol, Decl<'ra>>,
    /// Eagerly populated map of all local macro definitions.
    local_macro_map: FxHashMap<LocalDefId, &'ra Arc<SyntaxExtension>> = default::fx_hash_map(),
    /// Lazily populated cache of macro definitions loaded from external crates.
    extern_macro_map: CacheRefCell<FxHashMap<DefId, &'ra Arc<SyntaxExtension>>>,
    dummy_ext_bang: &'ra Arc<SyntaxExtension>,
    dummy_ext_derive: &'ra Arc<SyntaxExtension>,
    non_macro_attr: &'ra Arc<SyntaxExtension>,
    local_macro_def_scopes: FxHashMap<LocalDefId, LocalModule<'ra>> = default::fx_hash_map(),
    ast_transform_scopes: FxHashMap<LocalExpnId, LocalModule<'ra>> = default::fx_hash_map(),
    unused_macros: FxIndexMap<LocalDefId, (NodeId, Ident)>,
    /// A map from the macro to all its potentially unused arms and the `LocalDefId` of the macro itself.
    unused_macro_rules: FxIndexMap<NodeId, (LocalDefId, DenseBitSet<usize>)>,
    proc_macro_stubs: FxHashSet<LocalDefId> = default::fx_hash_set(),
    /// Traces collected during macro resolution and validated when it's complete.
    single_segment_macro_resolutions:
        CmRefCell<Vec<(Ident, MacroKind, ParentScope<'ra>, Option<Decl<'ra>>, Option<Span>)>>,
    multi_segment_macro_resolutions:
        CmRefCell<Vec<(Vec<Segment>, Span, MacroKind, ParentScope<'ra>, Option<Res>, Namespace)>>,
    builtin_attrs: Vec<(Ident, ParentScope<'ra>)> = Vec::new(),
    /// `derive(Copy)` marks items they are applied to so they are treated specially later.
    /// Derive macros cannot modify the item themselves and have to store the markers in the global
    /// context, so they attach the markers to derive container IDs using this resolver table.
    containers_deriving_copy: FxHashSet<LocalExpnId> = default::fx_hash_set(),
    containers_deriving_ord: FxHashSet<LocalExpnId> = default::fx_hash_set(),
    /// Parent scopes in which the macros were invoked.
    /// FIXME: `derives` are missing in these parent scopes and need to be taken from elsewhere.
    invocation_parent_scopes: FxHashMap<LocalExpnId, ParentScope<'ra>> = default::fx_hash_map(),
    /// `macro_rules` scopes *produced* by expanding the macro invocations,
    /// include all the `macro_rules` items and other invocations generated by them.
    output_macro_rules_scopes: FxHashMap<LocalExpnId, MacroRulesScopeRef<'ra>> = default::fx_hash_map(),
    /// `macro_rules` scopes produced by `macro_rules` item definitions.
    macro_rules_scopes: FxHashMap<LocalDefId, MacroRulesScopeRef<'ra>> = default::fx_hash_map(),
    /// Helper attributes that are in scope for the given expansion.
    helper_attrs: FxHashMap<LocalExpnId, Vec<(IdentKey, Span, Decl<'ra>)>> = default::fx_hash_map(),
    /// Ready or in-progress results of resolving paths inside the `#[derive(...)]` attribute
    /// with the given `ExpnId`.
    derive_data: FxHashMap<LocalExpnId, DeriveData> = default::fx_hash_map(),

    /// Avoid duplicated errors for "name already defined".
    name_already_seen: FxHashMap<Symbol, Span> = default::fx_hash_map(),

    potentially_unused_imports: Vec<Import<'ra>> = Vec::new(),

    potentially_unnecessary_qualifications: Vec<UnnecessaryQualification<'ra>> = Vec::new(),

    /// Table for mapping struct IDs into struct constructor IDs,
    /// it's not used during normal resolution, only for better error reporting.
    /// Also includes of list of each fields visibility
    struct_ctors: LocalDefIdMap<StructCtor> = Default::default(),

    /// for all the struct
    /// it's not used during normal resolution, only for better error reporting.
    struct_generics: LocalDefIdMap<Generics> = Default::default(),

    lint_buffer: LintBuffer,

    next_node_id: NodeId = CRATE_NODE_ID,

    /// Preserves per owner data once the owner is finished resolving.
    owners: NodeMap<PerOwnerResolverData<'tcx>>,

    /// An entry of `owners` that gets taken out and reinserted whenever an owner is handled.
    current_owner: PerOwnerResolverData<'tcx>,

    disambiguators: LocalDefIdMap<PerParentDisambiguatorState>,

    /// Indices of unnamed struct or variant fields with unresolved attributes.
    placeholder_field_indices: FxHashMap<NodeId, usize> = default::fx_hash_map(),
    /// When collecting definitions from an AST fragment produced by a macro invocation `ExpnId`
    /// we know what parent node that fragment should be attached to thanks to this table,
    /// and how the `impl Trait` fragments were introduced.
    invocation_parents: FxHashMap<LocalExpnId, InvocationParent>,

    /// Amount of lifetime parameters for each item in the crate.
    item_generics_num_lifetimes: FxHashMap<LocalDefId, usize> = default::fx_hash_map(),
    /// Generic args to suggest for required params (e.g. `<'_>`, `<_, _>`), if any.
    item_required_generic_args_suggestions: FxHashMap<LocalDefId, String> = default::fx_hash_map(),
    delegation_fn_sigs: LocalDefIdMap<DelegationFnSig> = Default::default(),
    delegation_infos: LocalDefIdMap<DelegationInfo> = Default::default(),

    main_def: Option<MainDefinition> = None,
    trait_impls: FxIndexMap<DefId, Vec<LocalDefId>>,
    /// A list of proc macro LocalDefIds, written out in the order in which
    /// they are declared in the static array generated by proc_macro_harness.
    proc_macros: Vec<LocalDefId> = Vec::new(),
    confused_type_with_std_module: FxIndexMap<Span, Span>,

    /// Names of items that were stripped out via cfg with their corresponding cfg meta item.
    stripped_cfg_items: Vec<StrippedCfgItem<NodeId>> = Vec::new(),

    effective_visibilities: EffectiveVisibilities,
    macro_reachable_adts: FxIndexMap<LocalDefId, FxIndexSet<LocalDefId>>,

    doc_link_resolutions: FxIndexMap<LocalDefId, DocLinkResMap>,
    doc_link_traits_in_scope: FxIndexMap<LocalDefId, Vec<DefId>>,
    all_macro_rules: UnordSet<Symbol> = Default::default(),

    /// Invocation ids of all glob delegations.
    glob_delegation_invoc_ids: FxHashSet<LocalExpnId> = default::fx_hash_set(),
    /// Analogue of module `unexpanded_invocations` but in trait impls, excluding glob delegations.
    /// Needed because glob delegations wait for all other neighboring macros to expand.
    impl_unexpanded_invocations: FxHashMap<LocalDefId, FxHashSet<LocalExpnId>> = default::fx_hash_map(),
    /// Simplified analogue of module `resolutions` but in trait impls, excluding glob delegations.
    /// Needed because glob delegations exclude explicitly defined names.
    impl_binding_keys: FxHashMap<LocalDefId, FxHashSet<BindingKey>> = default::fx_hash_map(),

    /// This is the `Span` where an `extern crate foo;` suggestion would be inserted, if `foo`
    /// could be a crate that wasn't imported. For diagnostics use only.
    current_crate_outer_attr_insert_span: Span,

    mods_with_parse_errors: FxHashSet<DefId> = default::fx_hash_set(),

    /// Whether `Resolver::register_macros_for_all_crates` has been called once already, as we
    /// don't need to run it more than once.
    all_crate_macros_already_registered: bool = false,

    // Stores pre-expansion and pre-placeholder-fragment-insertion names for `impl Trait` types
    // that were encountered during resolution. These names are used to generate item names
    // for APITs, so we don't want to leak details of resolution into these names.
    impl_trait_names: FxHashMap<NodeId, Symbol> = default::fx_hash_map(),
}

/// This provides memory for the rest of the crate. The `'ra` lifetime that is
/// used by many types in this crate is an abbreviation of `ResolverArenas`.
#[derive(Default)]
pub struct ResolverArenas<'ra> {
    modules: TypedArena<ModuleData<'ra>>,
    imports: TypedArena<ImportData<'ra>>,
    name_resolutions: TypedArena<CmRefCell<NameResolution<'ra>>>,
    ast_paths: TypedArena<ast::Path>,
    macros: TypedArena<Arc<SyntaxExtension>>,
    dropless: DroplessArena,
}

impl<'ra> ResolverArenas<'ra> {
    fn new_def_decl(
        &'ra self,
        res: Res,
        vis: Visibility<DefId>,
        span: Span,
        expansion: LocalExpnId,
        parent_module: Option<Module<'ra>>,
    ) -> Decl<'ra> {
        self.alloc_decl(DeclData {
            kind: DeclKind::Def(res),
            ambiguity: CmCell::new(None),
            initial_vis: vis,
            ambiguity_vis_max: CmCell::new(None),
            ambiguity_vis_min: CmCell::new(None),
            span,
            expansion,
            parent_module,
        })
    }

    fn new_pub_def_decl(&'ra self, res: Res, span: Span, expn_id: LocalExpnId) -> Decl<'ra> {
        self.new_def_decl(res, Visibility::Public, span, expn_id, None)
    }

    fn alloc_decl(&'ra self, data: DeclData<'ra>) -> Decl<'ra> {
        Interned::new_unchecked(self.dropless.alloc(data))
    }
    fn alloc_import(&'ra self, import: ImportData<'ra>) -> Import<'ra> {
        Interned::new_unchecked(self.imports.alloc(import))
    }
    fn alloc_name_resolution(
        &'ra self,
        orig_ident_span: Span,
    ) -> &'ra CmRefCell<NameResolution<'ra>> {
        self.name_resolutions.alloc(CmRefCell::new(NameResolution::new(orig_ident_span)))
    }
    fn alloc_macro_rules_scope(&'ra self, scope: MacroRulesScope<'ra>) -> MacroRulesScopeRef<'ra> {
        self.dropless.alloc(CacheCell::new(scope))
    }
    fn alloc_macro_rules_decl(&'ra self, decl: MacroRulesDecl<'ra>) -> &'ra MacroRulesDecl<'ra> {
        self.dropless.alloc(decl)
    }
    fn alloc_ast_paths(&'ra self, paths: &[ast::Path]) -> &'ra [ast::Path] {
        self.ast_paths.alloc_from_iter(paths.iter().cloned())
    }
    fn alloc_macro(&'ra self, ext: SyntaxExtension) -> &'ra Arc<SyntaxExtension> {
        self.macros.alloc(Arc::new(ext))
    }
    fn alloc_pattern_spans(&'ra self, spans: impl Iterator<Item = Span>) -> &'ra [Span] {
        self.dropless.alloc_from_iter(spans)
    }
}

impl<'ra, 'tcx> AsMut<Resolver<'ra, 'tcx>> for Resolver<'ra, 'tcx> {
    fn as_mut(&mut self) -> &mut Resolver<'ra, 'tcx> {
        self
    }
}

impl<'ra, 'tcx> AsRef<Resolver<'ra, 'tcx>> for Resolver<'ra, 'tcx> {
    fn as_ref(&self) -> &Resolver<'ra, 'tcx> {
        self
    }
}

impl<'tcx> Resolver<'_, 'tcx> {
    /// Only call this in analyses after the resolver has finished.
    /// Panics if the node id is currently not in the owner storage,
    /// e.g. because it's further up in the current visitor stack.
    fn owner_def_id(&self, owner: NodeId) -> LocalDefId {
        self.owners[&owner].def_id
    }

    /// Only call this in analyses after the resolver has finished.
    /// Panics if the node id is currently not in the owner storage,
    /// e.g. because it's further up in the current visitor stack.
    fn child_def_id(&self, owner: NodeId, id: NodeId) -> LocalDefId {
        self.owners[&owner].node_id_to_def_id[&id]
    }

    /// Get the `DefId` of a child of the current owner
    fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
        self.current_owner.node_id_to_def_id.get(&node).copied()
    }

    /// Get the `DefId` of a child of the current owner
    fn local_def_id(&self, node: NodeId) -> LocalDefId {
        self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
    }

    /// Adds a definition with a parent definition.
    fn create_def(
        &mut self,
        parent: LocalDefId,
        node_id: ast::NodeId,
        name: Option<Symbol>,
        def_kind: DefKind,
        expn_id: ExpnId,
        span: Span,
        is_owner: bool,
    ) -> TyCtxtFeed<'tcx, LocalDefId> {
        assert!(
            !self.current_owner.node_id_to_def_id.contains_key(&node_id),
            "adding a def for node-id {:?}, name {:?}, data {:?} but a previous def exists: {:?}",
            node_id,
            name,
            def_kind,
            self.tcx
                .definitions_untracked()
                .def_key(self.current_owner.node_id_to_def_id[&node_id]),
        );

        let disambiguator = self.disambiguators.get_or_create(parent);

        // FIXME: remove `def_span` body, pass in the right spans here and call `tcx.at().create_def()`
        let feed = self.tcx.create_def(parent, name, def_kind, None, disambiguator);
        let def_id = feed.def_id();

        // Create the definition.
        if expn_id != ExpnId::root() {
            self.expn_that_defined.insert(def_id, expn_id);
        }

        // A relative span's parent must be an absolute span.
        debug_assert_eq!(span.data_untracked().parent, None);
        let _id = self.tcx.untracked().source_span.push(span);
        debug_assert_eq!(_id, def_id);

        // Some things for which we allocate `LocalDefId`s don't correspond to
        // anything in the AST, so they don't have a `NodeId`. For these cases
        // we don't need a mapping from `NodeId` to `LocalDefId`.
        if node_id != ast::DUMMY_NODE_ID && !is_owner {
            debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
            self.current_owner.node_id_to_def_id.insert(node_id, def_id);
        }

        feed
    }

    fn item_generics_num_lifetimes(&self, def_id: DefId) -> usize {
        if let Some(def_id) = def_id.as_local() {
            self.item_generics_num_lifetimes[&def_id]
        } else {
            self.tcx.generics_of(def_id).own_counts().lifetimes
        }
    }

    fn item_required_generic_args_suggestion(&self, def_id: DefId) -> String {
        if let Some(def_id) = def_id.as_local() {
            self.item_required_generic_args_suggestions.get(&def_id).cloned().unwrap_or_default()
        } else {
            let required = self
                .tcx
                .generics_of(def_id)
                .own_params
                .iter()
                .filter_map(|param| match param.kind {
                    ty::GenericParamDefKind::Lifetime => Some("'_"),
                    ty::GenericParamDefKind::Type { has_default, .. }
                    | ty::GenericParamDefKind::Const { has_default } => {
                        if has_default {
                            None
                        } else {
                            Some("_")
                        }
                    }
                })
                .collect::<Vec<_>>();

            if required.is_empty() { String::new() } else { format!("<{}>", required.join(", ")) }
        }
    }

    pub fn tcx(&self) -> TyCtxt<'tcx> {
        self.tcx
    }

    /// This function is very slow, as it iterates over the entire
    /// [PerOwnerResolverData::node_id_to_def_id] map for all [Resolver::owners]
    /// just to find the [NodeId]
    /// that corresponds to the given [LocalDefId]. Only use this in
    /// diagnostics code paths. Do not use this during macro expansion,
    /// as it will not find any node ids within your current expansion's stack.
    fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId {
        self.owners
            .items()
            .flat_map(|(_, data)| {
                data.node_id_to_def_id
                    .items()
                    .chain(UnordItems::new([(&data.id, &data.def_id)].into_iter()))
            })
            .filter(|(_, v)| **v == def_id)
            .map(|(k, _)| *k)
            .get_only()
            .unwrap()
    }
}

impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
    pub fn new(
        tcx: TyCtxt<'tcx>,
        attrs: &[ast::Attribute],
        crate_span: Span,
        current_crate_outer_attr_insert_span: Span,
        arenas: &'ra ResolverArenas<'ra>,
    ) -> Resolver<'ra, 'tcx> {
        let root_def_id = CRATE_DEF_ID.to_def_id();
        let graph_root = LocalModule::new(
            None,
            ModuleKind::Def(DefKind::Mod, root_def_id, CRATE_NODE_ID, None),
            Visibility::Public,
            ExpnId::root(),
            crate_span,
            attr::contains_name(attrs, sym::no_implicit_prelude),
            arenas,
        );
        let local_modules = vec![graph_root];
        let local_module_map = FxIndexMap::from_iter([(CRATE_DEF_ID, graph_root)]);
        let empty_module = LocalModule::new(
            None,
            ModuleKind::Def(DefKind::Mod, root_def_id, CRATE_NODE_ID, None),
            Visibility::Public,
            ExpnId::root(),
            DUMMY_SP,
            true,
            arenas,
        );

        let owner_data = PerOwnerResolverData::new(CRATE_NODE_ID, CRATE_DEF_ID);
        let crate_feed = tcx.create_local_crate_def_id(crate_span);

        crate_feed.def_kind(DefKind::Mod);
        let mut owners = NodeMap::default();
        owners.insert(CRATE_NODE_ID, owner_data);

        let mut invocation_parents = FxHashMap::default();
        invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT);

        let extern_prelude = build_extern_prelude(tcx, attrs);
        let registered_tools = tcx.registered_tools(());
        let edition = tcx.sess.edition();

        let mut resolver = Resolver {
            tcx,

            // The outermost module has def ID 0; this is not reflected in the
            // AST.
            graph_root,
            assert_speculative: false, // Only set/cleared in Resolver::resolve_imports for now
            extern_prelude,

            empty_module,
            local_modules,
            local_module_map,
            extern_module_map: Default::default(),

            glob_map: Default::default(),
            maybe_unused_trait_imports: Default::default(),

            arenas,
            dummy_decl: arenas.new_pub_def_decl(Res::Err, DUMMY_SP, LocalExpnId::ROOT),
            builtin_type_decls: PrimTy::ALL
                .iter()
                .map(|prim_ty| {
                    let res = Res::PrimTy(*prim_ty);
                    let decl = arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT);
                    (prim_ty.name(), decl)
                })
                .collect(),
            builtin_attr_decls: BUILTIN_ATTRIBUTES
                .iter()
                .map(|builtin_attr| {
                    let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(*builtin_attr));
                    let decl = arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT);
                    (*builtin_attr, decl)
                })
                .collect(),
            registered_tool_decls: registered_tools
                .iter()
                .map(|&ident| {
                    let res = Res::ToolMod;
                    let decl = arenas.new_pub_def_decl(res, ident.span, LocalExpnId::ROOT);
                    (IdentKey::new(ident), decl)
                })
                .collect(),
            registered_tools,
            macro_use_prelude: Default::default(),
            extern_macro_map: Default::default(),
            dummy_ext_bang: arenas.alloc_macro(SyntaxExtension::dummy_bang(edition)),
            dummy_ext_derive: arenas.alloc_macro(SyntaxExtension::dummy_derive(edition)),
            non_macro_attr: arenas.alloc_macro(SyntaxExtension::non_macro_attr(edition)),
            unused_macros: Default::default(),
            unused_macro_rules: Default::default(),
            single_segment_macro_resolutions: Default::default(),
            multi_segment_macro_resolutions: Default::default(),
            lint_buffer: LintBuffer::default(),
            owners,
            current_owner: PerOwnerResolverData::new(DUMMY_NODE_ID, CRATE_DEF_ID),
            invocation_parents,
            trait_impls: Default::default(),
            confused_type_with_std_module: Default::default(),
            stripped_cfg_items: Default::default(),
            effective_visibilities: Default::default(),
            macro_reachable_adts: Default::default(),
            doc_link_resolutions: Default::default(),
            doc_link_traits_in_scope: Default::default(),
            current_crate_outer_attr_insert_span,
            disambiguators: Default::default(),
            ..
        };

        let root_parent_scope = ParentScope::module(graph_root, resolver.arenas);
        resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope);
        resolver.feed_visibility(crate_feed, Visibility::Public);

        resolver
    }

    fn new_local_module(
        &mut self,
        parent: Option<LocalModule<'ra>>,
        kind: ModuleKind,
        expn_id: ExpnId,
        span: Span,
        no_implicit_prelude: bool,
    ) -> LocalModule<'ra> {
        let vis =
            kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id));
        let module =
            LocalModule::new(parent, kind, vis, expn_id, span, no_implicit_prelude, self.arenas);
        self.local_modules.push(module);
        if let Some(def_id) = module.opt_def_id() {
            self.local_module_map.insert(def_id.expect_local(), module);
        }
        module
    }

    fn new_extern_module(
        &self,
        parent: Option<ExternModule<'ra>>,
        kind: ModuleKind,
        expn_id: ExpnId,
        span: Span,
        no_implicit_prelude: bool,
    ) -> ExternModule<'ra> {
        let def_id = kind.def_id();
        let module = ExternModule::new(
            parent,
            kind,
            self.tcx.visibility(def_id),
            expn_id,
            span,
            no_implicit_prelude,
            self.arenas,
        );
        self.extern_module_map.borrow_mut().insert(def_id, module);
        module
    }

    fn next_node_id(&mut self) -> NodeId {
        let start = self.next_node_id;
        let next = start.as_u32().checked_add(1).expect("input too large; ran out of NodeIds");
        self.next_node_id = ast::NodeId::from_u32(next);
        start
    }

    fn next_node_ids(&mut self, count: usize) -> std::ops::Range<NodeId> {
        let start = self.next_node_id;
        let end = start.as_usize().checked_add(count).expect("input too large; ran out of NodeIds");
        self.next_node_id = ast::NodeId::from_usize(end);
        start..self.next_node_id
    }

    pub fn lint_buffer(&mut self) -> &mut LintBuffer {
        &mut self.lint_buffer
    }

    pub fn arenas() -> ResolverArenas<'ra> {
        Default::default()
    }

    fn feed_visibility(&mut self, feed: TyCtxtFeed<'tcx, LocalDefId>, vis: Visibility) {
        feed.visibility(vis.to_def_id());
        self.visibilities_for_hashing.push((feed.def_id(), vis));
    }

    pub fn into_outputs(self) -> ResolverOutputs<'tcx> {
        let proc_macros = self.proc_macros;
        let expn_that_defined = self.expn_that_defined;
        let extern_crate_map = self.extern_crate_map;
        let maybe_unused_trait_imports = self.maybe_unused_trait_imports;
        let glob_map = self.glob_map;
        let main_def = self.main_def;
        let confused_type_with_std_module = self.confused_type_with_std_module;
        let effective_visibilities = self.effective_visibilities;

        let stripped_cfg_items = self
            .stripped_cfg_items
            .into_iter()
            .filter_map(|item| {
                let parent_scope = self.owners.get(&item.parent_scope)?.def_id.to_def_id();
                Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg })
            })
            .collect();
        let disambiguators = self
            .disambiguators
            .into_items()
            .map(|(def_id, disamb)| (def_id, Steal::new(disamb)))
            .collect();

        let global_ctxt = ResolverGlobalCtxt {
            expn_that_defined,
            visibilities_for_hashing: self.visibilities_for_hashing,
            effective_visibilities,
            macro_reachable_adts: self.macro_reachable_adts,
            extern_crate_map,
            module_children: self.module_children,
            ambig_module_children: self.ambig_module_children,
            glob_map,
            maybe_unused_trait_imports,
            main_def,
            trait_impls: self.trait_impls,
            proc_macros,
            confused_type_with_std_module,
            doc_link_resolutions: self.doc_link_resolutions,
            doc_link_traits_in_scope: self.doc_link_traits_in_scope,
            all_macro_rules: self.all_macro_rules,
            stripped_cfg_items,
        };
        let ast_lowering = ty::ResolverAstLowering {
            partial_res_map: self.partial_res_map,
            extra_lifetime_params_map: self.extra_lifetime_params_map,
            next_node_id: self.next_node_id,
            owners: self.owners,
            lint_buffer: Steal::new(self.lint_buffer),
            delegation_infos: self.delegation_infos,
            disambiguators,
        };
        ResolverOutputs { global_ctxt, ast_lowering }
    }

    fn cstore(&self) -> FreezeReadGuard<'_, CStore> {
        CStore::from_tcx(self.tcx)
    }

    fn cstore_mut(&self) -> FreezeWriteGuard<'_, CStore> {
        CStore::from_tcx_mut(self.tcx)
    }

    fn dummy_ext(&self, macro_kind: MacroKind) -> &'ra Arc<SyntaxExtension> {
        match macro_kind {
            MacroKind::Bang => self.dummy_ext_bang,
            MacroKind::Derive => self.dummy_ext_derive,
            MacroKind::Attr => self.non_macro_attr,
        }
    }

    /// Returns a conditionally mutable resolver.
    ///
    /// Currently only dependent on `assert_speculative`, if `assert_speculative` is false,
    /// the resolver will allow mutation; otherwise, it will be immutable.
    fn cm(&mut self) -> CmResolver<'_, 'ra, 'tcx> {
        CmResolver::new(self, !self.assert_speculative)
    }

    /// Runs the function on each namespace.
    fn per_ns<F: FnMut(&mut Self, Namespace)>(&mut self, mut f: F) {
        f(self, TypeNS);
        f(self, ValueNS);
        f(self, MacroNS);
    }

    fn per_ns_cm<'r, F: FnMut(CmResolver<'_, 'ra, 'tcx>, Namespace)>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        mut f: F,
    ) {
        f(self.reborrow(), TypeNS);
        f(self.reborrow(), ValueNS);
        f(self, MacroNS);
    }

    fn is_builtin_macro(&self, res: Res) -> bool {
        self.get_macro(res).is_some_and(|ext| ext.builtin_name.is_some())
    }

    fn is_specific_builtin_macro(&self, res: Res, symbol: Symbol) -> bool {
        self.get_macro(res).is_some_and(|ext| ext.builtin_name == Some(symbol))
    }

    fn macro_def(&self, mut ctxt: SyntaxContext) -> DefId {
        loop {
            match ctxt.outer_expn_data().macro_def_id {
                Some(def_id) => return def_id,
                None => ctxt.remove_mark(),
            };
        }
    }

    /// Entry point to crate resolution.
    pub fn resolve_crate(&mut self, krate: &Crate) {
        self.tcx.sess.time("resolve_crate", || {
            self.tcx.sess.time("finalize_imports", || self.finalize_imports());
            let exported_ambiguities = self.tcx.sess.time("compute_effective_visibilities", || {
                EffectiveVisibilitiesVisitor::compute_effective_visibilities(self, krate)
            });
            self.tcx.sess.time("lint_reexports", || self.lint_reexports(exported_ambiguities));
            self.tcx
                .sess
                .time("finalize_macro_resolutions", || self.finalize_macro_resolutions(krate));
            self.tcx.sess.time("late_resolve_crate", || self.late_resolve_crate(krate));
            self.tcx.sess.time("resolve_main", || self.resolve_main());
            self.tcx.sess.time("resolve_check_unused", || self.check_unused(krate));
            self.tcx.sess.time("resolve_report_errors", || self.report_errors(krate));
            self.tcx
                .sess
                .time("resolve_postprocess", || self.cstore_mut().postprocess(self.tcx, krate));
        });

        // Make sure we don't mutate the cstore from here on.
        self.tcx.untracked().cstore.freeze();
    }

    fn traits_in_scope(
        &mut self,
        current_trait: Option<Module<'ra>>,
        parent_scope: &ParentScope<'ra>,
        sp: Span,
        assoc_item: Option<(Symbol, Namespace)>,
    ) -> &'tcx [TraitCandidate<'tcx>] {
        let mut found_traits = Vec::new();

        if let Some(module) = current_trait {
            if self.trait_may_have_item(Some(module), assoc_item) {
                let def_id = module.def_id();
                found_traits.push(TraitCandidate {
                    def_id,
                    import_ids: &[],
                    lint_ambiguous: false,
                });
            }
        }

        let scope_set = ScopeSet::All(TypeNS);
        let ctxt = Macros20NormalizedSyntaxContext::new(sp.ctxt());
        self.cm().visit_scopes(scope_set, parent_scope, ctxt, sp, None, |mut this, scope, _, _| {
            match scope {
                Scope::ModuleNonGlobs(module, _) => {
                    this.get_mut().traits_in_module(module, assoc_item, &mut found_traits);
                }
                Scope::ModuleGlobs(..) => {
                    // Already handled in `ModuleNonGlobs` (but see #144993).
                }
                Scope::StdLibPrelude => {
                    if let Some(module) = this.prelude {
                        this.get_mut().traits_in_module(module, assoc_item, &mut found_traits);
                    }
                }
                Scope::ExternPreludeItems
                | Scope::ExternPreludeFlags
                | Scope::ToolPrelude
                | Scope::BuiltinTypes => {}
                _ => unreachable!(),
            }
            ControlFlow::<()>::Continue(())
        });

        self.tcx.hir_arena.alloc_slice(&found_traits)
    }

    fn traits_in_module(
        &mut self,
        module: Module<'ra>,
        assoc_item: Option<(Symbol, Namespace)>,
        found_traits: &mut Vec<TraitCandidate<'tcx>>,
    ) {
        module.ensure_traits(self);
        let traits = module.traits.borrow();
        for &(trait_name, trait_binding, trait_module, lint_ambiguous) in
            traits.as_ref().unwrap().iter()
        {
            if self.trait_may_have_item(trait_module, assoc_item) {
                let def_id = trait_binding.res().def_id();
                let import_ids = self.find_transitive_imports(&trait_binding.kind, trait_name);
                found_traits.push(TraitCandidate { def_id, import_ids, lint_ambiguous });
            }
        }
    }

    // List of traits in scope is pruned on best effort basis. We reject traits not having an
    // associated item with the given name and namespace (if specified). This is a conservative
    // optimization, proper hygienic type-based resolution of associated items is done in typeck.
    // We don't reject trait aliases (`trait_module == None`) because we don't have access to their
    // associated items.
    fn trait_may_have_item(
        &self,
        trait_module: Option<Module<'ra>>,
        assoc_item: Option<(Symbol, Namespace)>,
    ) -> bool {
        match (trait_module, assoc_item) {
            (Some(trait_module), Some((name, ns))) => self
                .resolutions(trait_module)
                .borrow()
                .iter()
                .any(|(key, _name_resolution)| key.ns == ns && key.ident.name == name),
            _ => true,
        }
    }

    fn find_transitive_imports(
        &mut self,
        mut kind: &DeclKind<'_>,
        trait_name: Symbol,
    ) -> &'tcx [LocalDefId] {
        let mut import_ids: SmallVec<[LocalDefId; 1]> = smallvec![];
        while let DeclKind::Import { import, source_decl, .. } = kind {
            if let Some(def_id) = import.def_id() {
                self.maybe_unused_trait_imports.insert(def_id);
                import_ids.push(def_id);
            }
            self.add_to_glob_map(*import, trait_name);
            kind = &source_decl.kind;
        }

        self.tcx.hir_arena.alloc_slice(&import_ids)
    }

    fn resolutions(&self, module: Module<'ra>) -> &'ra Resolutions<'ra> {
        if module.populate_on_access.get() {
            module.populate_on_access.set(false);
            self.build_reduced_graph_external(module.expect_extern());
        }
        &module.0.0.lazy_resolutions
    }

    fn resolution(
        &self,
        module: Module<'ra>,
        key: BindingKey,
    ) -> Option<Ref<'ra, NameResolution<'ra>>> {
        self.resolutions(module).borrow().get(&key).map(|resolution| resolution.borrow())
    }

    fn resolution_or_default(
        &self,
        module: Module<'ra>,
        key: BindingKey,
        orig_ident_span: Span,
    ) -> &'ra CmRefCell<NameResolution<'ra>> {
        self.resolutions(module)
            .borrow_mut_unchecked()
            .entry(key)
            .or_insert_with(|| self.arenas.alloc_name_resolution(orig_ident_span))
    }

    /// Test if AmbiguityError ambi is any identical to any one inside ambiguity_errors
    fn matches_previous_ambiguity_error(&self, ambi: &AmbiguityError<'_>) -> bool {
        for ambiguity_error in &self.ambiguity_errors {
            // if the span location and ident as well as its span are the same
            if ambiguity_error.kind == ambi.kind
                && ambiguity_error.ident == ambi.ident
                && ambiguity_error.ident.span == ambi.ident.span
                && ambiguity_error.b1.span == ambi.b1.span
                && ambiguity_error.b2.span == ambi.b2.span
            {
                return true;
            }
        }
        false
    }

    fn record_use(&mut self, ident: Ident, used_decl: Decl<'ra>, used: Used) {
        if let Some((b2, warning)) = used_decl.ambiguity.get() {
            let ambiguity_error = AmbiguityError {
                kind: AmbiguityKind::GlobVsGlob,
                ambig_vis: None,
                ident,
                b1: used_decl,
                b2,
                scope1: Scope::ModuleGlobs(used_decl.parent_module.unwrap(), None),
                scope2: Scope::ModuleGlobs(b2.parent_module.unwrap(), None),
                warning: if warning { Some(AmbiguityWarning::GlobImport) } else { None },
            };
            if !self.matches_previous_ambiguity_error(&ambiguity_error) {
                // avoid duplicated span information to be emit out
                self.ambiguity_errors.push(ambiguity_error);
            }
        }
        if let DeclKind::Import { import, source_decl } = used_decl.kind {
            if let ImportKind::MacroUse { warn_private: true } = import.kind {
                // Do not report the lint if the macro name resolves in stdlib prelude
                // even without the problematic `macro_use` import.
                let found_in_stdlib_prelude = self.prelude.is_some_and(|prelude| {
                    let empty_module = self.empty_module;
                    let arenas = self.arenas;
                    self.cm()
                        .maybe_resolve_ident_in_module(
                            ModuleOrUniformRoot::Module(prelude),
                            ident,
                            MacroNS,
                            &ParentScope::module(empty_module, arenas),
                            None,
                        )
                        .is_ok()
                });
                if !found_in_stdlib_prelude {
                    self.lint_buffer().buffer_lint(
                        PRIVATE_MACRO_USE,
                        import.root_id,
                        ident.span,
                        errors::MacroIsPrivate { ident },
                    );
                }
            }
            // Avoid marking `extern crate` items that refer to a name from extern prelude,
            // but not introduce it, as used if they are accessed from lexical scope.
            if used == Used::Scope
                && let Some(entry) = self.extern_prelude.get(&IdentKey::new(ident))
                && let Some((item_decl, _, false)) = entry.item_decl
                && item_decl == used_decl
            {
                return;
            }
            let old_used = self.import_use_map.entry(import).or_insert(used);
            if *old_used < used {
                *old_used = used;
            }
            if let Some(id) = import.id() {
                self.used_imports.insert(id);
            }
            self.add_to_glob_map(import, ident.name);
            self.record_use(ident, source_decl, Used::Other);
        }
    }

    #[inline]
    fn add_to_glob_map(&mut self, import: Import<'_>, name: Symbol) {
        if let ImportKind::Glob { def_id, .. } = import.kind {
            self.glob_map.entry(def_id).or_default().insert(name);
        }
    }

    fn resolve_crate_root(&self, ident: Ident) -> Module<'ra> {
        debug!("resolve_crate_root({:?})", ident);
        let mut ctxt = ident.span.ctxt();
        let mark = if ident.name == kw::DollarCrate {
            // When resolving `$crate` from a `macro_rules!` invoked in a `macro`,
            // we don't want to pretend that the `macro_rules!` definition is in the `macro`
            // as described in `SyntaxContext::apply_mark`, so we ignore prepended opaque marks.
            // FIXME: This is only a guess and it doesn't work correctly for `macro_rules!`
            // definitions actually produced by `macro` and `macro` definitions produced by
            // `macro_rules!`, but at least such configurations are not stable yet.
            ctxt = ctxt.normalize_to_macro_rules();
            debug!(
                "resolve_crate_root: marks={:?}",
                ctxt.marks().into_iter().map(|(i, t)| (i.expn_data(), t)).collect::<Vec<_>>()
            );
            let mut iter = ctxt.marks().into_iter().rev().peekable();
            let mut result = None;
            // Find the last opaque mark from the end if it exists.
            while let Some(&(mark, transparency)) = iter.peek() {
                if transparency == Transparency::Opaque {
                    result = Some(mark);
                    iter.next();
                } else {
                    break;
                }
            }
            debug!(
                "resolve_crate_root: found opaque mark {:?} {:?}",
                result,
                result.map(|r| r.expn_data())
            );
            // Then find the last semi-opaque mark from the end if it exists.
            for (mark, transparency) in iter {
                if transparency == Transparency::SemiOpaque {
                    result = Some(mark);
                } else {
                    break;
                }
            }
            debug!(
                "resolve_crate_root: found semi-opaque mark {:?} {:?}",
                result,
                result.map(|r| r.expn_data())
            );
            result
        } else {
            debug!("resolve_crate_root: not DollarCrate");
            ctxt = ctxt.normalize_to_macros_2_0();
            ctxt.adjust(ExpnId::root())
        };
        let module = match mark {
            Some(def) => self.expn_def_scope(def),
            None => {
                debug!(
                    "resolve_crate_root({:?}): found no mark (ident.span = {:?})",
                    ident, ident.span
                );
                return self.graph_root.to_module();
            }
        };
        let module = self.expect_module(
            module.opt_def_id().map_or(LOCAL_CRATE, |def_id| def_id.krate).as_def_id(),
        );
        debug!(
            "resolve_crate_root({:?}): got module {:?} ({:?}) (ident.span = {:?})",
            ident,
            module,
            module.name(),
            ident.span
        );
        module
    }

    fn resolve_self(&self, ctxt: &mut SyntaxContext, module: Module<'ra>) -> Module<'ra> {
        let mut module = self.expect_module(module.nearest_parent_mod());
        while module.span.ctxt().normalize_to_macros_2_0() != *ctxt {
            let parent = module.parent.unwrap_or_else(|| self.expn_def_scope(ctxt.remove_mark()));
            module = self.expect_module(parent.nearest_parent_mod());
        }
        module
    }

    fn record_partial_res(&mut self, node_id: NodeId, resolution: PartialRes) {
        debug!("(recording res) recording {:?} for {}", resolution, node_id);
        if let Some(prev_res) = self.partial_res_map.insert(node_id, resolution) {
            panic!("path resolved multiple times ({prev_res:?} before, {resolution:?} now)");
        }
    }

    fn record_pat_span(&mut self, node: NodeId, span: Span) {
        debug!("(recording pat) recording {:?} for {:?}", node, span);
        self.pat_span_map.insert(node, span);
    }

    fn is_accessible_from(&self, vis: Visibility<impl Into<DefId>>, module: Module<'ra>) -> bool {
        vis.is_accessible_from(module.nearest_parent_mod(), self.tcx)
    }

    fn disambiguate_macro_rules_vs_modularized(
        &self,
        macro_rules: Decl<'ra>,
        modularized: Decl<'ra>,
    ) -> bool {
        // Some non-controversial subset of ambiguities "modularized macro name" vs "macro_rules"
        // is disambiguated to mitigate regressions from macro modularization.
        // Scoping for `macro_rules` behaves like scoping for `let` at module level, in general.
        //
        // Panic on unwrap should be impossible, the only name_bindings passed in should be from
        // `resolve_ident_in_scope_set` which will always refer to a local binding from an
        // import or macro definition.
        let macro_rules = macro_rules.parent_module.unwrap();
        let modularized = modularized.parent_module.unwrap();
        macro_rules.nearest_parent_mod() == modularized.nearest_parent_mod()
            && modularized.is_ancestor_of(macro_rules)
    }

    fn extern_prelude_get_item<'r>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        ident: IdentKey,
        orig_ident_span: Span,
        finalize: bool,
    ) -> Option<Decl<'ra>> {
        let entry = self.extern_prelude.get(&ident);
        entry.and_then(|entry| entry.item_decl).map(|(decl, ..)| {
            if finalize {
                self.get_mut().record_use(ident.orig(orig_ident_span), decl, Used::Scope);
            }
            decl
        })
    }

    fn extern_prelude_get_flag(
        &self,
        ident: IdentKey,
        orig_ident_span: Span,
        finalize: bool,
    ) -> Option<Decl<'ra>> {
        let entry = self.extern_prelude.get(&ident);
        entry.and_then(|entry| entry.flag_decl.as_ref()).and_then(|flag_decl| {
            let (pending_decl, finalized, is_open) = flag_decl.get();
            let decl = match pending_decl {
                PendingDecl::Ready(decl) => {
                    if finalize && !finalized && !is_open {
                        self.cstore_mut().process_path_extern(
                            self.tcx,
                            ident.name,
                            orig_ident_span,
                        );
                    }
                    decl
                }
                PendingDecl::Pending => {
                    debug_assert!(!finalized);
                    if is_open {
                        let res = Res::OpenMod(ident.name);
                        Some(self.arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT))
                    } else {
                        let crate_id = if finalize {
                            self.cstore_mut().process_path_extern(
                                self.tcx,
                                ident.name,
                                orig_ident_span,
                            )
                        } else {
                            self.cstore_mut().maybe_process_path_extern(self.tcx, ident.name)
                        };
                        crate_id.map(|crate_id| {
                            let def_id = crate_id.as_def_id();
                            let res = Res::Def(DefKind::Mod, def_id);
                            self.arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT)
                        })
                    }
                }
            };
            flag_decl.set((PendingDecl::Ready(decl), finalize || finalized, is_open));
            decl.or_else(|| finalize.then_some(self.dummy_decl))
        })
    }

    /// Rustdoc uses this to resolve doc link paths in a recoverable way. `PathResult<'a>`
    /// isn't something that can be returned because it can't be made to live that long,
    /// and also it's a private type. Fortunately rustdoc doesn't need to know the error,
    /// just that an error occurred.
    fn resolve_rustdoc_path(
        &mut self,
        path_str: &str,
        ns: Namespace,
        parent_scope: ParentScope<'ra>,
    ) -> Option<Res> {
        let segments: Result<Vec<_>, ()> = path_str
            .split("::")
            .enumerate()
            .map(|(i, s)| {
                let sym = if s.is_empty() {
                    if i == 0 {
                        // For a path like `::a::b`, use `kw::PathRoot` as the leading segment.
                        kw::PathRoot
                    } else {
                        return Err(()); // occurs in cases like `String::`
                    }
                } else {
                    Symbol::intern(s)
                };
                Ok(Segment::from_ident(Ident::with_dummy_span(sym)))
            })
            .collect();
        let Ok(segments) = segments else { return None };

        match self.cm().maybe_resolve_path(&segments, Some(ns), &parent_scope, None) {
            PathResult::Module(ModuleOrUniformRoot::Module(module)) => Some(module.res().unwrap()),
            PathResult::NonModule(path_res) => {
                path_res.full_res().filter(|res| !matches!(res, Res::Def(DefKind::Ctor(..), _)))
            }
            PathResult::Module(ModuleOrUniformRoot::ExternPrelude) | PathResult::Failed { .. } => {
                None
            }
            path_result @ (PathResult::Module(..) | PathResult::Indeterminate) => {
                bug!("got invalid path_result: {path_result:?}")
            }
        }
    }

    /// Retrieves definition span of the given `DefId`.
    fn def_span(&self, def_id: DefId) -> Span {
        match def_id.as_local() {
            Some(def_id) => self.tcx.source_span(def_id),
            // Query `def_span` is not used because hashing its result span is expensive.
            None => self.cstore().def_span_untracked(self.tcx(), def_id),
        }
    }

    fn field_idents(&self, def_id: DefId) -> Option<Vec<Ident>> {
        match def_id.as_local() {
            Some(def_id) => self.field_names.get(&def_id).cloned(),
            None if matches!(
                self.tcx.def_kind(def_id),
                DefKind::Struct | DefKind::Union | DefKind::Variant
            ) =>
            {
                Some(
                    self.tcx
                        .associated_item_def_ids(def_id)
                        .iter()
                        .map(|&def_id| {
                            Ident::new(self.tcx.item_name(def_id), self.tcx.def_span(def_id))
                        })
                        .collect(),
                )
            }
            _ => None,
        }
    }

    fn field_defaults(&self, def_id: DefId) -> Option<Vec<Symbol>> {
        match def_id.as_local() {
            Some(def_id) => self.field_defaults.get(&def_id).cloned(),
            None if matches!(
                self.tcx.def_kind(def_id),
                DefKind::Struct | DefKind::Union | DefKind::Variant
            ) =>
            {
                Some(
                    self.tcx
                        .associated_item_def_ids(def_id)
                        .iter()
                        .filter_map(|&def_id| {
                            self.tcx.default_field(def_id).map(|_| self.tcx.item_name(def_id))
                        })
                        .collect(),
                )
            }
            _ => None,
        }
    }

    /// Checks if an expression refers to a function marked with
    /// `#[rustc_legacy_const_generics]` and returns the argument index list
    /// from the attribute.
    fn legacy_const_generic_args(&mut self, expr: &Expr) -> Option<Vec<usize>> {
        let ExprKind::Path(None, path) = &expr.kind else {
            return None;
        };
        // Don't perform legacy const generics rewriting if the path already
        // has generic arguments.
        if path.segments.last().unwrap().args.is_some() {
            return None;
        }

        let def_id = self.partial_res_map.get(&expr.id)?.full_res()?.opt_def_id()?;

        // We only support cross-crate argument rewriting. Uses
        // within the same crate should be updated to use the new
        // const generics style.
        if def_id.is_local() {
            return None;
        }

        find_attr!(
            // we can use parsed attrs here since for other crates they're already available
            self.tcx, def_id,
            RustcLegacyConstGenerics{fn_indexes,..} => fn_indexes
        )
        .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect())
    }

    fn resolve_main(&mut self) {
        let any_exe = self.tcx.crate_types().contains(&CrateType::Executable);
        // Don't try to resolve main unless it's an executable
        if !any_exe {
            return;
        }

        let module = self.graph_root;
        let ident = Ident::with_dummy_span(sym::main);
        let parent_scope = &ParentScope::module(module, self.arenas);

        let Ok(name_binding) = self.cm().maybe_resolve_ident_in_module(
            ModuleOrUniformRoot::Module(module.to_module()),
            ident,
            ValueNS,
            parent_scope,
            None,
        ) else {
            return;
        };

        let res = name_binding.res();
        let is_import = name_binding.is_import();
        let span = name_binding.span;
        if let Res::Def(DefKind::Fn, _) = res {
            self.record_use(ident, name_binding, Used::Other);
        }
        self.main_def = Some(MainDefinition { res, is_import, span });
    }
}

fn with_owner<'ra, 'tcx, R: AsMut<Resolver<'ra, 'tcx>>, T>(
    this: &mut R,
    owner: NodeId,
    work: impl FnOnce(&mut R) -> T,
) -> T {
    let tables = this.as_mut().owners.remove(&owner).unwrap();
    with_owner_tables(this, owner, tables, work)
}

#[instrument(level = "debug", skip(this, work))]
fn with_owner_tables<'ra, 'tcx, R: AsMut<Resolver<'ra, 'tcx>>, T>(
    this: &mut R,
    owner: NodeId,
    tables: PerOwnerResolverData<'tcx>,
    work: impl FnOnce(&mut R) -> T,
) -> T {
    debug_assert!(!this.as_mut().owners.contains_key(&owner));
    let resolver = this.as_mut();
    let old_owner = mem::replace(&mut resolver.current_owner, tables);
    let ret = work(this);
    let resolver = this.as_mut();
    let overwritten =
        resolver.owners.insert(owner, mem::replace(&mut resolver.current_owner, old_owner));
    assert!(overwritten.is_none());
    ret
}

fn build_extern_prelude<'tcx, 'ra>(
    tcx: TyCtxt<'tcx>,
    attrs: &[ast::Attribute],
) -> FxIndexMap<IdentKey, ExternPreludeEntry<'ra>> {
    let mut extern_prelude: FxIndexMap<IdentKey, ExternPreludeEntry<'ra>> = tcx
        .sess
        .opts
        .externs
        .iter()
        .filter_map(|(name, entry)| {
            // Make sure `self`, `super`, `_` etc do not get into extern prelude.
            // FIXME: reject `--extern self` and similar in option parsing instead.
            if entry.add_prelude
                && let sym = Symbol::intern(name)
                && sym.can_be_raw()
            {
                Some((IdentKey::with_root_ctxt(sym), ExternPreludeEntry::flag()))
            } else {
                None
            }
        })
        .collect();

    // Add open base entries for namespaced crates whose base segment
    // is missing from the prelude (e.g. `foo::bar` without `foo`).
    // These are necessary in order to resolve the open modules, whereas
    // the namespaced names are necessary in `extern_prelude` for actually
    // resolving the namespaced crates.
    let missing_open_bases: Vec<IdentKey> = extern_prelude
        .keys()
        .filter_map(|ident| {
            let (base, _) = ident.name.as_str().split_once("::")?;
            let base_sym = Symbol::intern(base);
            base_sym.can_be_raw().then(|| IdentKey::with_root_ctxt(base_sym))
        })
        .filter(|base_ident| !extern_prelude.contains_key(base_ident))
        .collect();

    extern_prelude.extend(
        missing_open_bases.into_iter().map(|ident| (ident, ExternPreludeEntry::open_flag())),
    );

    // Inject `core` / `std` unless suppressed by attributes.
    if !attr::contains_name(attrs, sym::no_core) {
        extern_prelude.insert(IdentKey::with_root_ctxt(sym::core), ExternPreludeEntry::flag());

        if !attr::contains_name(attrs, sym::no_std) {
            extern_prelude.insert(IdentKey::with_root_ctxt(sym::std), ExternPreludeEntry::flag());
        }
    }

    extern_prelude
}

fn names_to_string(names: impl Iterator<Item = Symbol>) -> String {
    let mut result = String::new();
    for (i, name) in names.enumerate().filter(|(_, name)| *name != kw::PathRoot) {
        if i > 0 {
            result.push_str("::");
        }
        if Ident::with_dummy_span(name).is_raw_guess() {
            result.push_str("r#");
        }
        result.push_str(name.as_str());
    }
    result
}

fn path_names_to_string(path: &Path) -> String {
    names_to_string(path.segments.iter().map(|seg| seg.ident.name))
}

/// A somewhat inefficient routine to obtain the name of a module.
fn module_to_string(mut module: Module<'_>) -> Option<String> {
    let mut names = Vec::new();
    while let Some(parent) = module.parent {
        names.push(module.name().unwrap_or(sym::opaque_module_name_placeholder));
        module = parent;
    }
    if names.is_empty() {
        return None;
    }
    Some(names_to_string(names.iter().rev().copied()))
}

#[derive(Copy, Clone, PartialEq, Debug)]
enum Stage {
    /// Resolving an import or a macro.
    /// Used when macro expansion is either not yet finished, or we are finalizing its results.
    /// Used by default as a more restrictive variant that can produce additional errors.
    Early,
    /// Resolving something in late resolution when all imports are resolved
    /// and all macros are expanded.
    Late,
}

/// Parts of import data required for finalizing import resolution.
/// Does not carry a lifetime, so it can be stored in `Finalize`.
#[derive(Copy, Clone, Debug)]
struct ImportSummary {
    vis: Visibility,
    nearest_parent_mod: LocalDefId,
    is_single: bool,
    priv_macro_use: bool,
    span: Span,
}

/// Invariant: if `Finalize` is used, expansion and import resolution must be complete.
#[derive(Copy, Clone, Debug)]
struct Finalize {
    /// Node ID for linting.
    node_id: NodeId,
    /// Span of the whole path or some its characteristic fragment.
    /// E.g. span of `b` in `foo::{a, b, c}`, or full span for regular paths.
    path_span: Span,
    /// Span of the path start, suitable for prepending something to it.
    /// E.g. span of `foo` in `foo::{a, b, c}`, or full span for regular paths.
    root_span: Span,
    /// Whether to report privacy errors or silently return "no resolution" for them,
    /// similarly to speculative resolution.
    report_private: bool = true,
    /// Tracks whether an item is used in scope or used relatively to a module.
    used: Used = Used::Other,
    /// Finalizing early or late resolution.
    stage: Stage = Stage::Early,
    /// Some import data, in case we are resolving an import's final segment.
    import: Option<ImportSummary> = None,
}

impl Finalize {
    fn new(node_id: NodeId, path_span: Span) -> Finalize {
        Finalize::with_root_span(node_id, path_span, path_span)
    }

    fn with_root_span(node_id: NodeId, path_span: Span, root_span: Span) -> Finalize {
        Finalize { node_id, path_span, root_span, .. }
    }
}

pub fn provide(providers: &mut Providers) {
    providers.registered_tools = macros::registered_tools;
}

/// A wrapper around `&mut Resolver` that may be mutable or immutable, depending on a conditions.
///
/// `Cm` stands for "conditionally mutable".
///
/// Prefer constructing it through [`Resolver::cm`] to ensure correctness.
type CmResolver<'r, 'ra, 'tcx> = ref_mut::RefOrMut<'r, Resolver<'ra, 'tcx>>;

// FIXME: These are cells for caches that can be populated even during speculative resolution,
// and should be replaced with mutexes, atomics, or other synchronized data when migrating to
// parallel name resolution.
use std::cell::{Cell as CacheCell, RefCell as CacheRefCell};

// FIXME: `*_unchecked` methods in the module below should be eliminated in the process
// of migration to parallel name resolution.
mod ref_mut {
    use std::cell::{BorrowMutError, Cell, Ref, RefCell, RefMut};
    use std::fmt;
    use std::ops::Deref;

    use crate::Resolver;

    /// A wrapper around a mutable reference that conditionally allows mutable access.
    pub(crate) struct RefOrMut<'a, T> {
        p: &'a mut T,
        mutable: bool,
    }

    impl<'a, T> Deref for RefOrMut<'a, T> {
        type Target = T;

        fn deref(&self) -> &Self::Target {
            self.p
        }
    }

    impl<'a, T> AsRef<T> for RefOrMut<'a, T> {
        fn as_ref(&self) -> &T {
            self.p
        }
    }

    impl<'a, T> RefOrMut<'a, T> {
        pub(crate) fn new(p: &'a mut T, mutable: bool) -> Self {
            RefOrMut { p, mutable }
        }

        /// This is needed because this wraps a `&mut T` and is therefore not `Copy`.
        pub(crate) fn reborrow(&mut self) -> RefOrMut<'_, T> {
            RefOrMut { p: self.p, mutable: self.mutable }
        }

        /// Returns a mutable reference to the inner value if allowed.
        ///
        /// # Panics
        /// Panics if the `mutable` flag is false.
        #[track_caller]
        pub(crate) fn get_mut(&mut self) -> &mut T {
            match self.mutable {
                false => panic!("can't mutably borrow speculative resolver"),
                true => self.p,
            }
        }
    }

    /// A wrapper around a [`Cell`] that only allows mutation based on a condition in the resolver.
    #[derive(Default)]
    pub(crate) struct CmCell<T>(Cell<T>);

    impl<T: Copy + fmt::Debug> fmt::Debug for CmCell<T> {
        fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
            f.debug_tuple("CmCell").field(&self.get()).finish()
        }
    }

    impl<T: Copy> Clone for CmCell<T> {
        fn clone(&self) -> CmCell<T> {
            CmCell::new(self.get())
        }
    }

    impl<T: Copy> CmCell<T> {
        pub(crate) const fn get(&self) -> T {
            self.0.get()
        }

        pub(crate) fn update<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>, f: impl FnOnce(T) -> T)
        where
            T: Copy,
        {
            let old = self.get();
            self.set(f(old), r);
        }
    }

    impl<T> CmCell<T> {
        pub(crate) const fn new(value: T) -> CmCell<T> {
            CmCell(Cell::new(value))
        }

        pub(crate) fn set<'ra, 'tcx>(&self, val: T, r: &Resolver<'ra, 'tcx>) {
            if r.assert_speculative {
                panic!("not allowed to mutate a `CmCell` during speculative resolution")
            }
            self.0.set(val);
        }

        pub(crate) fn into_inner(self) -> T {
            self.0.into_inner()
        }
    }

    /// A wrapper around a [`RefCell`] that only allows mutable borrows based on a condition in the resolver.
    #[derive(Default)]
    pub(crate) struct CmRefCell<T>(RefCell<T>);

    impl<T> CmRefCell<T> {
        pub(crate) const fn new(value: T) -> CmRefCell<T> {
            CmRefCell(RefCell::new(value))
        }

        #[track_caller]
        pub(crate) fn borrow_mut_unchecked(&self) -> RefMut<'_, T> {
            self.0.borrow_mut()
        }

        #[track_caller]
        pub(crate) fn borrow_mut<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> RefMut<'_, T> {
            if r.assert_speculative {
                panic!("not allowed to mutably borrow a `CmRefCell` during speculative resolution");
            }
            self.0.borrow_mut()
        }

        pub(crate) fn try_borrow_mut_unchecked(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
            self.0.try_borrow_mut()
        }

        #[track_caller]
        pub(crate) fn try_borrow_mut<'ra, 'tcx>(
            &self,
            r: &Resolver<'ra, 'tcx>,
        ) -> Result<RefMut<'_, T>, BorrowMutError> {
            if r.assert_speculative {
                panic!("not allowed to mutably borrow a `CmRefCell` during speculative resolution");
            }
            self.0.try_borrow_mut()
        }

        #[track_caller]
        pub(crate) fn borrow(&self) -> Ref<'_, T> {
            self.0.borrow()
        }
    }

    impl<T: Default> CmRefCell<T> {
        pub(crate) fn take<'ra, 'tcx>(&self, r: &Resolver<'ra, 'tcx>) -> T {
            if r.assert_speculative {
                panic!("not allowed to mutate a CmRefCell during speculative resolution");
            }
            self.0.take()
        }
    }
}

mod hygiene {
    use rustc_span::{ExpnId, SyntaxContext};

    /// A newtype around `SyntaxContext` that can only keep contexts produced by
    /// [SyntaxContext::normalize_to_macros_2_0].
    #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug)]
    pub(crate) struct Macros20NormalizedSyntaxContext(SyntaxContext);

    impl Macros20NormalizedSyntaxContext {
        #[inline]
        pub(crate) fn new(ctxt: SyntaxContext) -> Macros20NormalizedSyntaxContext {
            Macros20NormalizedSyntaxContext(ctxt.normalize_to_macros_2_0())
        }

        #[inline]
        pub(crate) fn new_adjusted(
            mut ctxt: SyntaxContext,
            expn_id: ExpnId,
        ) -> (Macros20NormalizedSyntaxContext, Option<ExpnId>) {
            let def = ctxt.normalize_to_macros_2_0_and_adjust(expn_id);
            (Macros20NormalizedSyntaxContext(ctxt), def)
        }

        #[inline]
        pub(crate) fn new_unchecked(ctxt: SyntaxContext) -> Macros20NormalizedSyntaxContext {
            debug_assert_eq!(ctxt, ctxt.normalize_to_macros_2_0());
            Macros20NormalizedSyntaxContext(ctxt)
        }

        /// The passed closure must preserve the context's normalized-ness.
        #[inline]
        pub(crate) fn update_unchecked<R>(&mut self, f: impl FnOnce(&mut SyntaxContext) -> R) -> R {
            let ret = f(&mut self.0);
            debug_assert_eq!(self.0, self.0.normalize_to_macros_2_0());
            ret
        }
    }

    impl std::ops::Deref for Macros20NormalizedSyntaxContext {
        type Target = SyntaxContext;
        fn deref(&self) -> &Self::Target {
            &self.0
        }
    }
}
