use std::ops::ControlFlow;

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

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;
    }
}

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,
        ) -> ControlFlow<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 ControlFlow::Break(break_result) =
                    visitor(&mut self, scope, use_prelude, ctxt)
                {
                    return Some(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>>,
        diag_metadata: Option<&DiagMetadata<'_>>,
    ) -> 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(|_| general_span),
                    *original_rib_ident_def,
                    ribs,
                    diag_metadata,
                )));
            } else if let RibKind::Block(Some(module)) = rib.kind
                && let Ok(binding) = self.cm().resolve_ident_in_module_unadjusted(
                    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> {
        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)),
        };
        let derive_fallback_lint_id = match finalize {
            Some(Finalize { node_id, stage: Stage::Late, .. }) => Some(node_id),
            _ => None,
        };

        // 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;

        // Go through all the scopes and try to resolve the name.
        let break_result = self.visit_scopes(
            scope_set,
            parent_scope,
            orig_ident.span.ctxt(),
            derive_fallback_lint_id,
            |this, scope, use_prelude, ctxt| {
                // We can break with an error at this step, it means we cannot determine the
                // resolution right now, but we must block and wait until we can instead of
                // considering outer scopes.
                match this.reborrow().resolve_ident_in_scope(
                    orig_ident,
                    ns,
                    scope,
                    use_prelude,
                    ctxt,
                    scope_set,
                    parent_scope,
                    // Shadowed bindings don't need to be marked as used or non-speculatively loaded.
                    if innermost_result.is_none() { finalize } else { None },
                    force,
                    ignore_binding,
                    ignore_import,
                    &mut extern_prelude_item_binding,
                    &mut extern_prelude_flag_binding,
                )? {
                    Ok((binding, flags))
                        if sub_namespace_match(binding.macro_kinds(), macro_kind) =>
                    {
                        // 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 ControlFlow::Break(Ok(binding));
                        }

                        if let Some((innermost_binding, innermost_flags)) = innermost_result {
                            // Found another solution, if the first one was "weak", report an error.
                            if this.get_mut().maybe_push_ambiguity(
                                orig_ident,
                                parent_scope,
                                binding,
                                innermost_binding,
                                flags,
                                innermost_flags,
                                extern_prelude_item_binding,
                                extern_prelude_flag_binding,
                            ) {
                                // No need to search for more potential ambiguities, one is enough.
                                return ControlFlow::Break(Ok(innermost_binding));
                            }
                        } else {
                            // Found the first solution.
                            innermost_result = Some((binding, flags));
                        }
                    }
                    Ok(_) | Err(Determinacy::Determined) => {}
                    Err(Determinacy::Undetermined) => determinacy = Determinacy::Undetermined,
                }

                ControlFlow::Continue(())
            },
        );

        // Scope visiting returned some result early.
        if let Some(break_result) = break_result {
            return break_result;
        }

        // Scope visiting walked all the scopes and maybe found something in one of them.
        match innermost_result {
            Some((binding, _)) => Ok(binding),
            None => Err(Determinacy::determined(determinacy == Determinacy::Determined || force)),
        }
    }

    fn resolve_ident_in_scope<'r>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        orig_ident: Ident,
        ns: Namespace,
        scope: Scope<'ra>,
        use_prelude: UsePrelude,
        ctxt: SyntaxContext,
        scope_set: ScopeSet<'ra>,
        parent_scope: &ParentScope<'ra>,
        finalize: Option<Finalize>,
        force: bool,
        ignore_binding: Option<NameBinding<'ra>>,
        ignore_import: Option<Import<'ra>>,
        extern_prelude_item_binding: &mut Option<NameBinding<'ra>>,
        extern_prelude_flag_binding: &mut Option<NameBinding<'ra>>,
    ) -> ControlFlow<
        Result<NameBinding<'ra>, Determinacy>,
        Result<(NameBinding<'ra>, Flags), Determinacy>,
    > {
        let ident = Ident::new(orig_ident.name, orig_ident.span.with_ctxt(ctxt));
        let ret = match scope {
            Scope::DeriveHelpers(expn_id) => {
                if let Some(binding) = self.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 self.reborrow().resolve_derive_macro_path(
                        derive,
                        parent_scope,
                        force,
                        ignore_import,
                    ) {
                        Ok((Some(ext), _)) => {
                            if ext.helper_attrs.contains(&ident.name) {
                                let binding = self.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)
                    } else {
                        (
                            &ParentScope { module, ..*parent_scope },
                            finalize.map(|f| Finalize { used: Used::Scope, ..f }),
                        )
                    };
                let binding = self.reborrow().resolve_ident_in_module_unadjusted(
                    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 {
                            self.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 == self.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(ControlFlow::Continue(determinacy)) => Err(determinacy),
                    Err(ControlFlow::Break(Determinacy::Undetermined)) => {
                        return ControlFlow::Break(Err(Determinacy::determined(force)));
                    }
                    // Privacy errors, do not happen during in scope resolution.
                    Err(ControlFlow::Break(Determinacy::Determined)) => unreachable!(),
                }
            }
            Scope::MacroUsePrelude => match self.macro_use_prelude.get(&ident.name).cloned() {
                Some(binding) => Ok((binding, Flags::MISC_FROM_PRELUDE)),
                None => Err(Determinacy::determined(
                    self.graph_root.unexpanded_invocations.borrow().is_empty(),
                )),
            },
            Scope::BuiltinAttrs => match self.builtin_attrs_bindings.get(&ident.name) {
                Some(binding) => Ok((*binding, Flags::empty())),
                None => Err(Determinacy::Determined),
            },
            Scope::ExternPreludeItems => {
                match self.reborrow().extern_prelude_get_item(ident, finalize.is_some()) {
                    Some(binding) => {
                        *extern_prelude_item_binding = Some(binding);
                        Ok((binding, Flags::empty()))
                    }
                    None => Err(Determinacy::determined(
                        self.graph_root.unexpanded_invocations.borrow().is_empty(),
                    )),
                }
            }
            Scope::ExternPreludeFlags => {
                match self.extern_prelude_get_flag(ident, finalize.is_some()) {
                    Some(binding) => {
                        *extern_prelude_flag_binding = Some(binding);
                        Ok((binding, Flags::empty()))
                    }
                    None => Err(Determinacy::Determined),
                }
            }
            Scope::ToolPrelude => match self.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) = self.prelude
                    && let Ok(binding) = self.reborrow().resolve_ident_in_module_unadjusted(
                        prelude,
                        ident,
                        ns,
                        parent_scope,
                        Shadowing::Unrestricted,
                        None,
                        ignore_binding,
                        ignore_import,
                    )
                    && (matches!(use_prelude, UsePrelude::Yes)
                        || self.is_builtin_macro(binding.res()))
                {
                    result = Ok((binding, Flags::MISC_FROM_PRELUDE));
                }

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

        ControlFlow::Continue(ret)
    }

    fn maybe_push_ambiguity(
        &mut self,
        orig_ident: Ident,
        parent_scope: &ParentScope<'ra>,
        binding: NameBinding<'ra>,
        innermost_binding: NameBinding<'ra>,
        flags: Flags,
        innermost_flags: Flags,
        extern_prelude_item_binding: Option<NameBinding<'ra>>,
        extern_prelude_flag_binding: Option<NameBinding<'ra>>,
    ) -> bool {
        let (res, innermost_res) = (binding.res(), innermost_binding.res());
        if res == innermost_res {
            return false;
        }

        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)
            && !self.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
                }
            };
            self.ambiguity_errors.push(AmbiguityError {
                kind,
                ident: orig_ident,
                b1: innermost_binding,
                b2: binding,
                warning: false,
                misc1: misc(innermost_flags),
                misc2: misc(flags),
            });
            return true;
        }

        false
    }

    #[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)
    }

    #[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> {
        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_virt_module_unadjusted(
            module,
            ident,
            ns,
            adjusted_parent_scope,
            finalize,
            ignore_binding,
            ignore_import,
        )
    }

    /// Attempts to resolve `ident` in namespace `ns` of `module`.
    #[instrument(level = "debug", skip(self))]
    fn resolve_ident_in_virt_module_unadjusted<'r>(
        self: CmResolver<'r, 'ra, 'tcx>,
        module: ModuleOrUniformRoot<'ra>,
        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> {
        match module {
            ModuleOrUniformRoot::Module(module) => self
                .resolve_ident_in_module_unadjusted(
                    module,
                    ident,
                    ns,
                    parent_scope,
                    Shadowing::Unrestricted,
                    finalize,
                    ignore_binding,
                    ignore_import,
                )
                .map_err(|determinacy| determinacy.into_value()),
            ModuleOrUniformRoot::ModuleAndExternPrelude(module) => self.resolve_ident_in_scope_set(
                ident,
                ScopeSet::ModuleAndExternPrelude(ns, module),
                parent_scope,
                finalize,
                finalize.is_some(),
                ignore_binding,
                ignore_import,
            ),
            ModuleOrUniformRoot::ExternPrelude => {
                if ns != TypeNS {
                    Err(Determined)
                } else {
                    self.resolve_ident_in_scope_set(
                        ident,
                        ScopeSet::ExternPrelude,
                        parent_scope,
                        finalize,
                        finalize.is_some(),
                        ignore_binding,
                        ignore_import,
                    )
                }
            }
            ModuleOrUniformRoot::CurrentScope => {
                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_...`.
                    }
                }

                self.resolve_ident_in_scope_set(
                    ident,
                    ScopeSet::All(ns),
                    parent_scope,
                    finalize,
                    finalize.is_some(),
                    ignore_binding,
                    ignore_import,
                )
            }
        }
    }

    /// Attempts to resolve `ident` in namespace `ns` of `module`.
    fn resolve_ident_in_module_unadjusted<'r>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        module: Module<'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>, ControlFlow<Determinacy, Determinacy>> {
        let res = self.reborrow().resolve_ident_in_module_non_globs_unadjusted(
            module,
            ident,
            ns,
            parent_scope,
            shadowing,
            finalize,
            ignore_binding,
            ignore_import,
        );

        match res {
            Ok(_) | Err(ControlFlow::Break(_)) => return res,
            Err(ControlFlow::Continue(_)) => {}
        }

        self.resolve_ident_in_module_globs_unadjusted(
            module,
            ident,
            ns,
            parent_scope,
            shadowing,
            finalize,
            ignore_binding,
            ignore_import,
        )
    }

    /// Attempts to resolve `ident` in namespace `ns` of non-glob bindings in `module`.
    fn resolve_ident_in_module_non_globs_unadjusted<'r>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        module: Module<'ra>,
        ident: Ident,
        ns: Namespace,
        parent_scope: &ParentScope<'ra>,
        shadowing: Shadowing,
        finalize: Option<Finalize>,
        ignore_binding: Option<NameBinding<'ra>>,
        ignore_import: Option<Import<'ra>>,
    ) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
        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_unchecked()
            .map_err(|_| ControlFlow::Continue(Determined))?;

        let binding = resolution.non_glob_binding.filter(|b| Some(*b) != ignore_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,
            );
        }

        // Items and single imports are not shadowable, if we have one, then it's determined.
        if let Some(binding) = binding {
            let accessible = self.is_accessible_from(binding.vis, parent_scope.module);
            return if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) };
        }

        // Check if one of single imports can still define the name, block if it can.
        if self.reborrow().single_import_can_define_name(
            &resolution,
            None,
            ns,
            ignore_import,
            ignore_binding,
            parent_scope,
        ) {
            return Err(ControlFlow::Break(Undetermined));
        }

        // Check if one of unexpanded macros can still define the name.
        if !module.unexpanded_invocations.borrow().is_empty() {
            return Err(ControlFlow::Continue(Undetermined));
        }

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

    /// Attempts to resolve `ident` in namespace `ns` of glob bindings in `module`.
    fn resolve_ident_in_module_globs_unadjusted<'r>(
        mut self: CmResolver<'r, 'ra, 'tcx>,
        module: Module<'ra>,
        ident: Ident,
        ns: Namespace,
        parent_scope: &ParentScope<'ra>,
        shadowing: Shadowing,
        finalize: Option<Finalize>,
        ignore_binding: Option<NameBinding<'ra>>,
        ignore_import: Option<Import<'ra>>,
    ) -> Result<NameBinding<'ra>, ControlFlow<Determinacy, Determinacy>> {
        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_unchecked()
            .map_err(|_| ControlFlow::Continue(Determined))?;

        let binding = resolution.glob_binding.filter(|b| Some(*b) != ignore_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,
            );
        }

        // 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(ControlFlow::Break(Undetermined));
        }

        // 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 {
            return if binding.determined() || ns == MacroNS || shadowing == Shadowing::Restricted {
                let accessible = self.is_accessible_from(binding.vis, parent_scope.module);
                if accessible { Ok(binding) } else { Err(ControlFlow::Break(Determined)) }
            } else {
                Err(ControlFlow::Break(Undetermined))
            };
        }

        // 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 `ControlFlow::Continue`.
        // 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(ControlFlow::Continue(Undetermined));
        }

        // 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(ControlFlow::Continue(Undetermined)),
            };
            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(
                module,
                ident,
                ns,
                adjusted_parent_scope,
                Shadowing::Unrestricted,
                None,
                ignore_binding,
                ignore_import,
            );

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

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

    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>, ControlFlow<Determinacy, Determinacy>> {
        let Finalize { path_span, report_private, used, root_span, .. } = finalize;

        let Some(binding) = binding else {
            return Err(ControlFlow::Continue(Determined));
        };

        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(ControlFlow::Break(Determined));
            }
        }

        // 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>],
        diag_metadata: Option<&DiagMetadata<'_>>,
    ) -> 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 {
                        let item = if let Some(diag_metadata) = diag_metadata
                            && let Some(current_item) = diag_metadata.current_item
                        {
                            let span = current_item
                                .kind
                                .ident()
                                .map(|i| i.span)
                                .unwrap_or(current_item.span);
                            Some((span, current_item.kind.clone()))
                        } else {
                            None
                        };
                        self.report_error(
                            span,
                            ResolutionError::GenericParamsFromOuterItem {
                                outer_res: res,
                                has_generic_params,
                                def_kind,
                                inner_item: item,
                                current_self_ty: diag_metadata
                                    .and_then(|m| m.current_self_type.as_ref())
                                    .and_then(|ty| {
                                        self.tcx.sess.source_map().span_to_snippet(ty.span).ok()
                                    }),
                            },
                        );
                    }
                    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 {
                        let item = if let Some(diag_metadata) = diag_metadata
                            && let Some(current_item) = diag_metadata.current_item
                        {
                            let span = current_item
                                .kind
                                .ident()
                                .map(|i| i.span)
                                .unwrap_or(current_item.span);
                            Some((span, current_item.kind.clone()))
                        } else {
                            None
                        };
                        self.report_error(
                            span,
                            ResolutionError::GenericParamsFromOuterItem {
                                outer_res: res,
                                has_generic_params,
                                def_kind,
                                inner_item: item,
                                current_self_ty: diag_metadata
                                    .and_then(|m| m.current_self_type.as_ref())
                                    .and_then(|ty| {
                                        self.tcx.sess.source_map().span_to_snippet(ty.span).ok()
                                    }),
                            },
                        );
                    }
                    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,
            None,
        )
    }
    #[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,
            None,
        )
    }

    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>>,
        diag_metadata: Option<&DiagMetadata<'_>>,
    ) -> 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,
                )
            } 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,
                    diag_metadata,
                ) {
                    // 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,
                                diag_metadata,
                            )
                        },
                    );
                }
            }
        }

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