//! 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(box_patterns)]
#![feature(const_default)]
#![feature(const_trait_impl)]
#![feature(control_flow_into_value)]
#![feature(default_field_values)]
#![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::fmt;
use std::ops::ControlFlow;
use std::sync::Arc;

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, 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::{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, LifetimeRes, 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::{PrimTy, TraitCandidate, find_attr};
use rustc_index::bit_set::DenseBitSet;
use rustc_metadata::creader::CStore;
use rustc_middle::bug;
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, RegisteredTools, ResolverAstLowering, ResolverGlobalCtxt,
    TyCtxt, TyCtxtFeed, Visibility,
};
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;

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: Module<'ra>, arenas: &'ra ResolverArenas<'ra>) -> ParentScope<'ra> {
        ParentScope {
            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,
}

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

#[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,
        inner_item: Option<(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,
}

enum VisResolutionError<'a> {
    Relative2018(Span, &'a 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. Used to avoid providing
    /// nonsensical suggestions.
    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 name of target
        segment_name: Symbol,
        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_name: ident.name,
            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, Option<Symbol>),
}

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

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

/// 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,
        self_decl: Option<Decl<'ra>>,
    ) -> Self {
        let is_foreign = match kind {
            ModuleKind::Def(_, def_id, _) => !def_id.is_local(),
            ModuleKind::Block => false,
        };
        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,
        }
    }

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

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

    fn res(&self) -> Option<Res> {
        match self.kind {
            ModuleKind::Def(kind, def_id, _) => Some(Res::Def(kind, def_id)),
            _ => 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: &impl AsRef<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 {
        matches!(self.kind, ModuleKind::Def(DefKind::Mod, _, _))
    }

    fn is_trait(self) -> bool {
        matches!(self.kind, ModuleKind::Def(DefKind::Trait, _, _))
    }

    fn nearest_item_scope(self) -> Module<'ra> {
        match self.kind {
            ModuleKind::Def(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(),
        }
    }

    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() => {
                panic!("`Module::expect_local` is called on a non-local 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 => {
                panic!("`Module::expect_extern` is called on a local module: {self:?}")
            }
        }
    }
}

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

impl<'ra> ExternModule<'ra> {
    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.kind {
            ModuleKind::Block => write!(f, "block"),
            ModuleKind::Def(..) => write!(f, "{:?}", self.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>>>,
    /// Produce a warning instead of an error when reporting ambiguities inside this binding.
    /// May apply to indirect ambiguities under imports, so `ambiguity.is_some()` is not required.
    warn_ambiguity: CmCell<bool>,
    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 `DefId` of the module to place the use-statements in.
    def_id: DefId,
    /// 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(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 warn_ambiguity_recursive(&self) -> bool {
        self.warn_ambiguity.get()
            || match self.kind {
                DeclKind::Import { source_decl, .. } => source_decl.warn_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>, r: &Resolver<'_, '_>) -> 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(r));
            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.unexpanded_invocations.borrow().is_empty()
                    && 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)>,
    has_derive_copy: bool,
}

struct MacroData {
    ext: Arc<SyntaxExtension>,
    nrules: usize,
    macro_rules: bool,
}

