use Determinacy::*;
use Namespace::*;
use rustc_ast::{self as ast, NodeId};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, MacroKinds, Namespace, NonMacroAttrKind, PartialRes, PerNS};
use rustc_middle::{bug, span_bug};
use rustc_session::lint::builtin::PROC_MACRO_DERIVE_RESOLUTION_FALLBACK;
use rustc_session::parse::feature_err;
use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
use rustc_span::{Ident, Span, kw, sym};
use tracing::{debug, instrument};

use crate::errors::{ParamKindInEnumDiscriminant, ParamKindInNonTrivialAnonConst};
use crate::imports::{Import, NameResolution};
use crate::late::{ConstantHasGenerics, NoConstantGenericsReason, PathSource, Rib, RibKind};
use crate::macros::{MacroRulesScope, sub_namespace_match};
use crate::{
    AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, CmResolver, Determinacy,
    Finalize, ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot,
    NameBinding, NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError,
    Resolver, Scope, ScopeSet, Segment, Stage, Used, Weak, errors,
};

#[derive(Copy, Clone)]
pub enum UsePrelude {
    No,
    Yes,
}

impl From<UsePrelude> for bool {
    fn from(up: UsePrelude) -> bool {
        matches!(up, UsePrelude::Yes)
    }
}

#[derive(Debug, PartialEq, Clone, Copy)]
enum Shadowing {
    Restricted,
    Unrestricted,
}

impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
    /// A generic scope visitor.
    /// Visits scopes in order to resolve some identifier in them or perform other actions.
    /// If the callback returns `Some` result, we stop visiting scopes and return it.
    pub(crate) fn visit_scopes<'r, T>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        scope_set: ScopeSet<'ra>,
        parent_scope: &ParentScope<'ra>,
        ctxt: SyntaxContext,
        derive_fallback_lint_id: Option<NodeId>,
        mut visitor: impl FnMut(
            &mut CmResolver<'r, 'ra, 'tcx>,
            Scope<'ra>,
            UsePrelude,
            SyntaxContext,
        ) -> Option<T>,
    ) -> Option<T> {
        // General principles:
        // 1. Not controlled (user-defined) names should have higher priority than controlled names
        //    built into the language or standard library. This way we can add new names into the
        //    language or standard library without breaking user code.
        // 2. "Closed set" below means new names cannot appear after the current resolution attempt.
        // Places to search (in order of decreasing priority):
        // (Type NS)
        // 1. FIXME: Ribs (type parameters), there's no necessary infrastructure yet
        //    (open set, not controlled).
        // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
        //    (open, not controlled).
        // 3. Extern prelude (open, the open part is from macro expansions, not controlled).
        // 4. Tool modules (closed, controlled right now, but not in the future).
        // 5. Standard library prelude (de-facto closed, controlled).
        // 6. Language prelude (closed, controlled).
        // (Value NS)
        // 1. FIXME: Ribs (local variables), there's no necessary infrastructure yet
        //    (open set, not controlled).
        // 2. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
        //    (open, not controlled).
        // 3. Standard library prelude (de-facto closed, controlled).
        // (Macro NS)
        // 1-3. Derive helpers (open, not controlled). All ambiguities with other names
        //    are currently reported as errors. They should be higher in priority than preludes
        //    and probably even names in modules according to the "general principles" above. They
        //    also should be subject to restricted shadowing because are effectively produced by
        //    derives (you need to resolve the derive first to add helpers into scope), but they
        //    should be available before the derive is expanded for compatibility.
        //    It's mess in general, so we are being conservative for now.
        // 1-3. `macro_rules` (open, not controlled), loop through `macro_rules` scopes. Have higher
        //    priority than prelude macros, but create ambiguities with macros in modules.
        // 1-3. Names in modules (both normal `mod`ules and blocks), loop through hygienic parents
        //    (open, not controlled). Have higher priority than prelude macros, but create
        //    ambiguities with `macro_rules`.
        // 4. `macro_use` prelude (open, the open part is from macro expansions, not controlled).
        // 4a. User-defined prelude from macro-use
        //    (open, the open part is from macro expansions, not controlled).
        // 4b. "Standard library prelude" part implemented through `macro-use` (closed, controlled).
        // 4c. Standard library prelude (de-facto closed, controlled).
        // 6. Language prelude: builtin attributes (closed, controlled).

        let rust_2015 = ctxt.edition().is_rust_2015();
        let (ns, macro_kind) = match scope_set {
            ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
            ScopeSet::ExternPrelude => (TypeNS, None),
            ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
        };
        let module = match scope_set {
            // Start with the specified module.
            ScopeSet::ModuleAndExternPrelude(_, module) => module,
            // Jump out of trait or enum modules, they do not act as scopes.
            _ => parent_scope.module.nearest_item_scope(),
        };
        let module_and_extern_prelude = matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..));
        let extern_prelude = matches!(scope_set, ScopeSet::ExternPrelude);
        let mut scope = match ns {
            _ if module_and_extern_prelude => Scope::Module(module, None),
            _ if extern_prelude => Scope::ExternPreludeItems,
            TypeNS | ValueNS => Scope::Module(module, None),
            MacroNS => Scope::DeriveHelpers(parent_scope.expansion),
        };
        let mut ctxt = ctxt.normalize_to_macros_2_0();
        let mut use_prelude = !module.no_implicit_prelude;

        loop {
            let visit = match scope {
                // Derive helpers are not in scope when resolving derives in the same container.
                Scope::DeriveHelpers(expn_id) => {
                    !(expn_id == parent_scope.expansion && macro_kind == Some(MacroKind::Derive))
                }
                Scope::DeriveHelpersCompat => true,
                Scope::MacroRules(macro_rules_scope) => {
                    // Use "path compression" on `macro_rules` scope chains. This is an optimization
                    // used to avoid long scope chains, see the comments on `MacroRulesScopeRef`.
                    // As another consequence of this optimization visitors never observe invocation
                    // scopes for macros that were already expanded.
                    while let MacroRulesScope::Invocation(invoc_id) = macro_rules_scope.get() {
                        if let Some(next_scope) = self.output_macro_rules_scopes.get(&invoc_id) {
                            macro_rules_scope.set(next_scope.get());
                        } else {
                            break;
                        }
                    }
                    true
                }
                Scope::Module(..) => true,
                Scope::MacroUsePrelude => use_prelude || rust_2015,
                Scope::BuiltinAttrs => true,
                Scope::ExternPreludeItems | Scope::ExternPreludeFlags => {
                    use_prelude || module_and_extern_prelude || extern_prelude
                }
                Scope::ToolPrelude => use_prelude,
                Scope::StdLibPrelude => use_prelude || ns == MacroNS,
                Scope::BuiltinTypes => true,
            };

            if visit {
                let use_prelude = if use_prelude { UsePrelude::Yes } else { UsePrelude::No };
                if let break_result @ Some(..) = visitor(&mut self, scope, use_prelude, ctxt) {
                    return break_result;
                }
            }

            scope = match scope {
                Scope::DeriveHelpers(LocalExpnId::ROOT) => Scope::DeriveHelpersCompat,
                Scope::DeriveHelpers(expn_id) => {
                    // Derive helpers are not visible to code generated by bang or derive macros.
                    let expn_data = expn_id.expn_data();
                    match expn_data.kind {
                        ExpnKind::Root
                        | ExpnKind::Macro(MacroKind::Bang | MacroKind::Derive, _) => {
                            Scope::DeriveHelpersCompat
                        }
                        _ => Scope::DeriveHelpers(expn_data.parent.expect_local()),
                    }
                }
                Scope::DeriveHelpersCompat => Scope::MacroRules(parent_scope.macro_rules),
                Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {
                    MacroRulesScope::Binding(binding) => {
                        Scope::MacroRules(binding.parent_macro_rules_scope)
                    }
                    MacroRulesScope::Invocation(invoc_id) => {
                        Scope::MacroRules(self.invocation_parent_scopes[&invoc_id].macro_rules)
                    }
                    MacroRulesScope::Empty => Scope::Module(module, None),
                },
                Scope::Module(..) if module_and_extern_prelude => match ns {
                    TypeNS => {
                        ctxt.adjust(ExpnId::root());
                        Scope::ExternPreludeItems
                    }
                    ValueNS | MacroNS => break,
                },
                Scope::Module(module, prev_lint_id) => {
                    use_prelude = !module.no_implicit_prelude;
                    match self.hygienic_lexical_parent(module, &mut ctxt, derive_fallback_lint_id) {
                        Some((parent_module, lint_id)) => {
                            Scope::Module(parent_module, lint_id.or(prev_lint_id))
                        }
                        None => {
                            ctxt.adjust(ExpnId::root());
                            match ns {
                                TypeNS => Scope::ExternPreludeItems,
                                ValueNS => Scope::StdLibPrelude,
                                MacroNS => Scope::MacroUsePrelude,
                            }
                        }
                    }
                }
                Scope::MacroUsePrelude => Scope::StdLibPrelude,
                Scope::BuiltinAttrs => break, // nowhere else to search
                Scope::ExternPreludeItems => Scope::ExternPreludeFlags,
                Scope::ExternPreludeFlags if module_and_extern_prelude || extern_prelude => break,
                Scope::ExternPreludeFlags => Scope::ToolPrelude,
                Scope::ToolPrelude => Scope::StdLibPrelude,
                Scope::StdLibPrelude => match ns {
                    TypeNS => Scope::BuiltinTypes,
                    ValueNS => break, // nowhere else to search
                    MacroNS => Scope::BuiltinAttrs,
                },
                Scope::BuiltinTypes => break, // nowhere else to search
            };
        }

        None
    }

    fn hygienic_lexical_parent(
        &self,
        module: Module<'ra>,
        ctxt: &mut SyntaxContext,
        derive_fallback_lint_id: Option<NodeId>,
    ) -> Option<(Module<'ra>, Option<NodeId>)> {
        if !module.expansion.outer_expn_is_descendant_of(*ctxt) {
            return Some((self.expn_def_scope(ctxt.remove_mark()), None));
        }

        if let ModuleKind::Block = module.kind {
            return Some((module.parent.unwrap().nearest_item_scope(), None));
        }

        // We need to support the next case under a deprecation warning
        // ```
        // struct MyStruct;
        // ---- begin: this comes from a proc macro derive
        // mod implementation_details {
        //     // Note that `MyStruct` is not in scope here.
        //     impl SomeTrait for MyStruct { ... }
        // }
        // ---- end
        // ```
        // So we have to fall back to the module's parent during lexical resolution in this case.
        if derive_fallback_lint_id.is_some()
            && let Some(parent) = module.parent
            // Inner module is inside the macro
            && module.expansion != parent.expansion
            // Parent module is outside of the macro
            && module.expansion.is_descendant_of(parent.expansion)
            // The macro is a proc macro derive
            && let Some(def_id) = module.expansion.expn_data().macro_def_id
        {
            let ext = &self.get_macro_by_def_id(def_id).ext;
            if ext.builtin_name.is_none()
                && ext.macro_kinds() == MacroKinds::DERIVE
                && parent.expansion.outer_expn_is_descendant_of(*ctxt)
            {
                return Some((parent, derive_fallback_lint_id));
            }
        }

        None
    }

    /// This resolves the identifier `ident` in the namespace `ns` in the current lexical scope.
    /// More specifically, we proceed up the hierarchy of scopes and return the binding for
    /// `ident` in the first scope that defines it (or None if no scopes define it).
    ///
    /// A block's items are above its local variables in the scope hierarchy, regardless of where
    /// the items are defined in the block. For example,
    /// ```rust
    /// fn f() {
    ///    g(); // Since there are no local variables in scope yet, this resolves to the item.
    ///    let g = || {};
    ///    fn g() {}
    ///    g(); // This resolves to the local variable `g` since it shadows the item.
    /// }
    /// ```
    ///
    /// Invariant: This must only be called during main resolution, not during
    /// import resolution.
    #[instrument(level = "debug", skip(self, ribs))]
    pub(crate) fn resolve_ident_in_lexical_scope(
        &mut self,
        mut ident: Ident,
        ns: Namespace,
        parent_scope: &ParentScope<'ra>,
        finalize: Option<Finalize>,
        ribs: &[Rib<'ra>],
        ignore_binding: Option<NameBinding<'ra>>,
    ) -> Option<LexicalScopeBinding<'ra>> {
        assert!(ns == TypeNS || ns == ValueNS);
        let orig_ident = ident;
        let (general_span, normalized_span) = if ident.name == kw::SelfUpper {
            // FIXME(jseyfried) improve `Self` hygiene
            let empty_span = ident.span.with_ctxt(SyntaxContext::root());
            (empty_span, empty_span)
        } else if ns == TypeNS {
            let normalized_span = ident.span.normalize_to_macros_2_0();
            (normalized_span, normalized_span)
        } else {
            (ident.span.normalize_to_macro_rules(), ident.span.normalize_to_macros_2_0())
        };
        ident.span = general_span;
        let normalized_ident = Ident { span: normalized_span, ..ident };

        // Walk backwards up the ribs in scope.
        for (i, rib) in ribs.iter().enumerate().rev() {
            debug!("walk rib\n{:?}", rib.bindings);
            // Use the rib kind to determine whether we are resolving parameters
            // (macro 2.0 hygiene) or local variables (`macro_rules` hygiene).
            let rib_ident = if rib.kind.contains_params() { normalized_ident } else { ident };
            if let Some((original_rib_ident_def, res)) = rib.bindings.get_key_value(&rib_ident) {
                // The ident resolves to a type parameter or local variable.
                return Some(LexicalScopeBinding::Res(self.validate_res_from_ribs(
                    i,
                    rib_ident,
                    *res,
                    finalize.map(|finalize| finalize.path_span),
                    *original_rib_ident_def,
                    ribs,
                )));
            } else if let RibKind::Block(Some(module)) = rib.kind
                && let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted(
                    ModuleOrUniformRoot::Module(module),
                    ident,
                    ns,
                    parent_scope,
                    Shadowing::Unrestricted,
                    finalize.map(|finalize| Finalize { used: Used::Scope, ..finalize }),
                    ignore_binding,
                    None,
                )
            {
                // The ident resolves to an item in a block.
                return Some(LexicalScopeBinding::Item(binding));
            } else if let RibKind::Module(module) = rib.kind {
                // Encountered a module item, abandon ribs and look into that module and preludes.
                let parent_scope = &ParentScope { module, ..*parent_scope };
                let finalize = finalize.map(|f| Finalize { stage: Stage::Late, ..f });
                return self
                    .cm()
                    .resolve_ident_in_scope_set(
                        orig_ident,
                        ScopeSet::All(ns),
                        parent_scope,
                        finalize,
                        finalize.is_some(),
                        ignore_binding,
                        None,
                    )
                    .ok()
                    .map(LexicalScopeBinding::Item);
            }

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

        unreachable!()
    }

    /// Resolve an identifier in the specified set of scopes.
    #[instrument(level = "debug", skip(self))]
    pub(crate) fn resolve_ident_in_scope_set<'r>(
        self: CmResolver<'r, 'ra, 'tcx>,
        orig_ident: Ident,
        scope_set: ScopeSet<'ra>,
        parent_scope: &ParentScope<'ra>,
        finalize: Option<Finalize>,
        force: bool,
        ignore_binding: Option<NameBinding<'ra>>,
        ignore_import: Option<Import<'ra>>,
    ) -> Result<NameBinding<'ra>, Determinacy> {
        bitflags::bitflags! {
            #[derive(Clone, Copy)]
            struct Flags: u8 {
                const MACRO_RULES          = 1 << 0;
                const MODULE               = 1 << 1;
                const MISC_SUGGEST_CRATE   = 1 << 2;
                const MISC_SUGGEST_SELF    = 1 << 3;
                const MISC_FROM_PRELUDE    = 1 << 4;
            }
        }

        assert!(force || finalize.is_none()); // `finalize` implies `force`

        // Make sure `self`, `super` etc produce an error when passed to here.
        if orig_ident.is_path_segment_keyword() {
            return Err(Determinacy::Determined);
        }

        let (ns, macro_kind) = match scope_set {
            ScopeSet::All(ns) | ScopeSet::ModuleAndExternPrelude(ns, _) => (ns, None),
            ScopeSet::ExternPrelude => (TypeNS, None),
            ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
        };

        // This is *the* result, resolution from the scope closest to the resolved identifier.
        // However, sometimes this result is "weak" because it comes from a glob import or
        // a macro expansion, and in this case it cannot shadow names from outer scopes, e.g.
        // mod m { ... } // solution in outer scope
        // {
        //     use prefix::*; // imports another `m` - innermost solution
        //                    // weak, cannot shadow the outer `m`, need to report ambiguity error
        //     m::mac!();
        // }
        // So we have to save the innermost solution and continue searching in outer scopes
        // to detect potential ambiguities.
        let mut innermost_result: Option<(NameBinding<'_>, Flags)> = None;
        let mut determinacy = Determinacy::Determined;
        let mut extern_prelude_item_binding = None;
        let mut extern_prelude_flag_binding = None;
        // Shadowed bindings don't need to be marked as used or non-speculatively loaded.
        macro finalize_scope() {
            if innermost_result.is_none() { finalize } else { None }
        }

        // Go through all the scopes and try to resolve the name.
        let derive_fallback_lint_id = match finalize {
            Some(Finalize { node_id, stage: Stage::Late, .. }) => Some(node_id),
            _ => None,
        };
        let break_result = self.visit_scopes(
            scope_set,
            parent_scope,
            orig_ident.span.ctxt(),
            derive_fallback_lint_id,
            |this, scope, use_prelude, ctxt| {
                let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
                let result = match scope {
                    Scope::DeriveHelpers(expn_id) => {
                        if let Some(binding) = this.helper_attrs.get(&expn_id).and_then(|attrs| {
                            attrs.iter().rfind(|(i, _)| ident == *i).map(|(_, binding)| *binding)
                        }) {
                            Ok((binding, Flags::empty()))
                        } else {
                            Err(Determinacy::Determined)
                        }
                    }
                    Scope::DeriveHelpersCompat => {
                        let mut result = Err(Determinacy::Determined);
                        for derive in parent_scope.derives {
                            let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
                            match this.reborrow().resolve_macro_path(
                                derive,
                                MacroKind::Derive,
                                parent_scope,
                                true,
                                force,
                                ignore_import,
                                None,
                            ) {
                                Ok((Some(ext), _)) => {
                                    if ext.helper_attrs.contains(&ident.name) {
                                        let binding = this.arenas.new_pub_res_binding(
                                            Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat),
                                            derive.span,
                                            LocalExpnId::ROOT,
                                        );
                                        result = Ok((binding, Flags::empty()));
                                        break;
                                    }
                                }
                                Ok(_) | Err(Determinacy::Determined) => {}
                                Err(Determinacy::Undetermined) => {
                                    result = Err(Determinacy::Undetermined)
                                }
                            }
                        }
                        result
                    }
                    Scope::MacroRules(macro_rules_scope) => match macro_rules_scope.get() {
                        MacroRulesScope::Binding(macro_rules_binding)
                            if ident == macro_rules_binding.ident =>
                        {
                            Ok((macro_rules_binding.binding, Flags::MACRO_RULES))
                        }
                        MacroRulesScope::Invocation(_) => Err(Determinacy::Undetermined),
                        _ => Err(Determinacy::Determined),
                    },
                    Scope::Module(module, derive_fallback_lint_id) => {
                        let (adjusted_parent_scope, adjusted_finalize) =
                            if matches!(scope_set, ScopeSet::ModuleAndExternPrelude(..)) {
                                (parent_scope, finalize_scope!())
                            } else {
                                (
                                    &ParentScope { module, ..*parent_scope },
                                    finalize_scope!().map(|f| Finalize { used: Used::Scope, ..f }),
                                )
                            };
                        let binding = this.reborrow().resolve_ident_in_module_unadjusted(
                            ModuleOrUniformRoot::Module(module),
                            ident,
                            ns,
                            adjusted_parent_scope,
                            Shadowing::Restricted,
                            adjusted_finalize,
                            ignore_binding,
                            ignore_import,
                        );
                        match binding {
                            Ok(binding) => {
                                if let Some(lint_id) = derive_fallback_lint_id {
                                    this.get_mut().lint_buffer.buffer_lint(
                                        PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
                                        lint_id,
                                        orig_ident.span,
                                        errors::ProcMacroDeriveResolutionFallback {
                                            span: orig_ident.span,
                                            ns_descr: ns.descr(),
                                            ident,
                                        },
                                    );
                                }
                                let misc_flags = if module == this.graph_root {
                                    Flags::MISC_SUGGEST_CRATE
                                } else if module.is_normal() {
                                    Flags::MISC_SUGGEST_SELF
                                } else {
                                    Flags::empty()
                                };
                                Ok((binding, Flags::MODULE | misc_flags))
                            }
                            Err((Determinacy::Undetermined, Weak::No)) => {
                                return Some(Err(Determinacy::determined(force)));
                            }
                            Err((Determinacy::Undetermined, Weak::Yes)) => {
                                Err(Determinacy::Undetermined)
                            }
                            Err((Determinacy::Determined, _)) => Err(Determinacy::Determined),
                        }
                    }
                    Scope::MacroUsePrelude => {
                        match this.macro_use_prelude.get(&ident.name).cloned() {
                            Some(binding) => Ok((binding, Flags::MISC_FROM_PRELUDE)),
                            None => Err(Determinacy::determined(
                                this.graph_root.unexpanded_invocations.borrow().is_empty(),
                            )),
                        }
                    }
                    Scope::BuiltinAttrs => match this.builtin_attrs_bindings.get(&ident.name) {
                        Some(binding) => Ok((*binding, Flags::empty())),
                        None => Err(Determinacy::Determined),
                    },
                    Scope::ExternPreludeItems => {
                        match this
                            .reborrow()
                            .extern_prelude_get_item(ident, finalize_scope!().is_some())
                        {
                            Some(binding) => {
                                extern_prelude_item_binding = Some(binding);
                                Ok((binding, Flags::empty()))
                            }
                            None => Err(Determinacy::determined(
                                this.graph_root.unexpanded_invocations.borrow().is_empty(),
                            )),
                        }
                    }
                    Scope::ExternPreludeFlags => {
                        match this.extern_prelude_get_flag(ident, finalize_scope!().is_some()) {
                            Some(binding) => {
                                extern_prelude_flag_binding = Some(binding);
                                Ok((binding, Flags::empty()))
                            }
                            None => Err(Determinacy::Determined),
                        }
                    }
                    Scope::ToolPrelude => match this.registered_tool_bindings.get(&ident) {
                        Some(binding) => Ok((*binding, Flags::empty())),
                        None => Err(Determinacy::Determined),
                    },
                    Scope::StdLibPrelude => {
                        let mut result = Err(Determinacy::Determined);
                        if let Some(prelude) = this.prelude
                            && let Ok(binding) = this.reborrow().resolve_ident_in_module_unadjusted(
                                ModuleOrUniformRoot::Module(prelude),
                                ident,
                                ns,
                                parent_scope,
                                Shadowing::Unrestricted,
                                None,
                                ignore_binding,
                                ignore_import,
                            )
                            && (matches!(use_prelude, UsePrelude::Yes)
                                || this.is_builtin_macro(binding.res()))
                        {
                            result = Ok((binding, Flags::MISC_FROM_PRELUDE));
                        }

                        result
                    }
                    Scope::BuiltinTypes => match this.builtin_types_bindings.get(&ident.name) {
                        Some(binding) => {
                            if matches!(ident.name, sym::f16)
                                && !this.tcx.features().f16()
                                && !ident.span.allows_unstable(sym::f16)
                                && finalize_scope!().is_some()
                            {
                                feature_err(
                                    this.tcx.sess,
                                    sym::f16,
                                    ident.span,
                                    "the type `f16` is unstable",
                                )
                                .emit();
                            }
                            if matches!(ident.name, sym::f128)
                                && !this.tcx.features().f128()
                                && !ident.span.allows_unstable(sym::f128)
                                && finalize_scope!().is_some()
                            {
                                feature_err(
                                    this.tcx.sess,
                                    sym::f128,
                                    ident.span,
                                    "the type `f128` is unstable",
                                )
                                .emit();
                            }
                            Ok((*binding, Flags::empty()))
                        }
                        None => Err(Determinacy::Determined),
                    },
                };

                match result {
                    Ok((binding, flags)) => {
                        if !sub_namespace_match(binding.macro_kinds(), macro_kind) {
                            return None;
                        }

                        // Below we report various ambiguity errors.
                        // We do not need to report them if we are either in speculative resolution,
                        // or in late resolution when everything is already imported and expanded
                        // and no ambiguities exist.
                        if matches!(finalize, None | Some(Finalize { stage: Stage::Late, .. })) {
                            return Some(Ok(binding));
                        }

                        if let Some((innermost_binding, innermost_flags)) = innermost_result {
                            // Found another solution, if the first one was "weak", report an error.
                            let (res, innermost_res) = (binding.res(), innermost_binding.res());
                            if res != innermost_res {
                                let is_builtin = |res| {
                                    matches!(res, Res::NonMacroAttr(NonMacroAttrKind::Builtin(..)))
                                };
                                let derive_helper =
                                    Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
                                let derive_helper_compat =
                                    Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat);

                                let ambiguity_error_kind = if is_builtin(innermost_res)
                                    || is_builtin(res)
                                {
                                    Some(AmbiguityKind::BuiltinAttr)
                                } else if innermost_res == derive_helper_compat
                                    || res == derive_helper_compat && innermost_res != derive_helper
                                {
                                    Some(AmbiguityKind::DeriveHelper)
                                } else if innermost_flags.contains(Flags::MACRO_RULES)
                                    && flags.contains(Flags::MODULE)
                                    && !this.disambiguate_macro_rules_vs_modularized(
                                        innermost_binding,
                                        binding,
                                    )
                                {
                                    Some(AmbiguityKind::MacroRulesVsModularized)
                                } else if flags.contains(Flags::MACRO_RULES)
                                    && innermost_flags.contains(Flags::MODULE)
                                {
                                    // should be impossible because of visitation order in
                                    // visit_scopes
                                    //
                                    // we visit all macro_rules scopes (e.g. textual scope macros)
                                    // before we visit any modules (e.g. path-based scope macros)
                                    span_bug!(
                                        orig_ident.span,
                                        "ambiguous scoped macro resolutions with path-based \
                                        scope resolution as first candidate"
                                    )
                                } else if innermost_binding.is_glob_import() {
                                    Some(AmbiguityKind::GlobVsOuter)
                                } else if innermost_binding
                                    .may_appear_after(parent_scope.expansion, binding)
                                {
                                    Some(AmbiguityKind::MoreExpandedVsOuter)
                                } else {
                                    None
                                };
                                // Skip ambiguity errors for extern flag bindings "overridden"
                                // by extern item bindings.
                                // FIXME: Remove with lang team approval.
                                let issue_145575_hack = Some(binding)
                                    == extern_prelude_flag_binding
                                    && extern_prelude_item_binding.is_some()
                                    && extern_prelude_item_binding != Some(innermost_binding);
                                if let Some(kind) = ambiguity_error_kind
                                    && !issue_145575_hack
                                {
                                    let misc = |f: Flags| {
                                        if f.contains(Flags::MISC_SUGGEST_CRATE) {
                                            AmbiguityErrorMisc::SuggestCrate
                                        } else if f.contains(Flags::MISC_SUGGEST_SELF) {
                                            AmbiguityErrorMisc::SuggestSelf
                                        } else if f.contains(Flags::MISC_FROM_PRELUDE) {
                                            AmbiguityErrorMisc::FromPrelude
                                        } else {
                                            AmbiguityErrorMisc::None
                                        }
                                    };
                                    this.get_mut().ambiguity_errors.push(AmbiguityError {
                                        kind,
                                        ident: orig_ident,
                                        b1: innermost_binding,
                                        b2: binding,
                                        warning: false,
                                        misc1: misc(innermost_flags),
                                        misc2: misc(flags),
                                    });
                                    return Some(Ok(innermost_binding));
                                }
                            }
                        } else {
                            // Found the first solution.
                            innermost_result = Some((binding, flags));
                        }
                    }
                    Err(Determinacy::Determined) => {}
                    Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined,
                }

                None
            },
        );

        if let Some(break_result) = break_result {
            return break_result;
        }

        // The first found solution was the only one, return it.
        if let Some((binding, _)) = innermost_result {
            return Ok(binding);
        }

        Err(Determinacy::determined(determinacy == Determinacy::Determined || force))
    }

    #[instrument(level = "debug", skip(self))]
    pub(crate) fn maybe_resolve_ident_in_module<'r>(
        self: CmResolver<'r, 'ra, 'tcx>,
        module: ModuleOrUniformRoot<'ra>,
        ident: Ident,
        ns: Namespace,
        parent_scope: &ParentScope<'ra>,
        ignore_import: Option<Import<'ra>>,
    ) -> Result<NameBinding<'ra>, Determinacy> {
        self.resolve_ident_in_module(module, ident, ns, parent_scope, None, None, ignore_import)
            .map_err(|(determinacy, _)| determinacy)
    }

    #[instrument(level = "debug", skip(self))]
    pub(crate) fn resolve_ident_in_module<'r>(
        self: CmResolver<'r, 'ra, 'tcx>,
        module: ModuleOrUniformRoot<'ra>,
        mut ident: Ident,
        ns: Namespace,
        parent_scope: &ParentScope<'ra>,
        finalize: Option<Finalize>,
        ignore_binding: Option<NameBinding<'ra>>,
        ignore_import: Option<Import<'ra>>,
    ) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
        let tmp_parent_scope;
        let mut adjusted_parent_scope = parent_scope;
        match module {
            ModuleOrUniformRoot::Module(m) => {
                if let Some(def) = ident.span.normalize_to_macros_2_0_and_adjust(m.expansion) {
                    tmp_parent_scope =
                        ParentScope { module: self.expn_def_scope(def), ..*parent_scope };
                    adjusted_parent_scope = &tmp_parent_scope;
                }
            }
            ModuleOrUniformRoot::ExternPrelude => {
                ident.span.normalize_to_macros_2_0_and_adjust(ExpnId::root());
            }
            ModuleOrUniformRoot::ModuleAndExternPrelude(..) | ModuleOrUniformRoot::CurrentScope => {
                // No adjustments
            }
        }
        self.resolve_ident_in_module_unadjusted(
            module,
            ident,
            ns,
            adjusted_parent_scope,
            Shadowing::Unrestricted,
            finalize,
            ignore_binding,
            ignore_import,
        )
    }
    /// Attempts to resolve `ident` in namespaces `ns` of `module`.
    /// Invariant: if `finalize` is `Some`, expansion and import resolution must be complete.
    #[instrument(level = "debug", skip(self))]
    fn resolve_ident_in_module_unadjusted<'r>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        module: ModuleOrUniformRoot<'ra>,
        ident: Ident,
        ns: Namespace,
        parent_scope: &ParentScope<'ra>,
        shadowing: Shadowing,
        finalize: Option<Finalize>,
        // This binding should be ignored during in-module resolution, so that we don't get
        // "self-confirming" import resolutions during import validation and checking.
        ignore_binding: Option<NameBinding<'ra>>,
        ignore_import: Option<Import<'ra>>,
    ) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
        let module = match module {
            ModuleOrUniformRoot::Module(module) => module,
            ModuleOrUniformRoot::ModuleAndExternPrelude(module) => {
                assert_eq!(shadowing, Shadowing::Unrestricted);
                let binding = self.resolve_ident_in_scope_set(
                    ident,
                    ScopeSet::ModuleAndExternPrelude(ns, module),
                    parent_scope,
                    finalize,
                    finalize.is_some(),
                    ignore_binding,
                    ignore_import,
                );
                return binding.map_err(|determinacy| (determinacy, Weak::No));
            }
            ModuleOrUniformRoot::ExternPrelude => {
                assert_eq!(shadowing, Shadowing::Unrestricted);
                return if ns != TypeNS {
                    Err((Determined, Weak::No))
                } else {
                    let binding = self.resolve_ident_in_scope_set(
                        ident,
                        ScopeSet::ExternPrelude,
                        parent_scope,
                        finalize,
                        finalize.is_some(),
                        ignore_binding,
                        ignore_import,
                    );
                    return binding.map_err(|determinacy| (determinacy, Weak::No));
                };
            }
            ModuleOrUniformRoot::CurrentScope => {
                assert_eq!(shadowing, Shadowing::Unrestricted);
                if ns == TypeNS {
                    if ident.name == kw::Crate || ident.name == kw::DollarCrate {
                        let module = self.resolve_crate_root(ident);
                        return Ok(module.self_binding.unwrap());
                    } else if ident.name == kw::Super || ident.name == kw::SelfLower {
                        // FIXME: Implement these with renaming requirements so that e.g.
                        // `use super;` doesn't work, but `use super as name;` does.
                        // Fall through here to get an error from `early_resolve_...`.
                    }
                }

                let binding = self.resolve_ident_in_scope_set(
                    ident,
                    ScopeSet::All(ns),
                    parent_scope,
                    finalize,
                    finalize.is_some(),
                    ignore_binding,
                    ignore_import,
                );
                return binding.map_err(|determinacy| (determinacy, Weak::No));
            }
        };

        let key = BindingKey::new(ident, ns);
        // `try_borrow_mut` is required to ensure exclusive access, even if the resulting binding
        // doesn't need to be mutable. It will fail when there is a cycle of imports, and without
        // the exclusive access infinite recursion will crash the compiler with stack overflow.
        let resolution = &*self
            .resolution_or_default(module, key)
            .try_borrow_mut()
            .map_err(|_| (Determined, Weak::No))?;

        // If the primary binding is unusable, search further and return the shadowed glob
        // binding if it exists. What we really want here is having two separate scopes in
        // a module - one for non-globs and one for globs, but until that's done use this
        // hack to avoid inconsistent resolution ICEs during import validation.
        let binding = [resolution.non_glob_binding, resolution.glob_binding]
            .into_iter()
            .find_map(|binding| if binding == ignore_binding { None } else { binding });

        if let Some(finalize) = finalize {
            return self.get_mut().finalize_module_binding(
                ident,
                binding,
                if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
                parent_scope,
                module,
                finalize,
                shadowing,
            );
        }

        let check_usable = |this: CmResolver<'r, 'ra, 'tcx>, binding: NameBinding<'ra>| {
            let usable = this.is_accessible_from(binding.vis, parent_scope.module);
            if usable { Ok(binding) } else { Err((Determined, Weak::No)) }
        };

        // Items and single imports are not shadowable, if we have one, then it's determined.
        if let Some(binding) = binding
            && !binding.is_glob_import()
        {
            return check_usable(self, binding);
        }

        // --- From now on we either have a glob resolution or no resolution. ---

        // Check if one of single imports can still define the name,
        // if it can then our result is not determined and can be invalidated.
        if self.reborrow().single_import_can_define_name(
            &resolution,
            binding,
            ns,
            ignore_import,
            ignore_binding,
            parent_scope,
        ) {
            return Err((Undetermined, Weak::No));
        }

        // So we have a resolution that's from a glob import. This resolution is determined
        // if it cannot be shadowed by some new item/import expanded from a macro.
        // This happens either if there are no unexpanded macros, or expanded names cannot
        // shadow globs (that happens in macro namespace or with restricted shadowing).
        //
        // Additionally, any macro in any module can plant names in the root module if it creates
        // `macro_export` macros, so the root module effectively has unresolved invocations if any
        // module has unresolved invocations.
        // However, it causes resolution/expansion to stuck too often (#53144), so, to make
        // progress, we have to ignore those potential unresolved invocations from other modules
        // and prohibit access to macro-expanded `macro_export` macros instead (unless restricted
        // shadowing is enabled, see `macro_expanded_macro_export_errors`).
        if let Some(binding) = binding {
            if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted {
                return check_usable(self, binding);
            } else {
                return Err((Undetermined, Weak::No));
            }
        }

        // --- From now on we have no resolution. ---

        // Now we are in situation when new item/import can appear only from a glob or a macro
        // expansion. With restricted shadowing names from globs and macro expansions cannot
        // shadow names from outer scopes, so we can freely fallback from module search to search
        // in outer scopes. For `resolve_ident_in_scope_set` to continue search in outer
        // scopes we return `Undetermined` with `Weak::Yes`.

        // Check if one of unexpanded macros can still define the name,
        // if it can then our "no resolution" result is not determined and can be invalidated.
        if !module.unexpanded_invocations.borrow().is_empty() {
            return Err((Undetermined, Weak::Yes));
        }

        // Check if one of glob imports can still define the name,
        // if it can then our "no resolution" result is not determined and can be invalidated.
        for glob_import in module.globs.borrow().iter() {
            if ignore_import == Some(*glob_import) {
                continue;
            }
            if !self.is_accessible_from(glob_import.vis, parent_scope.module) {
                continue;
            }
            let module = match glob_import.imported_module.get() {
                Some(ModuleOrUniformRoot::Module(module)) => module,
                Some(_) => continue,
                None => return Err((Undetermined, Weak::Yes)),
            };
            let tmp_parent_scope;
            let (mut adjusted_parent_scope, mut ident) =
                (parent_scope, ident.normalize_to_macros_2_0());
            match ident.span.glob_adjust(module.expansion, glob_import.span) {
                Some(Some(def)) => {
                    tmp_parent_scope =
                        ParentScope { module: self.expn_def_scope(def), ..*parent_scope };
                    adjusted_parent_scope = &tmp_parent_scope;
                }
                Some(None) => {}
                None => continue,
            };
            let result = self.reborrow().resolve_ident_in_module_unadjusted(
                ModuleOrUniformRoot::Module(module),
                ident,
                ns,
                adjusted_parent_scope,
                Shadowing::Unrestricted,
                None,
                ignore_binding,
                ignore_import,
            );

            match result {
                Err((Determined, _)) => continue,
                Ok(binding)
                    if !self.is_accessible_from(binding.vis, glob_import.parent_scope.module) =>
                {
                    continue;
                }
                Ok(_) | Err((Undetermined, _)) => return Err((Undetermined, Weak::Yes)),
            }
        }

        // No resolution and no one else can define the name - determinate error.
        Err((Determined, Weak::No))
    }

    fn finalize_module_binding(
        &mut self,
        ident: Ident,
        binding: Option<NameBinding<'ra>>,
        shadowed_glob: Option<NameBinding<'ra>>,
        parent_scope: &ParentScope<'ra>,
        module: Module<'ra>,
        finalize: Finalize,
        shadowing: Shadowing,
    ) -> Result<NameBinding<'ra>, (Determinacy, Weak)> {
        let Finalize { path_span, report_private, used, root_span, .. } = finalize;

        let Some(binding) = binding else {
            return Err((Determined, Weak::No));
        };

        if !self.is_accessible_from(binding.vis, parent_scope.module) {
            if report_private {
                self.privacy_errors.push(PrivacyError {
                    ident,
                    binding,
                    dedup_span: path_span,
                    outermost_res: None,
                    source: None,
                    parent_scope: *parent_scope,
                    single_nested: path_span != root_span,
                });
            } else {
                return Err((Determined, Weak::No));
            }
        }

        // Forbid expanded shadowing to avoid time travel.
        if let Some(shadowed_glob) = shadowed_glob
            && shadowing == Shadowing::Restricted
            && finalize.stage == Stage::Early
            && binding.expansion != LocalExpnId::ROOT
            && binding.res() != shadowed_glob.res()
        {
            self.ambiguity_errors.push(AmbiguityError {
                kind: AmbiguityKind::GlobVsExpanded,
                ident,
                b1: binding,
                b2: shadowed_glob,
                warning: false,
                misc1: AmbiguityErrorMisc::None,
                misc2: AmbiguityErrorMisc::None,
            });
        }

        if shadowing == Shadowing::Unrestricted
            && binding.expansion != LocalExpnId::ROOT
            && let NameBindingKind::Import { import, .. } = binding.kind
            && matches!(import.kind, ImportKind::MacroExport)
        {
            self.macro_expanded_macro_export_errors.insert((path_span, binding.span));
        }

        // If we encounter a re-export for a type with private fields, it will not be able to
        // be constructed through this re-export. We track that case here to expand later
        // privacy errors with appropriate information.
        if let Res::Def(_, def_id) = binding.res() {
            let struct_ctor = match def_id.as_local() {
                Some(def_id) => self.struct_constructors.get(&def_id).cloned(),
                None => {
                    let ctor = self.cstore().ctor_untracked(def_id);
                    ctor.map(|(ctor_kind, ctor_def_id)| {
                        let ctor_res = Res::Def(
                            DefKind::Ctor(rustc_hir::def::CtorOf::Struct, ctor_kind),
                            ctor_def_id,
                        );
                        let ctor_vis = self.tcx.visibility(ctor_def_id);
                        let field_visibilities = self
                            .tcx
                            .associated_item_def_ids(def_id)
                            .iter()
                            .map(|field_id| self.tcx.visibility(field_id))
                            .collect();
                        (ctor_res, ctor_vis, field_visibilities)
                    })
                }
            };
            if let Some((_, _, fields)) = struct_ctor
                && fields.iter().any(|vis| !self.is_accessible_from(*vis, module))
            {
                self.inaccessible_ctor_reexport.insert(path_span, binding.span);
            }
        }

        self.record_use(ident, binding, used);
        return Ok(binding);
    }

    // Checks if a single import can define the `Ident` corresponding to `binding`.
    // This is used to check whether we can definitively accept a glob as a resolution.
    fn single_import_can_define_name<'r>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        resolution: &NameResolution<'ra>,
        binding: Option<NameBinding<'ra>>,
        ns: Namespace,
        ignore_import: Option<Import<'ra>>,
        ignore_binding: Option<NameBinding<'ra>>,
        parent_scope: &ParentScope<'ra>,
    ) -> bool {
        for single_import in &resolution.single_imports {
            if ignore_import == Some(*single_import) {
                continue;
            }
            if !self.is_accessible_from(single_import.vis, parent_scope.module) {
                continue;
            }
            if let Some(ignored) = ignore_binding
                && let NameBindingKind::Import { import, .. } = ignored.kind
                && import == *single_import
            {
                continue;
            }

            let Some(module) = single_import.imported_module.get() else {
                return true;
            };
            let ImportKind::Single { source, target, bindings, .. } = &single_import.kind else {
                unreachable!();
            };
            if source != target {
                if bindings.iter().all(|binding| binding.get().binding().is_none()) {
                    return true;
                } else if bindings[ns].get().binding().is_none() && binding.is_some() {
                    return true;
                }
            }

            match self.reborrow().resolve_ident_in_module(
                module,
                *source,
                ns,
                &single_import.parent_scope,
                None,
                ignore_binding,
                ignore_import,
            ) {
                Err((Determined, _)) => continue,
                Ok(binding)
                    if !self.is_accessible_from(binding.vis, single_import.parent_scope.module) =>
                {
                    continue;
                }
                Ok(_) | Err((Undetermined, _)) => {
                    return true;
                }
            }
        }

        false
    }

    /// Validate a local resolution (from ribs).
    #[instrument(level = "debug", skip(self, all_ribs))]
    fn validate_res_from_ribs(
        &mut self,
        rib_index: usize,
        rib_ident: Ident,
        mut res: Res,
        finalize: Option<Span>,
        original_rib_ident_def: Ident,
        all_ribs: &[Rib<'ra>],
    ) -> Res {
        debug!("validate_res_from_ribs({:?})", res);
        let ribs = &all_ribs[rib_index + 1..];

        // An invalid forward use of a generic parameter from a previous default
        // or in a const param ty.
        if let RibKind::ForwardGenericParamBan(reason) = all_ribs[rib_index].kind {
            if let Some(span) = finalize {
                let res_error = if rib_ident.name == kw::SelfUpper {
                    ResolutionError::ForwardDeclaredSelf(reason)
                } else {
                    ResolutionError::ForwardDeclaredGenericParam(rib_ident.name, reason)
                };
                self.report_error(span, res_error);
            }
            assert_eq!(res, Res::Err);
            return Res::Err;
        }

        match res {
            Res::Local(_) => {
                use ResolutionError::*;
                let mut res_err = None;

                for rib in ribs {
                    match rib.kind {
                        RibKind::Normal
                        | RibKind::Block(..)
                        | RibKind::FnOrCoroutine
                        | RibKind::Module(..)
                        | RibKind::MacroDefinition(..)
                        | RibKind::ForwardGenericParamBan(_) => {
                            // Nothing to do. Continue.
                        }
                        RibKind::Item(..) | RibKind::AssocItem => {
                            // This was an attempt to access an upvar inside a
                            // named function item. This is not allowed, so we
                            // report an error.
                            if let Some(span) = finalize {
                                // We don't immediately trigger a resolve error, because
                                // we want certain other resolution errors (namely those
                                // emitted for `ConstantItemRibKind` below) to take
                                // precedence.
                                res_err = Some((span, CannotCaptureDynamicEnvironmentInFnItem));
                            }
                        }
                        RibKind::ConstantItem(_, item) => {
                            // Still doesn't deal with upvars
                            if let Some(span) = finalize {
                                let (span, resolution_error) = match item {
                                    None if rib_ident.name == kw::SelfLower => {
                                        (span, LowercaseSelf)
                                    }
                                    None => {
                                        // If we have a `let name = expr;`, we have the span for
                                        // `name` and use that to see if it is followed by a type
                                        // specifier. If not, then we know we need to suggest
                                        // `const name: Ty = expr;`. This is a heuristic, it will
                                        // break down in the presence of macros.
                                        let sm = self.tcx.sess.source_map();
                                        let type_span = match sm.span_look_ahead(
                                            original_rib_ident_def.span,
                                            ":",
                                            None,
                                        ) {
                                            None => {
                                                Some(original_rib_ident_def.span.shrink_to_hi())
                                            }
                                            Some(_) => None,
                                        };
                                        (
                                            rib_ident.span,
                                            AttemptToUseNonConstantValueInConstant {
                                                ident: original_rib_ident_def,
                                                suggestion: "const",
                                                current: "let",
                                                type_span,
                                            },
                                        )
                                    }
                                    Some((ident, kind)) => (
                                        span,
                                        AttemptToUseNonConstantValueInConstant {
                                            ident,
                                            suggestion: "let",
                                            current: kind.as_str(),
                                            type_span: None,
                                        },
                                    ),
                                };
                                self.report_error(span, resolution_error);
                            }
                            return Res::Err;
                        }
                        RibKind::ConstParamTy => {
                            if let Some(span) = finalize {
                                self.report_error(
                                    span,
                                    ParamInTyOfConstParam { name: rib_ident.name },
                                );
                            }
                            return Res::Err;
                        }
                        RibKind::InlineAsmSym => {
                            if let Some(span) = finalize {
                                self.report_error(span, InvalidAsmSym);
                            }
                            return Res::Err;
                        }
                    }
                }
                if let Some((span, res_err)) = res_err {
                    self.report_error(span, res_err);
                    return Res::Err;
                }
            }
            Res::Def(DefKind::TyParam, _) | Res::SelfTyParam { .. } | Res::SelfTyAlias { .. } => {
                for rib in ribs {
                    let (has_generic_params, def_kind) = match rib.kind {
                        RibKind::Normal
                        | RibKind::Block(..)
                        | RibKind::FnOrCoroutine
                        | RibKind::Module(..)
                        | RibKind::MacroDefinition(..)
                        | RibKind::InlineAsmSym
                        | RibKind::AssocItem
                        | RibKind::ForwardGenericParamBan(_) => {
                            // Nothing to do. Continue.
                            continue;
                        }

                        RibKind::ConstParamTy => {
                            if !self.tcx.features().generic_const_parameter_types() {
                                if let Some(span) = finalize {
                                    self.report_error(
                                        span,
                                        ResolutionError::ParamInTyOfConstParam {
                                            name: rib_ident.name,
                                        },
                                    );
                                }
                                return Res::Err;
                            } else {
                                continue;
                            }
                        }

                        RibKind::ConstantItem(trivial, _) => {
                            if let ConstantHasGenerics::No(cause) = trivial {
                                // HACK(min_const_generics): If we encounter `Self` in an anonymous
                                // constant we can't easily tell if it's generic at this stage, so
                                // we instead remember this and then enforce the self type to be
                                // concrete later on.
                                if let Res::SelfTyAlias {
                                    alias_to: def,
                                    forbid_generic: _,
                                    is_trait_impl,
                                } = res
                                {
                                    res = Res::SelfTyAlias {
                                        alias_to: def,
                                        forbid_generic: true,
                                        is_trait_impl,
                                    }
                                } else {
                                    if let Some(span) = finalize {
                                        let error = match cause {
                                            NoConstantGenericsReason::IsEnumDiscriminant => {
                                                ResolutionError::ParamInEnumDiscriminant {
                                                    name: rib_ident.name,
                                                    param_kind: ParamKindInEnumDiscriminant::Type,
                                                }
                                            }
                                            NoConstantGenericsReason::NonTrivialConstArg => {
                                                ResolutionError::ParamInNonTrivialAnonConst {
                                                    name: rib_ident.name,
                                                    param_kind:
                                                        ParamKindInNonTrivialAnonConst::Type,
                                                }
                                            }
                                        };
                                        let _: ErrorGuaranteed = self.report_error(span, error);
                                    }

                                    return Res::Err;
                                }
                            }

                            continue;
                        }

                        // This was an attempt to use a type parameter outside its scope.
                        RibKind::Item(has_generic_params, def_kind) => {
                            (has_generic_params, def_kind)
                        }
                    };

                    if let Some(span) = finalize {
                        self.report_error(
                            span,
                            ResolutionError::GenericParamsFromOuterItem(
                                res,
                                has_generic_params,
                                def_kind,
                            ),
                        );
                    }
                    return Res::Err;
                }
            }
            Res::Def(DefKind::ConstParam, _) => {
                for rib in ribs {
                    let (has_generic_params, def_kind) = match rib.kind {
                        RibKind::Normal
                        | RibKind::Block(..)
                        | RibKind::FnOrCoroutine
                        | RibKind::Module(..)
                        | RibKind::MacroDefinition(..)
                        | RibKind::InlineAsmSym
                        | RibKind::AssocItem
                        | RibKind::ForwardGenericParamBan(_) => continue,

                        RibKind::ConstParamTy => {
                            if !self.tcx.features().generic_const_parameter_types() {
                                if let Some(span) = finalize {
                                    self.report_error(
                                        span,
                                        ResolutionError::ParamInTyOfConstParam {
                                            name: rib_ident.name,
                                        },
                                    );
                                }
                                return Res::Err;
                            } else {
                                continue;
                            }
                        }

                        RibKind::ConstantItem(trivial, _) => {
                            if let ConstantHasGenerics::No(cause) = trivial {
                                if let Some(span) = finalize {
                                    let error = match cause {
                                        NoConstantGenericsReason::IsEnumDiscriminant => {
                                            ResolutionError::ParamInEnumDiscriminant {
                                                name: rib_ident.name,
                                                param_kind: ParamKindInEnumDiscriminant::Const,
                                            }
                                        }
                                        NoConstantGenericsReason::NonTrivialConstArg => {
                                            ResolutionError::ParamInNonTrivialAnonConst {
                                                name: rib_ident.name,
                                                param_kind: ParamKindInNonTrivialAnonConst::Const {
                                                    name: rib_ident.name,
                                                },
                                            }
                                        }
                                    };
                                    self.report_error(span, error);
                                }

                                return Res::Err;
                            }

                            continue;
                        }

                        RibKind::Item(has_generic_params, def_kind) => {
                            (has_generic_params, def_kind)
                        }
                    };

                    // This was an attempt to use a const parameter outside its scope.
                    if let Some(span) = finalize {
                        self.report_error(
                            span,
                            ResolutionError::GenericParamsFromOuterItem(
                                res,
                                has_generic_params,
                                def_kind,
                            ),
                        );
                    }
                    return Res::Err;
                }
            }
            _ => {}
        }

        res
    }

    #[instrument(level = "debug", skip(self))]
    pub(crate) fn maybe_resolve_path<'r>(
        self: CmResolver<'r, 'ra, 'tcx>,
        path: &[Segment],
        opt_ns: Option<Namespace>, // `None` indicates a module path in import
        parent_scope: &ParentScope<'ra>,
        ignore_import: Option<Import<'ra>>,
    ) -> PathResult<'ra> {
        self.resolve_path_with_ribs(
            path,
            opt_ns,
            parent_scope,
            None,
            None,
            None,
            None,
            ignore_import,
        )
    }
    #[instrument(level = "debug", skip(self))]
    pub(crate) fn resolve_path<'r>(
        self: CmResolver<'r, 'ra, 'tcx>,
        path: &[Segment],
        opt_ns: Option<Namespace>, // `None` indicates a module path in import
        parent_scope: &ParentScope<'ra>,
        finalize: Option<Finalize>,
        ignore_binding: Option<NameBinding<'ra>>,
        ignore_import: Option<Import<'ra>>,
    ) -> PathResult<'ra> {
        self.resolve_path_with_ribs(
            path,
            opt_ns,
            parent_scope,
            None,
            finalize,
            None,
            ignore_binding,
            ignore_import,
        )
    }

    pub(crate) fn resolve_path_with_ribs<'r>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        path: &[Segment],
        opt_ns: Option<Namespace>, // `None` indicates a module path in import
        parent_scope: &ParentScope<'ra>,
        source: Option<PathSource<'_, '_, '_>>,
        finalize: Option<Finalize>,
        ribs: Option<&PerNS<Vec<Rib<'ra>>>>,
        ignore_binding: Option<NameBinding<'ra>>,
        ignore_import: Option<Import<'ra>>,
    ) -> PathResult<'ra> {
        let mut module = None;
        let mut module_had_parse_errors = false;
        let mut allow_super = true;
        let mut second_binding = None;

        // We'll provide more context to the privacy errors later, up to `len`.
        let privacy_errors_len = self.privacy_errors.len();
        fn record_segment_res<'r, 'ra, 'tcx>(
            mut this: CmResolver<'r, 'ra, 'tcx>,
            finalize: Option<Finalize>,
            res: Res,
            id: Option<NodeId>,
        ) {
            if finalize.is_some()
                && let Some(id) = id
                && !this.partial_res_map.contains_key(&id)
            {
                assert!(id != ast::DUMMY_NODE_ID, "Trying to resolve dummy id");
                this.get_mut().record_partial_res(id, PartialRes::new(res));
            }
        }

        for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
            debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);

            let is_last = segment_idx + 1 == path.len();
            let ns = if is_last { opt_ns.unwrap_or(TypeNS) } else { TypeNS };
            let name = ident.name;

            allow_super &= ns == TypeNS && (name == kw::SelfLower || name == kw::Super);

            if ns == TypeNS {
                if allow_super && name == kw::Super {
                    let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
                    let self_module = match segment_idx {
                        0 => Some(self.resolve_self(&mut ctxt, parent_scope.module)),
                        _ => match module {
                            Some(ModuleOrUniformRoot::Module(module)) => Some(module),
                            _ => None,
                        },
                    };
                    if let Some(self_module) = self_module
                        && let Some(parent) = self_module.parent
                    {
                        module =
                            Some(ModuleOrUniformRoot::Module(self.resolve_self(&mut ctxt, parent)));
                        continue;
                    }
                    return PathResult::failed(
                        ident,
                        false,
                        finalize.is_some(),
                        module_had_parse_errors,
                        module,
                        || ("there are too many leading `super` keywords".to_string(), None),
                    );
                }
                if segment_idx == 0 {
                    if name == kw::SelfLower {
                        let mut ctxt = ident.span.ctxt().normalize_to_macros_2_0();
                        let self_mod = self.resolve_self(&mut ctxt, parent_scope.module);
                        if let Some(res) = self_mod.res() {
                            record_segment_res(self.reborrow(), finalize, res, id);
                        }
                        module = Some(ModuleOrUniformRoot::Module(self_mod));
                        continue;
                    }
                    if name == kw::PathRoot && ident.span.at_least_rust_2018() {
                        module = Some(ModuleOrUniformRoot::ExternPrelude);
                        continue;
                    }
                    if name == kw::PathRoot
                        && ident.span.is_rust_2015()
                        && self.tcx.sess.at_least_rust_2018()
                    {
                        // `::a::b` from 2015 macro on 2018 global edition
                        let crate_root = self.resolve_crate_root(ident);
                        module = Some(ModuleOrUniformRoot::ModuleAndExternPrelude(crate_root));
                        continue;
                    }
                    if name == kw::PathRoot || name == kw::Crate || name == kw::DollarCrate {
                        // `::a::b`, `crate::a::b` or `$crate::a::b`
                        let crate_root = self.resolve_crate_root(ident);
                        if let Some(res) = crate_root.res() {
                            record_segment_res(self.reborrow(), finalize, res, id);
                        }
                        module = Some(ModuleOrUniformRoot::Module(crate_root));
                        continue;
                    }
                }
            }

            // Report special messages for path segment keywords in wrong positions.
            if ident.is_path_segment_keyword() && segment_idx != 0 {
                return PathResult::failed(
                    ident,
                    false,
                    finalize.is_some(),
                    module_had_parse_errors,
                    module,
                    || {
                        let name_str = if name == kw::PathRoot {
                            "crate root".to_string()
                        } else {
                            format!("`{name}`")
                        };
                        let label = if segment_idx == 1 && path[0].ident.name == kw::PathRoot {
                            format!("global paths cannot start with {name_str}")
                        } else {
                            format!("{name_str} in paths can only be used in start position")
                        };
                        (label, None)
                    },
                );
            }

            let binding = if let Some(module) = module {
                self.reborrow()
                    .resolve_ident_in_module(
                        module,
                        ident,
                        ns,
                        parent_scope,
                        finalize,
                        ignore_binding,
                        ignore_import,
                    )
                    .map_err(|(determinacy, _)| determinacy)
            } else if let Some(ribs) = ribs
                && let Some(TypeNS | ValueNS) = opt_ns
            {
                assert!(ignore_import.is_none());
                match self.get_mut().resolve_ident_in_lexical_scope(
                    ident,
                    ns,
                    parent_scope,
                    finalize,
                    &ribs[ns],
                    ignore_binding,
                ) {
                    // we found a locally-imported or available item/module
                    Some(LexicalScopeBinding::Item(binding)) => Ok(binding),
                    // we found a local variable or type param
                    Some(LexicalScopeBinding::Res(res)) => {
                        record_segment_res(self.reborrow(), finalize, res, id);
                        return PathResult::NonModule(PartialRes::with_unresolved_segments(
                            res,
                            path.len() - 1,
                        ));
                    }
                    _ => Err(Determinacy::determined(finalize.is_some())),
                }
            } else {
                self.reborrow().resolve_ident_in_scope_set(
                    ident,
                    ScopeSet::All(ns),
                    parent_scope,
                    finalize,
                    finalize.is_some(),
                    ignore_binding,
                    ignore_import,
                )
            };

            match binding {
                Ok(binding) => {
                    if segment_idx == 1 {
                        second_binding = Some(binding);
                    }
                    let res = binding.res();

                    // Mark every privacy error in this path with the res to the last element. This allows us
                    // to detect the item the user cares about and either find an alternative import, or tell
                    // the user it is not accessible.
                    if finalize.is_some() {
                        for error in &mut self.get_mut().privacy_errors[privacy_errors_len..] {
                            error.outermost_res = Some((res, ident));
                            error.source = match source {
                                Some(PathSource::Struct(Some(expr)))
                                | Some(PathSource::Expr(Some(expr))) => Some(expr.clone()),
                                _ => None,
                            };
                        }
                    }

                    let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
                    if let Some(def_id) = binding.res().module_like_def_id() {
                        if self.mods_with_parse_errors.contains(&def_id) {
                            module_had_parse_errors = true;
                        }
                        module = Some(ModuleOrUniformRoot::Module(self.expect_module(def_id)));
                        record_segment_res(self.reborrow(), finalize, res, id);
                    } else if res == Res::ToolMod && !is_last && opt_ns.is_some() {
                        if binding.is_import() {
                            self.dcx().emit_err(errors::ToolModuleImported {
                                span: ident.span,
                                import: binding.span,
                            });
                        }
                        let res = Res::NonMacroAttr(NonMacroAttrKind::Tool);
                        return PathResult::NonModule(PartialRes::new(res));
                    } else if res == Res::Err {
                        return PathResult::NonModule(PartialRes::new(Res::Err));
                    } else if opt_ns.is_some() && (is_last || maybe_assoc) {
                        if let Some(finalize) = finalize {
                            self.get_mut().lint_if_path_starts_with_module(
                                finalize,
                                path,
                                second_binding,
                            );
                        }
                        record_segment_res(self.reborrow(), finalize, res, id);
                        return PathResult::NonModule(PartialRes::with_unresolved_segments(
                            res,
                            path.len() - segment_idx - 1,
                        ));
                    } else {
                        return PathResult::failed(
                            ident,
                            is_last,
                            finalize.is_some(),
                            module_had_parse_errors,
                            module,
                            || {
                                let label = format!(
                                    "`{ident}` is {} {}, not a module",
                                    res.article(),
                                    res.descr()
                                );
                                (label, None)
                            },
                        );
                    }
                }
                Err(Undetermined) => return PathResult::Indeterminate,
                Err(Determined) => {
                    if let Some(ModuleOrUniformRoot::Module(module)) = module
                        && opt_ns.is_some()
                        && !module.is_normal()
                    {
                        return PathResult::NonModule(PartialRes::with_unresolved_segments(
                            module.res().unwrap(),
                            path.len() - segment_idx,
                        ));
                    }

                    let mut this = self.reborrow();
                    return PathResult::failed(
                        ident,
                        is_last,
                        finalize.is_some(),
                        module_had_parse_errors,
                        module,
                        || {
                            this.get_mut().report_path_resolution_error(
                                path,
                                opt_ns,
                                parent_scope,
                                ribs,
                                ignore_binding,
                                ignore_import,
                                module,
                                segment_idx,
                                ident,
                            )
                        },
                    );
                }
            }
        }

        if let Some(finalize) = finalize {
            self.get_mut().lint_if_path_starts_with_module(finalize, path, second_binding);
        }

        PathResult::Module(match module {
            Some(module) => module,
            None if path.is_empty() => ModuleOrUniformRoot::CurrentScope,
            _ => bug!("resolve_path: non-empty path `{:?}` has no module", path),
        })
    }
}
