use Determinacy::*;
use Namespace::*;
use rustc_ast::{self as ast, NodeId};
use rustc_errors::ErrorGuaranteed;
use rustc_hir::def::{DefKind, Namespace, NonMacroAttrKind, PartialRes, PerNS};
use rustc_middle::bug;
use rustc_session::lint::BuiltinLintDiag;
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, Determinacy, Finalize,
    ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding,
    NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope,
    ScopeSet, Segment, 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<T>(
        &mut self,
        scope_set: ScopeSet<'ra>,
        parent_scope: &ParentScope<'ra>,
        ctxt: SyntaxContext,
        mut visitor: impl FnMut(&mut Self, 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, _)
            | ScopeSet::Late(ns, ..) => (ns, None),
            ScopeSet::Macro(macro_kind) => (MacroNS, Some(macro_kind)),
        };
        let module = match scope_set {
            // Start with the specified module.
            ScopeSet::Late(_, 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 mut scope = match ns {
            _ if module_and_extern_prelude => Scope::Module(module, None),
            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::ExternPrelude => use_prelude || module_and_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(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::ExternPrelude
                    }
                    ValueNS | MacroNS => break,
                },
                Scope::Module(module, prev_lint_id) => {
                    use_prelude = !module.no_implicit_prelude;
                    let derive_fallback_lint_id = match scope_set {
                        ScopeSet::Late(.., lint_id) => lint_id,
                        _ => None,
                    };
                    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::ExternPrelude,
                                ValueNS => Scope::StdLibPrelude,
                                MacroNS => Scope::MacroUsePrelude,
                            }
                        }
                    }
                }
                Scope::MacroUsePrelude => Scope::StdLibPrelude,
                Scope::BuiltinAttrs => break, // nowhere else to search
                Scope::ExternPrelude if module_and_extern_prelude => break,
                Scope::ExternPrelude => 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_kind() == MacroKind::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.
        let mut module = self.graph_root;
        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,
                )));
            }

            module = match rib.kind {
                RibKind::Module(module) => module,
                RibKind::MacroDefinition(def) if 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();
                    continue;
                }
                _ => continue,
            };

            match module.kind {
                ModuleKind::Block => {} // We can see through blocks
                _ => break,
            }

            let item = self.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,
            );
            if let Ok(binding) = item {
                // The ident resolves to an item.
                return Some(LexicalScopeBinding::Item(binding));
            }
        }
        self.early_resolve_ident_in_lexical_scope(
            orig_ident,
            ScopeSet::Late(ns, module, finalize.map(|finalize| finalize.node_id)),
            parent_scope,
            finalize,
            finalize.is_some(),
            ignore_binding,
            None,
        )
        .ok()
        .map(LexicalScopeBinding::Item)
    }

    /// Resolve an identifier in lexical scope.
    /// This is a variation of `fn resolve_ident_in_lexical_scope` that can be run during
    /// expansion and import resolution (perhaps they can be merged in the future).
    /// The function is used for resolving initial segments of macro paths (e.g., `foo` in
    /// `foo::bar!();` or `foo!();`) and also for import paths on 2018 edition.
    #[instrument(level = "debug", skip(self))]
    pub(crate) fn early_resolve_ident_in_lexical_scope(
        &mut self,
        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, _)
            | ScopeSet::Late(ns, ..) => (ns, 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;

        // 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(),
            |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 => {
                        // FIXME: Try running this logic earlier, to allocate name bindings for
                        // legacy derive helpers when creating an attribute invocation with
                        // following derives. Legacy derive helpers are not common, so it shouldn't
                        // affect performance. It should also allow to remove the `derives`
                        // component from `ParentScope`.
                        let mut result = Err(Determinacy::Determined);
                        for derive in parent_scope.derives {
                            let parent_scope = &ParentScope { derives: &[], ..*parent_scope };
                            match this.resolve_macro_path(
                                derive,
                                Some(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, 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 = this.resolve_ident_in_module_unadjusted(
                            ModuleOrUniformRoot::Module(module),
                            ident,
                            ns,
                            adjusted_parent_scope,
                            if matches!(scope_set, ScopeSet::Late(..)) {
                                Shadowing::Unrestricted
                            } else {
                                Shadowing::Restricted
                            },
                            finalize,
                            ignore_binding,
                            ignore_import,
                        );
                        match binding {
                            Ok(binding) => {
                                if let Some(lint_id) = derive_fallback_lint_id {
                                    this.lint_buffer.buffer_lint(
                                        PROC_MACRO_DERIVE_RESOLUTION_FALLBACK,
                                        lint_id,
                                        orig_ident.span,
                                        BuiltinLintDiag::ProcMacroDeriveResolutionFallback {
                                            span: orig_ident.span,
                                            ns,
                                            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::ExternPrelude => {
                        match this.extern_prelude_get(ident, finalize.is_some()) {
                            Some(binding) => Ok((binding, Flags::empty())),
                            None => Err(Determinacy::determined(
                                this.graph_root.unexpanded_invocations.borrow().is_empty(),
                            )),
                        }
                    }
                    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.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.is_some()
                                && innermost_result.is_none()
                            {
                                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.is_some()
                                && innermost_result.is_none()
                            {
                                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_kind(), macro_kind) =>
                    {
                        if finalize.is_none() || matches!(scope_set, ScopeSet::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,
                                    )
                                    || flags.contains(Flags::MACRO_RULES)
                                        && innermost_flags.contains(Flags::MODULE)
                                        && !this.disambiguate_macro_rules_vs_modularized(
                                            binding,
                                            innermost_binding,
                                        )
                                {
                                    Some(AmbiguityKind::MacroRulesVsModularized)
                                } 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
                                };
                                if let Some(kind) = ambiguity_error_kind {
                                    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.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));
                        }
                    }
                    Ok(..) | 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(
        &mut self,
        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(
        &mut self,
        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(
        &mut self,
        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.early_resolve_ident_in_lexical_scope(
                    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 if let Some(binding) = self.extern_prelude_get(ident, finalize.is_some()) {
                    Ok(binding)
                } else if !self.graph_root.unexpanded_invocations.borrow().is_empty() {
                    // Macro-expanded `extern crate` items can add names to extern prelude.
                    Err((Undetermined, Weak::No))
                } else {
                    Err((Determined, 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.early_resolve_ident_in_lexical_scope(
                    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.finalize_module_binding(
                ident,
                binding,
                if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
                parent_scope,
                finalize,
                shadowing,
            );
        }

        let check_usable = |this: &Self, 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.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 `early_resolve_ident_in_lexical_scope` 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.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>,
        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,
                    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
            && 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));
        }

        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(
        &mut self,
        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.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::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::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::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(
        &mut self,
        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, ignore_import)
    }

    #[instrument(level = "debug", skip(self))]
    pub(crate) fn resolve_path(
        &mut self,
        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,
            finalize,
            None,
            ignore_binding,
            ignore_import,
        )
    }

    pub(crate) fn resolve_path_with_ribs(
        &mut self,
        path: &[Segment],
        opt_ns: Option<Namespace>, // `None` indicates a module path in import
        parent_scope: &ParentScope<'ra>,
        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();

        for (segment_idx, &Segment { ident, id, .. }) in path.iter().enumerate() {
            debug!("resolve_path ident {} {:?} {:?}", segment_idx, ident, id);
            let record_segment_res = |this: &mut Self, res| {
                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.record_partial_res(id, PartialRes::new(res));
                }
            };

            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, res);
                        }
                        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, res);
                        }
                        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.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.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, res);
                        return PathResult::NonModule(PartialRes::with_unresolved_segments(
                            res,
                            path.len() - 1,
                        ));
                    }
                    _ => Err(Determinacy::determined(finalize.is_some())),
                }
            } else {
                self.early_resolve_ident_in_lexical_scope(
                    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.
                    for error in &mut self.privacy_errors[privacy_errors_len..] {
                        error.outermost_res = Some((res, ident));
                    }

                    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, res);
                    } 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) {
                        self.lint_if_path_starts_with_module(finalize, path, second_binding);
                        record_segment_res(self, res);
                        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,
                        ));
                    }

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

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