impl MacroData {
    fn new(ext: Arc<SyntaxExtension>) -> MacroData {
        MacroData { ext, nrules: 0, macro_rules: false }
    }
}

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(),
    /// Resolutions for import nodes, which have multiple resolutions in different namespaces.
    import_res_map: NodeMap<PerNS<Option<Res>>> = 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(),
    /// Resolutions for labels (node IDs of their corresponding blocks or loops).
    label_res_map: NodeMap<NodeId> = Default::default(),
    /// Resolutions for lifetimes.
    lifetimes_res_map: NodeMap<LifetimeRes> = Default::default(),
    /// Lifetime parameters that lowering will have to introduce.
    extra_lifetime_params_map: NodeMap<Vec<(Ident, NodeId, LifetimeRes)>> = 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(),
    trait_map: NodeMap<&'tcx [TraitCandidate<'tcx>]> = 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(),
    /// 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 MacroData> = default::fx_hash_map(),
    /// Lazily populated cache of macro definitions loaded from external crates.
    extern_macro_map: CacheRefCell<FxHashMap<DefId, &'ra MacroData>>,
    dummy_ext_bang: Arc<SyntaxExtension>,
    dummy_ext_derive: Arc<SyntaxExtension>,
    non_macro_attr: &'ra MacroData,
    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.
    unused_macro_rules: FxIndexMap<NodeId, 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(),
    /// 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,

    node_id_to_def_id: NodeMap<LocalDefId>,

    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>,
    /// Whether lifetime elision was successful.
    lifetime_elision_allowed: FxHashSet<NodeId> = default::fx_hash_set(),

    /// 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,
    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<MacroData>,
    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),
            warn_ambiguity: CmCell::new(false),
            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 new_module(
        &'ra self,
        parent: Option<Module<'ra>>,
        kind: ModuleKind,
        vis: Visibility<DefId>,
        expn_id: ExpnId,
        span: Span,
        no_implicit_prelude: bool,
    ) -> Module<'ra> {
        let self_decl = match kind {
            ModuleKind::Def(def_kind, def_id, _) => Some(self.new_def_decl(
                Res::Def(def_kind, def_id),
                vis,
                span,
                LocalExpnId::ROOT,
                None,
            )),
            ModuleKind::Block => None,
        };
        Module(Interned::new_unchecked(self.modules.alloc(ModuleData::new(
            parent,
            kind,
            expn_id,
            span,
            no_implicit_prelude,
            self_decl,
        ))))
    }
    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, macro_data: MacroData) -> &'ra MacroData {
        self.macros.alloc(macro_data)
    }
    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> {
    fn opt_local_def_id(&self, node: NodeId) -> Option<LocalDefId> {
        self.node_id_to_def_id.get(&node).copied()
    }

    fn local_def_id(&self, node: NodeId) -> LocalDefId {
        self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`"))
    }

    fn local_def_kind(&self, node: NodeId) -> DefKind {
        self.tcx.def_kind(self.local_def_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,
    ) -> TyCtxtFeed<'tcx, LocalDefId> {
        assert!(
            !self.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.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 {
            debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id);
            self.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
    /// [Resolver::node_id_to_def_id] map just to find the [NodeId]
    /// that corresponds to the given [LocalDefId]. Only use this in
    /// diagnostics code paths.
    fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId {
        self.node_id_to_def_id
            .items()
            .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 = arenas.new_module(
            None,
            ModuleKind::Def(DefKind::Mod, root_def_id, None),
            Visibility::Public,
            ExpnId::root(),
            crate_span,
            attr::contains_name(attrs, sym::no_implicit_prelude),
        );
        let graph_root = graph_root.expect_local();
        let local_modules = vec![graph_root];
        let local_module_map = FxIndexMap::from_iter([(CRATE_DEF_ID, graph_root)]);
        let empty_module = arenas.new_module(
            None,
            ModuleKind::Def(DefKind::Mod, root_def_id, None),
            Visibility::Public,
            ExpnId::root(),
            DUMMY_SP,
            true,
        );
        let empty_module = empty_module.expect_local();

        let mut node_id_to_def_id = NodeMap::default();
        let crate_feed = tcx.create_local_crate_def_id(crate_span);

        crate_feed.def_kind(DefKind::Mod);
        node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID);

        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.name));
                    let decl = arenas.new_pub_def_decl(res, DUMMY_SP, LocalExpnId::ROOT);
                    (builtin_attr.name, 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: Arc::new(SyntaxExtension::dummy_bang(edition)),
            dummy_ext_derive: Arc::new(SyntaxExtension::dummy_derive(edition)),
            non_macro_attr: arenas
                .alloc_macro(MacroData::new(Arc::new(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(),
            node_id_to_def_id,
            invocation_parents,
            trait_impls: Default::default(),
            confused_type_with_std_module: Default::default(),
            stripped_cfg_items: Default::default(),
            effective_visibilities: 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.to_module(), 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 parent = parent.map(|m| m.to_module());
        let vis =
            kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id));
        let module = self
            .arenas
            .new_module(parent, kind, vis, expn_id, span, no_implicit_prelude)
            .expect_local();
        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 parent = parent.map(|m| m.to_module());
        let vis =
            kind.opt_def_id().map_or(Visibility::Public, |def_id| self.tcx.visibility(def_id));
        let module = self
            .arenas
            .new_module(parent, kind, vis, expn_id, span, no_implicit_prelude)
            .expect_extern();
        self.extern_module_map.borrow_mut().insert(module.def_id(), module);
        module
    }

    fn new_local_macro(&mut self, def_id: LocalDefId, macro_data: MacroData) -> &'ra MacroData {
        let mac = self.arenas.alloc_macro(macro_data);
        self.local_macro_map.insert(def_id, mac);
        mac
    }

    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.node_id_to_def_id.get(&item.parent_scope)?.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,
            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,
            import_res_map: self.import_res_map,
            label_res_map: self.label_res_map,
            lifetimes_res_map: self.lifetimes_res_map,
            extra_lifetime_params_map: self.extra_lifetime_params_map,
            next_node_id: self.next_node_id,
            node_id_to_def_id: self.node_id_to_def_id,
            trait_map: self.trait_map,
            lifetime_elision_allowed: self.lifetime_elision_allowed,
            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) -> Arc<SyntaxExtension> {
        match macro_kind {
            MacroKind::Bang => Arc::clone(&self.dummy_ext_bang),
            MacroKind::Derive => Arc::clone(&self.dummy_ext_derive),
            MacroKind::Attr => Arc::clone(&self.non_macro_attr.ext),
        }
    }

    /// 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(|macro_data| macro_data.ext.builtin_name.is_some())
    }

    fn is_specific_builtin_macro(&self, res: Res, symbol: Symbol) -> bool {
        self.get_macro(res).is_some_and(|macro_data| macro_data.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(node_id) = import.id() {
                let def_id = self.local_def_id(node_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) {
        self.record_use_inner(ident, used_decl, used, used_decl.warn_ambiguity.get());
    }

    fn record_use_inner(
        &mut self,
        ident: Ident,
        used_decl: Decl<'ra>,
        used: Used,
        warn_ambiguity: bool,
    ) {
        if let Some(b2) = 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 warn_ambiguity { 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.to_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_inner(
                ident,
                source_decl,
                Used::Other,
                warn_ambiguity || source_decl.warn_ambiguity.get(),
            );
        }
    }

    #[inline]
    fn add_to_glob_map(&mut self, import: Import<'_>, name: Symbol) {
        if let ImportKind::Glob { id, .. } = import.kind {
            let def_id = self.local_def_id(id);
            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.kind.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.to_module();
        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),
            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 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();
    loop {
        if let ModuleKind::Def(.., name) = module.kind {
            if let Some(parent) = module.parent {
                // `unwrap` is safe: the presence of a parent means it's not the crate root.
                names.push(name.unwrap());
                module = parent
            } else {
                break;
            }
        } else {
            names.push(sym::opaque_module_name_placeholder);
            let Some(parent) = module.parent else {
                return None;
            };
            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,
}

/// 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,
            }
        }

        /// Returns a mutable reference to the inner value without checking if
        /// it's in a mutable state.
        pub(crate) fn get_mut_unchecked(&mut self) -> &mut T {
            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_unchecked(&self, f: impl FnOnce(T) -> T)
        where
            T: Copy,
        {
            let old = self.get();
            self.set_unchecked(f(old));
        }
    }

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

        pub(crate) fn set_unchecked(&self, val: T) {
            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.borrow_mut_unchecked()
        }

        #[track_caller]
        pub(crate) fn try_borrow_mut_unchecked(&self) -> Result<RefMut<'_, T>, BorrowMutError> {
            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
        }
    }
}
