about summary refs log tree commit diff
path: root/compiler/rustc_resolve
diff options
context:
space:
mode:
Diffstat (limited to 'compiler/rustc_resolve')
-rw-r--r--compiler/rustc_resolve/src/build_reduced_graph.rs181
-rw-r--r--compiler/rustc_resolve/src/check_unused.rs2
-rw-r--r--compiler/rustc_resolve/src/def_collector.rs1
-rw-r--r--compiler/rustc_resolve/src/diagnostics.rs65
-rw-r--r--compiler/rustc_resolve/src/ident.rs30
-rw-r--r--compiler/rustc_resolve/src/imports.rs326
-rw-r--r--compiler/rustc_resolve/src/late.rs14
-rw-r--r--compiler/rustc_resolve/src/late/diagnostics.rs35
-rw-r--r--compiler/rustc_resolve/src/lib.rs120
-rw-r--r--compiler/rustc_resolve/src/macros.rs28
10 files changed, 384 insertions, 418 deletions
diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs
index ef122deba4e..5a1be618cee 100644
--- a/compiler/rustc_resolve/src/build_reduced_graph.rs
+++ b/compiler/rustc_resolve/src/build_reduced_graph.rs
@@ -20,9 +20,9 @@ use rustc_hir::def::{self, *};
 use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LocalDefId};
 use rustc_index::bit_set::DenseBitSet;
 use rustc_metadata::creader::LoadedMacro;
+use rustc_middle::bug;
 use rustc_middle::metadata::ModChild;
-use rustc_middle::ty::Feed;
-use rustc_middle::{bug, ty};
+use rustc_middle::ty::{Feed, Visibility};
 use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind};
 use rustc_span::{Ident, Span, Symbol, kw, sym};
 use tracing::debug;
@@ -32,56 +32,43 @@ use crate::def_collector::collect_definitions;
 use crate::imports::{ImportData, ImportKind};
 use crate::macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 use crate::{
-    BindingKey, Determinacy, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind,
-    ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult,
-    ResolutionError, Resolver, ResolverArenas, Segment, ToNameBinding, Used, VisResolutionError,
-    errors,
+    BindingKey, ExternPreludeEntry, Finalize, MacroData, Module, ModuleKind, ModuleOrUniformRoot,
+    NameBinding, ParentScope, PathResult, ResolutionError, Resolver, Segment, Used,
+    VisResolutionError, errors,
 };
 
 type Res = def::Res<NodeId>;
 
-impl<'ra, Id: Into<DefId>> ToNameBinding<'ra>
-    for (Module<'ra>, ty::Visibility<Id>, Span, LocalExpnId)
-{
-    fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> {
-        arenas.alloc_name_binding(NameBindingData {
-            kind: NameBindingKind::Module(self.0),
-            ambiguity: None,
-            warn_ambiguity: false,
-            vis: self.1.to_def_id(),
-            span: self.2,
-            expansion: self.3,
-        })
-    }
-}
-
-impl<'ra, Id: Into<DefId>> ToNameBinding<'ra> for (Res, ty::Visibility<Id>, Span, LocalExpnId) {
-    fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> {
-        arenas.alloc_name_binding(NameBindingData {
-            kind: NameBindingKind::Res(self.0),
-            ambiguity: None,
-            warn_ambiguity: false,
-            vis: self.1.to_def_id(),
-            span: self.2,
-            expansion: self.3,
-        })
-    }
-}
-
 impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     /// Defines `name` in namespace `ns` of module `parent` to be `def` if it is not yet defined;
     /// otherwise, reports an error.
-    pub(crate) fn define<T>(&mut self, parent: Module<'ra>, ident: Ident, ns: Namespace, def: T)
-    where
-        T: ToNameBinding<'ra>,
-    {
-        let binding = def.to_name_binding(self.arenas);
+    pub(crate) fn define_binding(
+        &mut self,
+        parent: Module<'ra>,
+        ident: Ident,
+        ns: Namespace,
+        binding: NameBinding<'ra>,
+    ) {
         let key = self.new_disambiguated_key(ident, ns);
         if let Err(old_binding) = self.try_define(parent, key, binding, false) {
             self.report_conflict(parent, ident, ns, old_binding, binding);
         }
     }
 
+    fn define(
+        &mut self,
+        parent: Module<'ra>,
+        ident: Ident,
+        ns: Namespace,
+        res: Res,
+        vis: Visibility<impl Into<DefId>>,
+        span: Span,
+        expn_id: LocalExpnId,
+    ) {
+        let binding = self.arenas.new_res_binding(res, vis.to_def_id(), span, expn_id);
+        self.define_binding(parent, ident, ns, binding)
+    }
+
     /// Walks up the tree of definitions starting at `def_id`,
     /// stopping at the first encountered module.
     /// Parent block modules for arbitrary def-ids are not recorded for the local crate,
@@ -122,7 +109,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         if !def_id.is_local() {
             // Query `def_kind` is not used because query system overhead is too expensive here.
             let def_kind = self.cstore().def_kind_untracked(def_id);
-            if let DefKind::Mod | DefKind::Enum | DefKind::Trait = def_kind {
+            if def_kind.is_module_like() {
                 let parent = self
                     .tcx
                     .opt_parent(def_id)
@@ -224,12 +211,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let expansion = parent_scope.expansion;
         // Record primary definitions.
         match res {
-            Res::Def(DefKind::Mod | DefKind::Enum | DefKind::Trait, def_id) => {
-                let module = self.expect_module(def_id);
-                self.define(parent, ident, TypeNS, (module, vis, span, expansion));
-            }
             Res::Def(
-                DefKind::Struct
+                DefKind::Mod
+                | DefKind::Enum
+                | DefKind::Trait
+                | DefKind::Struct
                 | DefKind::Union
                 | DefKind::Variant
                 | DefKind::TyAlias
@@ -240,7 +226,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 _,
             )
             | Res::PrimTy(..)
-            | Res::ToolMod => self.define(parent, ident, TypeNS, (res, vis, span, expansion)),
+            | Res::ToolMod => self.define(parent, ident, TypeNS, res, vis, span, expansion),
             Res::Def(
                 DefKind::Fn
                 | DefKind::AssocFn
@@ -249,9 +235,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 | DefKind::AssocConst
                 | DefKind::Ctor(..),
                 _,
-            ) => self.define(parent, ident, ValueNS, (res, vis, span, expansion)),
+            ) => self.define(parent, ident, ValueNS, res, vis, span, expansion),
             Res::Def(DefKind::Macro(..), _) | Res::NonMacroAttr(..) => {
-                self.define(parent, ident, MacroNS, (res, vis, span, expansion))
+                self.define(parent, ident, MacroNS, res, vis, span, expansion)
             }
             Res::Def(
                 DefKind::TyParam
@@ -295,10 +281,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         Res::Def(self.r.tcx.def_kind(def_id), def_id)
     }
 
-    fn resolve_visibility(&mut self, vis: &ast::Visibility) -> ty::Visibility {
+    fn resolve_visibility(&mut self, vis: &ast::Visibility) -> Visibility {
         self.try_resolve_visibility(vis, true).unwrap_or_else(|err| {
             self.r.report_vis_error(err);
-            ty::Visibility::Public
+            Visibility::Public
         })
     }
 
@@ -306,10 +292,10 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         &mut self,
         vis: &'ast ast::Visibility,
         finalize: bool,
-    ) -> Result<ty::Visibility, VisResolutionError<'ast>> {
+    ) -> Result<Visibility, VisResolutionError<'ast>> {
         let parent_scope = &self.parent_scope;
         match vis.kind {
-            ast::VisibilityKind::Public => Ok(ty::Visibility::Public),
+            ast::VisibilityKind::Public => Ok(Visibility::Public),
             ast::VisibilityKind::Inherited => {
                 Ok(match self.parent_scope.module.kind {
                     // Any inherited visibility resolved directly inside an enum or trait
@@ -319,7 +305,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         self.r.tcx.visibility(def_id).expect_local()
                     }
                     // Otherwise, the visibility is restricted to the nearest parent `mod` item.
-                    _ => ty::Visibility::Restricted(
+                    _ => Visibility::Restricted(
                         self.parent_scope.module.nearest_parent_mod().expect_local(),
                     ),
                 })
@@ -367,9 +353,9 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         }
                         if module.is_normal() {
                             match res {
-                                Res::Err => Ok(ty::Visibility::Public),
+                                Res::Err => Ok(Visibility::Public),
                                 _ => {
-                                    let vis = ty::Visibility::Restricted(res.def_id());
+                                    let vis = Visibility::Restricted(res.def_id());
                                     if self.r.is_accessible_from(vis, parent_scope.module) {
                                         Ok(vis.expect_local())
                                     } else {
@@ -434,7 +420,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         item: &ast::Item,
         root_span: Span,
         root_id: NodeId,
-        vis: ty::Visibility,
+        vis: Visibility,
     ) {
         let current_module = self.parent_scope.module;
         let import = self.r.arenas.alloc_import(ImportData {
@@ -482,7 +468,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         list_stem: bool,
         // The whole `use` item
         item: &Item,
-        vis: ty::Visibility,
+        vis: Visibility,
         root_span: Span,
     ) {
         debug!(
@@ -620,16 +606,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 let kind = ImportKind::Single {
                     source: source.ident,
                     target: ident,
-                    source_bindings: PerNS {
-                        type_ns: Cell::new(Err(Determinacy::Undetermined)),
-                        value_ns: Cell::new(Err(Determinacy::Undetermined)),
-                        macro_ns: Cell::new(Err(Determinacy::Undetermined)),
-                    },
-                    target_bindings: PerNS {
-                        type_ns: Cell::new(None),
-                        value_ns: Cell::new(None),
-                        macro_ns: Cell::new(None),
-                    },
+                    bindings: Default::default(),
                     type_ns_only,
                     nested,
                     id,
@@ -700,7 +677,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         true,
                         // The whole `use` item
                         item,
-                        ty::Visibility::Restricted(
+                        Visibility::Restricted(
                             self.parent_scope.module.nearest_parent_mod().expect_local(),
                         ),
                         root_span,
@@ -716,7 +693,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         ident: Ident,
         feed: Feed<'tcx, LocalDefId>,
         adt_res: Res,
-        adt_vis: ty::Visibility,
+        adt_vis: Visibility,
         adt_span: Span,
     ) {
         let parent_scope = &self.parent_scope;
@@ -724,7 +701,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let expansion = parent_scope.expansion;
 
         // Define a name in the type namespace if it is not anonymous.
-        self.r.define(parent, ident, TypeNS, (adt_res, adt_vis, adt_span, expansion));
+        self.r.define(parent, ident, TypeNS, adt_res, adt_vis, adt_span, expansion);
         self.r.feed_visibility(feed, adt_vis);
         let def_id = feed.key();
 
@@ -776,7 +753,12 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             }
 
             ItemKind::Mod(_, ident, ref mod_kind) => {
-                let module = self.r.new_module(
+                self.r.define(parent, ident, TypeNS, res, vis, sp, expansion);
+
+                if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind {
+                    self.r.mods_with_parse_errors.insert(def_id);
+                }
+                self.parent_scope.module = self.r.new_module(
                     Some(parent),
                     ModuleKind::Def(def_kind, def_id, Some(ident.name)),
                     expansion.to_expn_id(),
@@ -784,24 +766,16 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                     parent.no_implicit_prelude
                         || ast::attr::contains_name(&item.attrs, sym::no_implicit_prelude),
                 );
-                self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
-
-                if let ast::ModKind::Loaded(_, _, _, Err(_)) = mod_kind {
-                    self.r.mods_with_parse_errors.insert(def_id);
-                }
-
-                // Descend into the module.
-                self.parent_scope.module = module;
             }
 
             // These items live in the value namespace.
             ItemKind::Const(box ConstItem { ident, .. })
             | ItemKind::Delegation(box Delegation { ident, .. })
             | ItemKind::Static(box StaticItem { ident, .. }) => {
-                self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
+                self.r.define(parent, ident, ValueNS, res, vis, sp, expansion);
             }
             ItemKind::Fn(box Fn { ident, .. }) => {
-                self.r.define(parent, ident, ValueNS, (res, vis, sp, expansion));
+                self.r.define(parent, ident, ValueNS, res, vis, sp, expansion);
 
                 // Functions introducing procedural macros reserve a slot
                 // in the macro namespace as well (see #52225).
@@ -810,19 +784,19 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
 
             // These items live in the type namespace.
             ItemKind::TyAlias(box TyAlias { ident, .. }) | ItemKind::TraitAlias(ident, ..) => {
-                self.r.define(parent, ident, TypeNS, (res, vis, sp, expansion));
+                self.r.define(parent, ident, TypeNS, res, vis, sp, expansion);
             }
 
             ItemKind::Enum(ident, _, _) | ItemKind::Trait(box ast::Trait { ident, .. }) => {
-                let module = self.r.new_module(
+                self.r.define(parent, ident, TypeNS, res, vis, sp, expansion);
+
+                self.parent_scope.module = self.r.new_module(
                     Some(parent),
                     ModuleKind::Def(def_kind, def_id, Some(ident.name)),
                     expansion.to_expn_id(),
                     item.span,
                     parent.no_implicit_prelude,
                 );
-                self.r.define(parent, ident, TypeNS, (module, vis, sp, expansion));
-                self.parent_scope.module = module;
             }
 
             // These items live in both the type and value namespaces.
@@ -844,7 +818,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                     let mut ctor_vis = if vis.is_public()
                         && ast::attr::contains_name(&item.attrs, sym::non_exhaustive)
                     {
-                        ty::Visibility::Restricted(CRATE_DEF_ID)
+                        Visibility::Restricted(CRATE_DEF_ID)
                     } else {
                         vis
                     };
@@ -857,7 +831,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                         // constructor visibility should still be determined correctly.
                         let field_vis = self
                             .try_resolve_visibility(&field.vis, false)
-                            .unwrap_or(ty::Visibility::Public);
+                            .unwrap_or(Visibility::Public);
                         if ctor_vis.is_at_least(field_vis, self.r.tcx) {
                             ctor_vis = field_vis;
                         }
@@ -866,7 +840,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                     let feed = self.r.feed(ctor_node_id);
                     let ctor_def_id = feed.key();
                     let ctor_res = self.res(ctor_def_id);
-                    self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, sp, expansion));
+                    self.r.define(parent, ident, ValueNS, ctor_res, ctor_vis, sp, expansion);
                     self.r.feed_visibility(feed, ctor_vis);
                     // We need the field visibility spans also for the constructor for E0603.
                     self.insert_field_visibilities_local(ctor_def_id.to_def_id(), vdata.fields());
@@ -906,7 +880,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         item: &Item,
         ident: Ident,
         local_def_id: LocalDefId,
-        vis: ty::Visibility,
+        vis: Visibility,
         parent: Module<'ra>,
     ) {
         let sp = item.span;
@@ -930,8 +904,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         }
         .map(|module| {
             let used = self.process_macro_use_imports(item, module);
-            let vis = ty::Visibility::<LocalDefId>::Public;
-            let binding = (module, vis, sp, expansion).to_name_binding(self.r.arenas);
+            let binding = self.r.arenas.new_pub_res_binding(module.res().unwrap(), sp, expansion);
             (used, Some(ModuleOrUniformRoot::Module(module)), binding)
         })
         .unwrap_or((true, None, self.r.dummy_binding));
@@ -988,7 +961,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 );
             }
         }
-        self.r.define(parent, ident, TypeNS, imported_binding);
+        self.r.define_binding(parent, ident, TypeNS, imported_binding);
     }
 
     /// Constructs the reduced graph for one foreign item.
@@ -1005,7 +978,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let parent = self.parent_scope.module;
         let expansion = self.parent_scope.expansion;
         let vis = self.resolve_visibility(&item.vis);
-        self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
+        self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
         self.r.feed_visibility(feed, vis);
     }
 
@@ -1091,7 +1064,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 root_span: span,
                 span,
                 module_path: Vec::new(),
-                vis: ty::Visibility::Restricted(CRATE_DEF_ID),
+                vis: Visibility::Restricted(CRATE_DEF_ID),
             })
         };
 
@@ -1241,11 +1214,11 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             self.r.macro_names.insert(ident);
             let is_macro_export = ast::attr::contains_name(&item.attrs, sym::macro_export);
             let vis = if is_macro_export {
-                ty::Visibility::Public
+                Visibility::Public
             } else {
-                ty::Visibility::Restricted(CRATE_DEF_ID)
+                Visibility::Restricted(CRATE_DEF_ID)
             };
-            let binding = (res, vis, span, expansion).to_name_binding(self.r.arenas);
+            let binding = self.r.arenas.new_res_binding(res, vis.to_def_id(), span, expansion);
             self.r.set_binding_parent_module(binding, parent_scope.module);
             self.r.all_macro_rules.insert(ident.name);
             if is_macro_export {
@@ -1264,7 +1237,7 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 });
                 self.r.import_use_map.insert(import, Used::Other);
                 let import_binding = self.r.import(binding, import);
-                self.r.define(self.r.graph_root, ident, MacroNS, import_binding);
+                self.r.define_binding(self.r.graph_root, ident, MacroNS, import_binding);
             } else {
                 self.r.check_reserved_macro_name(ident, res);
                 self.insert_unused_macro(ident, def_id, item.id);
@@ -1285,14 +1258,14 @@ impl<'a, 'ra, 'tcx> BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
                 // Visibilities must not be resolved non-speculatively twice
                 // and we already resolved this one as a `fn` item visibility.
                 ItemKind::Fn(..) => {
-                    self.try_resolve_visibility(&item.vis, false).unwrap_or(ty::Visibility::Public)
+                    self.try_resolve_visibility(&item.vis, false).unwrap_or(Visibility::Public)
                 }
                 _ => self.resolve_visibility(&item.vis),
             };
             if !vis.is_public() {
                 self.insert_unused_macro(ident, def_id, item.id);
             }
-            self.r.define(module, ident, MacroNS, (res, vis, span, expansion));
+            self.r.define(module, ident, MacroNS, res, vis, span, expansion);
             self.r.feed_visibility(feed, vis);
             self.parent_scope.macro_rules
         }
@@ -1428,7 +1401,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         if ctxt == AssocCtxt::Trait {
             let parent = self.parent_scope.module;
             let expansion = self.parent_scope.expansion;
-            self.r.define(parent, ident, ns, (self.res(def_id), vis, item.span, expansion));
+            self.r.define(parent, ident, ns, self.res(def_id), vis, item.span, expansion);
         } else if !matches!(&item.kind, AssocItemKind::Delegation(deleg) if deleg.from_glob) {
             let impl_def_id = self.r.tcx.local_parent(local_def_id);
             let key = BindingKey::new(ident.normalize_to_macros_2_0(), ns);
@@ -1513,13 +1486,13 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
         let feed = self.r.feed(variant.id);
         let def_id = feed.key();
         let vis = self.resolve_visibility(&variant.vis);
-        self.r.define(parent, ident, TypeNS, (self.res(def_id), vis, variant.span, expn_id));
+        self.r.define(parent, ident, TypeNS, self.res(def_id), vis, variant.span, expn_id);
         self.r.feed_visibility(feed, vis);
 
         // If the variant is marked as non_exhaustive then lower the visibility to within the crate.
         let ctor_vis =
             if vis.is_public() && ast::attr::contains_name(&variant.attrs, sym::non_exhaustive) {
-                ty::Visibility::Restricted(CRATE_DEF_ID)
+                Visibility::Restricted(CRATE_DEF_ID)
             } else {
                 vis
             };
@@ -1529,7 +1502,7 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for BuildReducedGraphVisitor<'a, 'ra, 'tcx> {
             let feed = self.r.feed(ctor_node_id);
             let ctor_def_id = feed.key();
             let ctor_res = self.res(ctor_def_id);
-            self.r.define(parent, ident, ValueNS, (ctor_res, ctor_vis, variant.span, expn_id));
+            self.r.define(parent, ident, ValueNS, ctor_res, ctor_vis, variant.span, expn_id);
             self.r.feed_visibility(feed, ctor_vis);
         }
 
diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs
index 2e870c47f8e..81ee02ac3c7 100644
--- a/compiler/rustc_resolve/src/check_unused.rs
+++ b/compiler/rustc_resolve/src/check_unused.rs
@@ -511,7 +511,7 @@ impl Resolver<'_, '_> {
             for (_key, resolution) in self.resolutions(*module).borrow().iter() {
                 let resolution = resolution.borrow();
 
-                if let Some(binding) = resolution.binding
+                if let Some(binding) = resolution.best_binding()
                     && let NameBindingKind::Import { import, .. } = binding.kind
                     && let ImportKind::Single { id, .. } = import.kind
                 {
diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs
index e2caf632dd2..781e2ce9704 100644
--- a/compiler/rustc_resolve/src/def_collector.rs
+++ b/compiler/rustc_resolve/src/def_collector.rs
@@ -132,6 +132,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> {
                     &self.resolver.tcx.sess,
                     self.resolver.tcx.features(),
                     Vec::new(),
+                    Early { emit_errors: false },
                 );
                 let attrs = parser.parse_attribute_list(
                     &i.attrs,
diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs
index c4ff5770e76..11e4a729ae2 100644
--- a/compiler/rustc_resolve/src/diagnostics.rs
+++ b/compiler/rustc_resolve/src/diagnostics.rs
@@ -1,11 +1,10 @@
-use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::ptr::P;
 use rustc_ast::visit::{self, Visitor};
-use rustc_ast::{
-    self as ast, CRATE_NODE_ID, Crate, ItemKind, MetaItemInner, MetaItemKind, ModKind, NodeId, Path,
-};
+use rustc_ast::{self as ast, CRATE_NODE_ID, Crate, ItemKind, ModKind, NodeId, Path};
 use rustc_ast_pretty::pprust;
-use rustc_attr_data_structures::{self as attr, AttributeKind, Stability, find_attr};
+use rustc_attr_data_structures::{
+    self as attr, AttributeKind, CfgEntry, Stability, StrippedCfgItem, find_attr,
+};
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::unord::{UnordMap, UnordSet};
 use rustc_errors::codes::*;
@@ -233,12 +232,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             return;
         }
 
-        let old_kind = match (ns, old_binding.module()) {
+        let old_kind = match (ns, old_binding.res()) {
             (ValueNS, _) => "value",
             (MacroNS, _) => "macro",
             (TypeNS, _) if old_binding.is_extern_crate() => "extern crate",
-            (TypeNS, Some(module)) if module.is_normal() => "module",
-            (TypeNS, Some(module)) if module.is_trait() => "trait",
+            (TypeNS, Res::Def(DefKind::Mod, _)) => "module",
+            (TypeNS, Res::Def(DefKind::Trait, _)) => "trait",
             (TypeNS, _) => "type",
         };
 
@@ -1320,7 +1319,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 }
 
                 // collect submodules to explore
-                if let Some(module) = name_binding.module() {
+                if let Some(def_id) = name_binding.res().module_like_def_id() {
                     // form the path
                     let mut path_segments = path_segments.clone();
                     path_segments.push(ast::PathSegment::from_ident(ident));
@@ -1340,14 +1339,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
                     if !is_extern_crate_that_also_appears_in_prelude || alias_import {
                         // add the module to the lookup
-                        if seen_modules.insert(module.def_id()) {
+                        if seen_modules.insert(def_id) {
                             if via_import { &mut worklist_via_import } else { &mut worklist }.push(
                                 (
-                                    module,
+                                    this.expect_module(def_id),
                                     path_segments,
                                     child_accessible,
                                     child_doc_visible,
-                                    is_stable && this.is_stable(module.def_id(), name_binding.span),
+                                    is_stable && this.is_stable(def_id, name_binding.span),
                                 ),
                             );
                         }
@@ -1440,7 +1439,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         |(key, name_resolution)| {
                             if key.ns == TypeNS
                                 && key.ident == ident
-                                && let Some(binding) = name_resolution.borrow().binding
+                                && let Some(binding) = name_resolution.borrow().best_binding()
                             {
                                 match binding.res() {
                                     // No disambiguation needed if the identically named item we
@@ -1494,7 +1493,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     return None;
                 };
                 for (_, resolution) in this.resolutions(m).borrow().iter() {
-                    let Some(binding) = resolution.borrow().binding else {
+                    let Some(binding) = resolution.borrow().best_binding() else {
                         continue;
                     };
                     let Res::Def(DefKind::Macro(MacroKind::Derive | MacroKind::Attr), def_id) =
@@ -2095,7 +2094,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                         true, // re-export
                     ));
                 }
-                NameBindingKind::Res(_) | NameBindingKind::Module(_) => {}
+                NameBindingKind::Res(_) => {}
             }
             let first = binding == first_binding;
             let def_span = self.tcx.sess.source_map().guess_head_span(binding.span);
@@ -2307,25 +2306,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     .ok()
                 };
                 if let Some(binding) = binding {
-                    let mut found = |what| {
-                        msg = format!(
-                            "expected {}, found {} `{}` in {}",
-                            ns.descr(),
-                            what,
-                            ident,
-                            parent
-                        )
-                    };
-                    if binding.module().is_some() {
-                        found("module")
-                    } else {
-                        match binding.res() {
-                            // Avoid using TyCtxt::def_kind_descr in the resolver, because it
-                            // indirectly *calls* the resolver, and would cause a query cycle.
-                            Res::Def(kind, id) => found(kind.descr(id)),
-                            _ => found(ns_to_try.descr()),
-                        }
-                    }
+                    msg = format!(
+                        "expected {}, found {} `{ident}` in {parent}",
+                        ns.descr(),
+                        binding.res().descr(),
+                    );
                 };
             }
             (msg, None)
@@ -2860,17 +2845,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             let note = errors::FoundItemConfigureOut { span: ident.span };
             err.subdiagnostic(note);
 
-            if let MetaItemKind::List(nested) = &cfg.kind
-                && let MetaItemInner::MetaItem(meta_item) = &nested[0]
-                && let MetaItemKind::NameValue(feature_name) = &meta_item.kind
-            {
-                let note = errors::ItemWasBehindFeature {
-                    feature: feature_name.symbol,
-                    span: meta_item.span,
-                };
+            if let CfgEntry::NameValue { value: Some((feature, _)), .. } = cfg.0 {
+                let note = errors::ItemWasBehindFeature { feature, span: cfg.1 };
                 err.subdiagnostic(note);
             } else {
-                let note = errors::ItemWasCfgOut { span: cfg.span };
+                let note = errors::ItemWasCfgOut { span: cfg.1 };
                 err.subdiagnostic(note);
             }
         }
diff --git a/compiler/rustc_resolve/src/ident.rs b/compiler/rustc_resolve/src/ident.rs
index 558cbef0014..84d66c15f00 100644
--- a/compiler/rustc_resolve/src/ident.rs
+++ b/compiler/rustc_resolve/src/ident.rs
@@ -3,11 +3,10 @@ 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, ty};
+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::def_id::LocalDefId;
 use rustc_span::hygiene::{ExpnId, ExpnKind, LocalExpnId, MacroKind, SyntaxContext};
 use rustc_span::{Ident, Span, kw, sym};
 use tracing::{debug, instrument};
@@ -20,11 +19,9 @@ use crate::{
     AmbiguityError, AmbiguityErrorMisc, AmbiguityKind, BindingKey, Determinacy, Finalize,
     ImportKind, LexicalScopeBinding, Module, ModuleKind, ModuleOrUniformRoot, NameBinding,
     NameBindingKind, ParentScope, PathResult, PrivacyError, Res, ResolutionError, Resolver, Scope,
-    ScopeSet, Segment, ToNameBinding, Used, Weak, errors,
+    ScopeSet, Segment, Used, Weak, errors,
 };
 
-type Visibility = ty::Visibility<LocalDefId>;
-
 #[derive(Copy, Clone)]
 pub enum UsePrelude {
     No,
@@ -464,13 +461,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             ) {
                                 Ok((Some(ext), _)) => {
                                     if ext.helper_attrs.contains(&ident.name) {
-                                        let binding = (
+                                        let binding = this.arenas.new_pub_res_binding(
                                             Res::NonMacroAttr(NonMacroAttrKind::DeriveHelperCompat),
-                                            Visibility::Public,
                                             derive.span,
                                             LocalExpnId::ROOT,
-                                        )
-                                            .to_name_binding(this.arenas);
+                                        );
                                         result = Ok((binding, Flags::empty()));
                                         break;
                                     }
@@ -875,7 +870,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         // 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.binding, resolution.shadowed_glob]
+        let binding = [resolution.non_glob_binding, resolution.glob_binding]
             .into_iter()
             .find_map(|binding| if binding == ignore_binding { None } else { binding });
 
@@ -883,7 +878,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             return self.finalize_module_binding(
                 ident,
                 binding,
-                resolution.shadowed_glob,
+                if resolution.non_glob_binding.is_some() { resolution.glob_binding } else { None },
                 parent_scope,
                 finalize,
                 shadowing,
@@ -1090,14 +1085,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             let Some(module) = single_import.imported_module.get() else {
                 return true;
             };
-            let ImportKind::Single { source, target, target_bindings, .. } = &single_import.kind
-            else {
+            let ImportKind::Single { source, target, bindings, .. } = &single_import.kind else {
                 unreachable!();
             };
             if source != target {
-                if target_bindings.iter().all(|binding| binding.get().is_none()) {
+                if bindings.iter().all(|binding| binding.get().binding().is_none()) {
                     return true;
-                } else if target_bindings[ns].get().is_none() && binding.is_some() {
+                } else if bindings[ns].get().binding().is_none() && binding.is_some() {
                     return true;
                 }
             }
@@ -1638,11 +1632,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     }
 
                     let maybe_assoc = opt_ns != Some(MacroNS) && PathSource::Type.is_expected(res);
-                    if let Some(next_module) = binding.module() {
-                        if self.mods_with_parse_errors.contains(&next_module.def_id()) {
+                    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(next_module));
+                        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() {
diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs
index 2e81b54b136..9a031ee03e0 100644
--- a/compiler/rustc_resolve/src/imports.rs
+++ b/compiler/rustc_resolve/src/imports.rs
@@ -11,7 +11,8 @@ use rustc_errors::{Applicability, MultiSpan, pluralize, struct_span_code_err};
 use rustc_hir::def::{self, DefKind, PartialRes};
 use rustc_hir::def_id::DefId;
 use rustc_middle::metadata::{ModChild, Reexport};
-use rustc_middle::{span_bug, ty};
+use rustc_middle::span_bug;
+use rustc_middle::ty::Visibility;
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{
     AMBIGUOUS_GLOB_REEXPORTS, HIDDEN_GLOB_REEXPORTS, PUB_USE_OF_PRIVATE_EXTERN_CRATE,
@@ -24,7 +25,6 @@ use rustc_span::{Ident, Span, Symbol, kw, sym};
 use smallvec::SmallVec;
 use tracing::debug;
 
-use crate::Determinacy::{self, *};
 use crate::Namespace::*;
 use crate::diagnostics::{DiagMode, Suggestion, import_candidates};
 use crate::errors::{
@@ -33,13 +33,30 @@ use crate::errors::{
     ConsiderAddingMacroExport, ConsiderMarkingAsPub,
 };
 use crate::{
-    AmbiguityError, AmbiguityKind, BindingKey, Finalize, ImportSuggestion, Module,
+    AmbiguityError, AmbiguityKind, BindingKey, Determinacy, Finalize, ImportSuggestion, Module,
     ModuleOrUniformRoot, NameBinding, NameBindingData, NameBindingKind, ParentScope, PathResult,
     PerNS, ResolutionError, Resolver, ScopeSet, Segment, Used, module_to_string, names_to_string,
 };
 
 type Res = def::Res<NodeId>;
 
+/// A [`NameBinding`] in the process of being resolved.
+#[derive(Clone, Copy, Default, PartialEq)]
+pub(crate) enum PendingBinding<'ra> {
+    Ready(Option<NameBinding<'ra>>),
+    #[default]
+    Pending,
+}
+
+impl<'ra> PendingBinding<'ra> {
+    pub(crate) fn binding(self) -> Option<NameBinding<'ra>> {
+        match self {
+            PendingBinding::Ready(binding) => binding,
+            PendingBinding::Pending => None,
+        }
+    }
+}
+
 /// Contains data for specific kinds of imports.
 #[derive(Clone)]
 pub(crate) enum ImportKind<'ra> {
@@ -49,10 +66,8 @@ pub(crate) enum ImportKind<'ra> {
         /// `target` in `use prefix::source as target`.
         /// It will directly use `source` when the format is `use prefix::source`.
         target: Ident,
-        /// Bindings to which `source` refers to.
-        source_bindings: PerNS<Cell<Result<NameBinding<'ra>, Determinacy>>>,
-        /// Bindings introduced by `target`.
-        target_bindings: PerNS<Cell<Option<NameBinding<'ra>>>>,
+        /// Bindings introduced by the import.
+        bindings: PerNS<Cell<PendingBinding<'ra>>>,
         /// `true` for `...::{self [as target]}` imports, `false` otherwise.
         type_ns_only: bool,
         /// Did this import result from a nested import? ie. `use foo::{bar, baz};`
@@ -74,7 +89,7 @@ pub(crate) enum ImportKind<'ra> {
         is_prelude: bool,
         // The visibility of the greatest re-export.
         // n.b. `max_vis` is only used in `finalize_import` to check for re-export errors.
-        max_vis: Cell<Option<ty::Visibility>>,
+        max_vis: Cell<Option<Visibility>>,
         id: NodeId,
     },
     ExternCrate {
@@ -96,26 +111,14 @@ impl<'ra> std::fmt::Debug for ImportKind<'ra> {
     fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
         use ImportKind::*;
         match self {
-            Single {
-                source,
-                target,
-                source_bindings,
-                target_bindings,
-                type_ns_only,
-                nested,
-                id,
-            } => f
+            Single { source, target, bindings, type_ns_only, nested, id, .. } => f
                 .debug_struct("Single")
                 .field("source", source)
                 .field("target", target)
                 // Ignore the nested bindings to avoid an infinite loop while printing.
                 .field(
-                    "source_bindings",
-                    &source_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
-                )
-                .field(
-                    "target_bindings",
-                    &target_bindings.clone().map(|b| b.into_inner().map(|_| format_args!(".."))),
+                    "bindings",
+                    &bindings.clone().map(|b| b.into_inner().binding().map(|_| format_args!(".."))),
                 )
                 .field("type_ns_only", type_ns_only)
                 .field("nested", nested)
@@ -183,7 +186,7 @@ pub(crate) struct ImportData<'ra> {
     /// |`use ::foo`      | `ModuleOrUniformRoot::CrateRootAndExternPrelude`    | a special case in 2015 edition |
     /// |`use foo`        | `ModuleOrUniformRoot::CurrentScope`                 | - |
     pub imported_module: Cell<Option<ModuleOrUniformRoot<'ra>>>,
-    pub vis: ty::Visibility,
+    pub vis: Visibility,
 }
 
 /// All imports are unique and allocated on a same arena,
@@ -242,15 +245,16 @@ pub(crate) struct NameResolution<'ra> {
     /// Single imports that may define the name in the namespace.
     /// Imports are arena-allocated, so it's ok to use pointers as keys.
     pub single_imports: FxIndexSet<Import<'ra>>,
-    /// The least shadowable known binding for this name, or None if there are no known bindings.
-    pub binding: Option<NameBinding<'ra>>,
-    pub shadowed_glob: Option<NameBinding<'ra>>,
+    /// The non-glob binding for this name, if it is known to exist.
+    pub non_glob_binding: Option<NameBinding<'ra>>,
+    /// The glob binding for this name, if it is known to exist.
+    pub glob_binding: Option<NameBinding<'ra>>,
 }
 
 impl<'ra> NameResolution<'ra> {
     /// Returns the binding for the name if it is known or None if it not known.
     pub(crate) fn binding(&self) -> Option<NameBinding<'ra>> {
-        self.binding.and_then(|binding| {
+        self.best_binding().and_then(|binding| {
             if !binding.is_glob_import() || self.single_imports.is_empty() {
                 Some(binding)
             } else {
@@ -258,6 +262,10 @@ impl<'ra> NameResolution<'ra> {
             }
         })
     }
+
+    pub(crate) fn best_binding(&self) -> Option<NameBinding<'ra>> {
+        self.non_glob_binding.or(self.glob_binding)
+    }
 }
 
 /// An error that may be transformed into a diagnostic later. Used to combine multiple unresolved
@@ -338,69 +346,71 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         self.check_reserved_macro_name(key.ident, res);
         self.set_binding_parent_module(binding, module);
         self.update_resolution(module, key, warn_ambiguity, |this, resolution| {
-            if let Some(old_binding) = resolution.binding {
+            if let Some(old_binding) = resolution.best_binding() {
                 if res == Res::Err && old_binding.res() != Res::Err {
                     // Do not override real bindings with `Res::Err`s from error recovery.
                     return Ok(());
                 }
                 match (old_binding.is_glob_import(), binding.is_glob_import()) {
                     (true, true) => {
+                        let (glob_binding, old_glob_binding) = (binding, old_binding);
                         // FIXME: remove `!binding.is_ambiguity_recursive()` after delete the warning ambiguity.
                         if !binding.is_ambiguity_recursive()
                             && let NameBindingKind::Import { import: old_import, .. } =
-                                old_binding.kind
-                            && let NameBindingKind::Import { import, .. } = binding.kind
+                                old_glob_binding.kind
+                            && let NameBindingKind::Import { import, .. } = glob_binding.kind
                             && old_import == import
                         {
-                            // We should replace the `old_binding` with `binding` regardless
-                            // of whether they has same resolution or not when they are
-                            // imported from the same glob-import statement.
-                            resolution.binding = Some(binding);
-                        } else if res != old_binding.res() {
-                            resolution.binding = Some(this.new_ambiguity_binding(
+                            // When imported from the same glob-import statement, we should replace
+                            // `old_glob_binding` with `glob_binding`, regardless of whether
+                            // they have the same resolution or not.
+                            resolution.glob_binding = Some(glob_binding);
+                        } else if res != old_glob_binding.res() {
+                            resolution.glob_binding = Some(this.new_ambiguity_binding(
                                 AmbiguityKind::GlobVsGlob,
-                                old_binding,
-                                binding,
+                                old_glob_binding,
+                                glob_binding,
                                 warn_ambiguity,
                             ));
                         } else if !old_binding.vis.is_at_least(binding.vis, this.tcx) {
                             // We are glob-importing the same item but with greater visibility.
-                            resolution.binding = Some(binding);
+                            resolution.glob_binding = Some(glob_binding);
                         } else if binding.is_ambiguity_recursive() {
-                            resolution.binding = Some(this.new_warn_ambiguity_binding(binding));
+                            resolution.glob_binding =
+                                Some(this.new_warn_ambiguity_binding(glob_binding));
                         }
                     }
                     (old_glob @ true, false) | (old_glob @ false, true) => {
-                        let (glob_binding, nonglob_binding) =
+                        let (glob_binding, non_glob_binding) =
                             if old_glob { (old_binding, binding) } else { (binding, old_binding) };
                         if key.ns == MacroNS
-                            && nonglob_binding.expansion != LocalExpnId::ROOT
-                            && glob_binding.res() != nonglob_binding.res()
+                            && non_glob_binding.expansion != LocalExpnId::ROOT
+                            && glob_binding.res() != non_glob_binding.res()
                         {
-                            resolution.binding = Some(this.new_ambiguity_binding(
+                            resolution.non_glob_binding = Some(this.new_ambiguity_binding(
                                 AmbiguityKind::GlobVsExpanded,
-                                nonglob_binding,
+                                non_glob_binding,
                                 glob_binding,
                                 false,
                             ));
                         } else {
-                            resolution.binding = Some(nonglob_binding);
+                            resolution.non_glob_binding = Some(non_glob_binding);
                         }
 
-                        if let Some(old_shadowed_glob) = resolution.shadowed_glob {
-                            assert!(old_shadowed_glob.is_glob_import());
-                            if glob_binding.res() != old_shadowed_glob.res() {
-                                resolution.shadowed_glob = Some(this.new_ambiguity_binding(
+                        if let Some(old_glob_binding) = resolution.glob_binding {
+                            assert!(old_glob_binding.is_glob_import());
+                            if glob_binding.res() != old_glob_binding.res() {
+                                resolution.glob_binding = Some(this.new_ambiguity_binding(
                                     AmbiguityKind::GlobVsGlob,
-                                    old_shadowed_glob,
+                                    old_glob_binding,
                                     glob_binding,
                                     false,
                                 ));
-                            } else if !old_shadowed_glob.vis.is_at_least(binding.vis, this.tcx) {
-                                resolution.shadowed_glob = Some(glob_binding);
+                            } else if !old_glob_binding.vis.is_at_least(binding.vis, this.tcx) {
+                                resolution.glob_binding = Some(glob_binding);
                             }
                         } else {
-                            resolution.shadowed_glob = Some(glob_binding);
+                            resolution.glob_binding = Some(glob_binding);
                         }
                     }
                     (false, false) => {
@@ -408,7 +418,11 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     }
                 }
             } else {
-                resolution.binding = Some(binding);
+                if binding.is_glob_import() {
+                    resolution.glob_binding = Some(binding);
+                } else {
+                    resolution.non_glob_binding = Some(binding);
+                }
             }
 
             Ok(())
@@ -491,8 +505,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     // Define a dummy resolution containing a `Res::Err` as a placeholder for a failed
     // or indeterminate resolution, also mark such failed imports as used to avoid duplicate diagnostics.
     fn import_dummy_binding(&mut self, import: Import<'ra>, is_indeterminate: bool) {
-        if let ImportKind::Single { target, ref target_bindings, .. } = import.kind {
-            if !(is_indeterminate || target_bindings.iter().all(|binding| binding.get().is_none()))
+        if let ImportKind::Single { target, ref bindings, .. } = import.kind {
+            if !(is_indeterminate
+                || bindings.iter().all(|binding| binding.get().binding().is_none()))
             {
                 return; // Has resolution, do not create the dummy binding
             }
@@ -567,10 +582,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
             glob_error |= import.is_glob();
 
-            if let ImportKind::Single { source, ref source_bindings, .. } = import.kind
+            if let ImportKind::Single { source, ref bindings, .. } = import.kind
                 && source.name == kw::SelfLower
                 // Silence `unresolved import` error if E0429 is already emitted
-                && let Err(Determined) = source_bindings.value_ns.get()
+                && let PendingBinding::Ready(None) = bindings.value_ns.get()
             {
                 continue;
             }
@@ -628,7 +643,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             for (key, resolution) in self.resolutions(*module).borrow().iter() {
                 let resolution = resolution.borrow();
 
-                let Some(binding) = resolution.binding else { continue };
+                let Some(binding) = resolution.best_binding() else { continue };
 
                 if let NameBindingKind::Import { import, .. } = binding.kind
                     && let Some((amb_binding, _)) = binding.ambiguity
@@ -648,7 +663,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     );
                 }
 
-                if let Some(glob_binding) = resolution.shadowed_glob {
+                if let Some(glob_binding) = resolution.glob_binding
+                    && resolution.non_glob_binding.is_some()
+                {
                     if binding.res() != Res::Err
                         && glob_binding.res() != Res::Err
                         && let NameBindingKind::Import { import: glob_import, .. } =
@@ -663,9 +680,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             NameBindingKind::Res(res) => {
                                 Some(self.def_id_to_node_id(res.def_id().expect_local()))
                             }
-                            NameBindingKind::Module(module) => {
-                                Some(self.def_id_to_node_id(module.def_id().expect_local()))
-                            }
                             NameBindingKind::Import { import, .. } => import.id(),
                         };
                         if let Some(binding_id) = binding_id {
@@ -819,15 +833,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         };
 
         import.imported_module.set(Some(module));
-        let (source, target, source_bindings, target_bindings, type_ns_only) = match import.kind {
-            ImportKind::Single {
-                source,
-                target,
-                ref source_bindings,
-                ref target_bindings,
-                type_ns_only,
-                ..
-            } => (source, target, source_bindings, target_bindings, type_ns_only),
+        let (source, target, bindings, type_ns_only) = match import.kind {
+            ImportKind::Single { source, target, ref bindings, type_ns_only, .. } => {
+                (source, target, bindings, type_ns_only)
+            }
             ImportKind::Glob { .. } => {
                 self.resolve_glob_import(import);
                 return 0;
@@ -838,21 +847,18 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let mut indeterminate_count = 0;
         self.per_ns(|this, ns| {
             if !type_ns_only || ns == TypeNS {
-                if let Err(Undetermined) = source_bindings[ns].get() {
-                    let binding = this.maybe_resolve_ident_in_module(
-                        module,
-                        source,
-                        ns,
-                        &import.parent_scope,
-                        Some(import),
-                    );
-                    source_bindings[ns].set(binding);
-                } else {
+                if bindings[ns].get() != PendingBinding::Pending {
                     return;
                 };
-
+                let binding_result = this.maybe_resolve_ident_in_module(
+                    module,
+                    source,
+                    ns,
+                    &import.parent_scope,
+                    Some(import),
+                );
                 let parent = import.parent_scope.module;
-                match source_bindings[ns].get() {
+                let binding = match binding_result {
                     Ok(binding) => {
                         if binding.is_assoc_item()
                             && !this.tcx.features().import_trait_associated_functions()
@@ -865,12 +871,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             )
                             .emit();
                         }
-
+                        // We need the `target`, `source` can be extracted.
                         let imported_binding = this.import(binding, import);
-                        target_bindings[ns].set(Some(imported_binding));
-                        this.define(parent, target, ns, imported_binding);
+                        this.define_binding(parent, target, ns, imported_binding);
+                        PendingBinding::Ready(Some(imported_binding))
                     }
-                    Err(Determined) => {
+                    Err(Determinacy::Determined) => {
                         // Don't update the resolution for underscores, because it was never added.
                         if target.name != kw::Underscore {
                             let key = BindingKey::new(target, ns);
@@ -878,9 +884,14 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                                 resolution.single_imports.swap_remove(&import);
                             });
                         }
+                        PendingBinding::Ready(None)
                     }
-                    Err(Undetermined) => indeterminate_count += 1,
-                }
+                    Err(Determinacy::Undetermined) => {
+                        indeterminate_count += 1;
+                        PendingBinding::Pending
+                    }
+                };
+                bindings[ns].set(binding);
             }
         });
 
@@ -893,7 +904,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     /// consolidate multiple unresolved import errors into a single diagnostic.
     fn finalize_import(&mut self, import: Import<'ra>) -> Option<UnresolvedImportError> {
         let ignore_binding = match &import.kind {
-            ImportKind::Single { target_bindings, .. } => target_bindings[TypeNS].get(),
+            ImportKind::Single { bindings, .. } => bindings[TypeNS].get().binding(),
             _ => None,
         };
         let ambiguity_errors_len =
@@ -1011,60 +1022,53 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             PathResult::Indeterminate => unreachable!(),
         };
 
-        let (ident, target, source_bindings, target_bindings, type_ns_only, import_id) =
-            match import.kind {
-                ImportKind::Single {
-                    source,
-                    target,
-                    ref source_bindings,
-                    ref target_bindings,
-                    type_ns_only,
-                    id,
-                    ..
-                } => (source, target, source_bindings, target_bindings, type_ns_only, id),
-                ImportKind::Glob { is_prelude, ref max_vis, id } => {
-                    if import.module_path.len() <= 1 {
-                        // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
-                        // 2 segments, so the `resolve_path` above won't trigger it.
-                        let mut full_path = import.module_path.clone();
-                        full_path.push(Segment::from_ident(Ident::dummy()));
-                        self.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
-                    }
+        let (ident, target, bindings, type_ns_only, import_id) = match import.kind {
+            ImportKind::Single { source, target, ref bindings, type_ns_only, id, .. } => {
+                (source, target, bindings, type_ns_only, id)
+            }
+            ImportKind::Glob { is_prelude, ref max_vis, id } => {
+                if import.module_path.len() <= 1 {
+                    // HACK(eddyb) `lint_if_path_starts_with_module` needs at least
+                    // 2 segments, so the `resolve_path` above won't trigger it.
+                    let mut full_path = import.module_path.clone();
+                    full_path.push(Segment::from_ident(Ident::dummy()));
+                    self.lint_if_path_starts_with_module(Some(finalize), &full_path, None);
+                }
 
-                    if let ModuleOrUniformRoot::Module(module) = module
-                        && module == import.parent_scope.module
-                    {
-                        // Importing a module into itself is not allowed.
-                        return Some(UnresolvedImportError {
+                if let ModuleOrUniformRoot::Module(module) = module
+                    && module == import.parent_scope.module
+                {
+                    // Importing a module into itself is not allowed.
+                    return Some(UnresolvedImportError {
+                        span: import.span,
+                        label: Some(String::from("cannot glob-import a module into itself")),
+                        note: None,
+                        suggestion: None,
+                        candidates: None,
+                        segment: None,
+                        module: None,
+                    });
+                }
+                if !is_prelude
+                    && let Some(max_vis) = max_vis.get()
+                    && !max_vis.is_at_least(import.vis, self.tcx)
+                {
+                    let def_id = self.local_def_id(id);
+                    self.lint_buffer.buffer_lint(
+                        UNUSED_IMPORTS,
+                        id,
+                        import.span,
+                        BuiltinLintDiag::RedundantImportVisibility {
+                            max_vis: max_vis.to_string(def_id, self.tcx),
+                            import_vis: import.vis.to_string(def_id, self.tcx),
                             span: import.span,
-                            label: Some(String::from("cannot glob-import a module into itself")),
-                            note: None,
-                            suggestion: None,
-                            candidates: None,
-                            segment: None,
-                            module: None,
-                        });
-                    }
-                    if !is_prelude
-                        && let Some(max_vis) = max_vis.get()
-                        && !max_vis.is_at_least(import.vis, self.tcx)
-                    {
-                        let def_id = self.local_def_id(id);
-                        self.lint_buffer.buffer_lint(
-                            UNUSED_IMPORTS,
-                            id,
-                            import.span,
-                            BuiltinLintDiag::RedundantImportVisibility {
-                                max_vis: max_vis.to_string(def_id, self.tcx),
-                                import_vis: import.vis.to_string(def_id, self.tcx),
-                                span: import.span,
-                            },
-                        );
-                    }
-                    return None;
+                        },
+                    );
                 }
-                _ => unreachable!(),
-            };
+                return None;
+            }
+            _ => unreachable!(),
+        };
 
         if self.privacy_errors.len() != privacy_errors_len {
             // Get the Res for the last element, so that we can point to alternative ways of
@@ -1095,17 +1099,17 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     ns,
                     &import.parent_scope,
                     Some(Finalize { report_private: false, ..finalize }),
-                    target_bindings[ns].get(),
+                    bindings[ns].get().binding(),
                     Some(import),
                 );
 
                 match binding {
                     Ok(binding) => {
                         // Consistency checks, analogous to `finalize_macro_resolutions`.
-                        let initial_res = source_bindings[ns].get().map(|initial_binding| {
+                        let initial_res = bindings[ns].get().binding().map(|binding| {
+                            let initial_binding = binding.import_source();
                             all_ns_err = false;
-                            if let Some(target_binding) = target_bindings[ns].get()
-                                && target.name == kw::Underscore
+                            if target.name == kw::Underscore
                                 && initial_binding.is_extern_crate()
                                 && !initial_binding.is_import()
                             {
@@ -1114,7 +1118,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                                 } else {
                                     Used::Other
                                 };
-                                this.record_use(ident, target_binding, used);
+                                this.record_use(ident, binding, used);
                             }
                             initial_binding.res()
                         });
@@ -1126,7 +1130,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                                 .span_delayed_bug(import.span, "some error happened for an import");
                             return;
                         }
-                        if let Ok(initial_res) = initial_res {
+                        if let Some(initial_res) = initial_res {
                             if res != initial_res {
                                 span_bug!(import.span, "inconsistent resolution for an import");
                             }
@@ -1179,7 +1183,9 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                             return None;
                         } // Never suggest the same name
                         match *resolution.borrow() {
-                            NameResolution { binding: Some(name_binding), .. } => {
+                            ref resolution
+                                if let Some(name_binding) = resolution.best_binding() =>
+                            {
                                 match name_binding.kind {
                                     NameBindingKind::Import { binding, .. } => {
                                         match binding.kind {
@@ -1269,13 +1275,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let mut any_successful_reexport = false;
         let mut crate_private_reexport = false;
         self.per_ns(|this, ns| {
-            let Ok(binding) = source_bindings[ns].get() else {
+            let Some(binding) = bindings[ns].get().binding().map(|b| b.import_source()) else {
                 return;
             };
 
             if !binding.vis.is_at_least(import.vis, this.tcx) {
                 reexport_error = Some((ns, binding));
-                if let ty::Visibility::Restricted(binding_def_id) = binding.vis
+                if let Visibility::Restricted(binding_def_id) = binding.vis
                     && binding_def_id.is_top_level_module()
                 {
                     crate_private_reexport = true;
@@ -1340,7 +1346,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             let mut full_path = import.module_path.clone();
             full_path.push(Segment::from_ident(ident));
             self.per_ns(|this, ns| {
-                if let Ok(binding) = source_bindings[ns].get() {
+                if let Some(binding) = bindings[ns].get().binding().map(|b| b.import_source()) {
                     this.lint_if_path_starts_with_module(Some(finalize), &full_path, Some(binding));
                 }
             });
@@ -1350,7 +1356,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         // this may resolve to either a value or a type, but for documentation
         // purposes it's good enough to just favor one over the other.
         self.per_ns(|this, ns| {
-            if let Ok(binding) = source_bindings[ns].get() {
+            if let Some(binding) = bindings[ns].get().binding().map(|b| b.import_source()) {
                 this.import_res_map.entry(import_id).or_default()[ns] = Some(binding.res());
             }
         });
@@ -1361,10 +1367,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
     pub(crate) fn check_for_redundant_imports(&mut self, import: Import<'ra>) -> bool {
         // This function is only called for single imports.
-        let ImportKind::Single {
-            source, target, ref source_bindings, ref target_bindings, id, ..
-        } = import.kind
-        else {
+        let ImportKind::Single { source, target, ref bindings, id, .. } = import.kind else {
             unreachable!()
         };
 
@@ -1391,7 +1394,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         let mut is_redundant = true;
         let mut redundant_span = PerNS { value_ns: None, type_ns: None, macro_ns: None };
         self.per_ns(|this, ns| {
-            if is_redundant && let Ok(binding) = source_bindings[ns].get() {
+            let binding = bindings[ns].get().binding().map(|b| b.import_source());
+            if is_redundant && let Some(binding) = binding {
                 if binding.res() == Res::Err {
                     return;
                 }
@@ -1402,7 +1406,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                     &import.parent_scope,
                     None,
                     false,
-                    target_bindings[ns].get(),
+                    bindings[ns].get().binding(),
                     None,
                 ) {
                     Ok(other_binding) => {
diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs
index 08629090bb1..3ef98100d09 100644
--- a/compiler/rustc_resolve/src/late.rs
+++ b/compiler/rustc_resolve/src/late.rs
@@ -28,7 +28,7 @@ use rustc_hir::def::{self, CtorKind, DefKind, LifetimeRes, NonMacroAttrKind, Par
 use rustc_hir::def_id::{CRATE_DEF_ID, DefId, LOCAL_CRATE, LocalDefId};
 use rustc_hir::{MissingLifetimeKind, PrimTy, TraitCandidate};
 use rustc_middle::middle::resolve_bound_vars::Set1;
-use rustc_middle::ty::DelegationFnSig;
+use rustc_middle::ty::{DelegationFnSig, Visibility};
 use rustc_middle::{bug, span_bug};
 use rustc_session::config::{CrateType, ResolveDocLinks};
 use rustc_session::lint::{self, BuiltinLintDiag};
@@ -638,8 +638,8 @@ impl PathSource<'_, '_, '_> {
 enum MaybeExported<'a> {
     Ok(NodeId),
     Impl(Option<DefId>),
-    ImplItem(Result<DefId, &'a Visibility>),
-    NestedUse(&'a Visibility),
+    ImplItem(Result<DefId, &'a ast::Visibility>),
+    NestedUse(&'a ast::Visibility),
 }
 
 impl MaybeExported<'_> {
@@ -3437,7 +3437,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
         };
         ident.span.normalize_to_macros_2_0_and_adjust(module.expansion);
         let key = BindingKey::new(ident, ns);
-        let mut binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
+        let mut binding =
+            self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.best_binding());
         debug!(?binding);
         if binding.is_none() {
             // We could not find the trait item in the correct namespace.
@@ -3448,7 +3449,8 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                 _ => ns,
             };
             let key = BindingKey::new(ident, ns);
-            binding = self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.binding);
+            binding =
+                self.r.resolution(module, key).try_borrow().ok().and_then(|r| r.best_binding());
             debug!(?binding);
         }
 
@@ -3461,7 +3463,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> {
                     span,
                     "error should be emitted when an unexpected trait item is used",
                 );
-                rustc_middle::ty::Visibility::Public
+                Visibility::Public
             };
             this.r.feed_visibility(this.r.feed(id), vis);
         };
diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs
index 8114021510e..a4601cb44eb 100644
--- a/compiler/rustc_resolve/src/late/diagnostics.rs
+++ b/compiler/rustc_resolve/src/late/diagnostics.rs
@@ -880,8 +880,10 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
     fn lookup_doc_alias_name(&mut self, path: &[Segment], ns: Namespace) -> Option<(DefId, Ident)> {
         let find_doc_alias_name = |r: &mut Resolver<'ra, '_>, m: Module<'ra>, item_name: Symbol| {
             for resolution in r.resolutions(m).borrow().values() {
-                let Some(did) =
-                    resolution.borrow().binding.and_then(|binding| binding.res().opt_def_id())
+                let Some(did) = resolution
+                    .borrow()
+                    .best_binding()
+                    .and_then(|binding| binding.res().opt_def_id())
                 else {
                     continue;
                 };
@@ -1464,15 +1466,16 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 self.resolve_path(mod_path, None, None)
             {
                 let resolutions = self.r.resolutions(module).borrow();
-                let targets: Vec<_> =
-                    resolutions
-                        .iter()
-                        .filter_map(|(key, resolution)| {
-                            resolution.borrow().binding.map(|binding| binding.res()).and_then(
-                                |res| if filter_fn(res) { Some((key, res)) } else { None },
-                            )
-                        })
-                        .collect();
+                let targets: Vec<_> = resolutions
+                    .iter()
+                    .filter_map(|(key, resolution)| {
+                        resolution
+                            .borrow()
+                            .best_binding()
+                            .map(|binding| binding.res())
+                            .and_then(|res| if filter_fn(res) { Some((key, res)) } else { None })
+                    })
+                    .collect();
                 if let [target] = targets.as_slice() {
                     return Some(TypoSuggestion::single_item_from_ident(target.0.ident, target.1));
                 }
@@ -2305,7 +2308,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
         let targets = resolutions
             .borrow()
             .iter()
-            .filter_map(|(key, res)| res.borrow().binding.map(|binding| (key, binding.res())))
+            .filter_map(|(key, res)| {
+                res.borrow().best_binding().map(|binding| (key, binding.res()))
+            })
             .filter(|(_, res)| match (kind, res) {
                 (AssocItemKind::Const(..), Res::Def(DefKind::AssocConst, _)) => true,
                 (AssocItemKind::Fn(_), Res::Def(DefKind::AssocFn, _)) => true,
@@ -2651,18 +2656,17 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                 if result.is_some() || !name_binding.vis.is_visible_locally() {
                     return;
                 }
-                if let Some(module) = name_binding.module() {
+                if let Some(module_def_id) = name_binding.res().module_like_def_id() {
                     // form the path
                     let mut path_segments = path_segments.clone();
                     path_segments.push(ast::PathSegment::from_ident(ident));
-                    let module_def_id = module.def_id();
                     let doc_visible = doc_visible
                         && (module_def_id.is_local() || !r.tcx.is_doc_hidden(module_def_id));
                     if module_def_id == def_id {
                         let path =
                             Path { span: name_binding.span, segments: path_segments, tokens: None };
                         result = Some((
-                            module,
+                            r.expect_module(module_def_id),
                             ImportSuggestion {
                                 did: Some(def_id),
                                 descr: "module",
@@ -2677,6 +2681,7 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> {
                     } else {
                         // add the module to the lookup
                         if seen_modules.insert(module_def_id) {
+                            let module = r.expect_module(module_def_id);
                             worklist.push((module, path_segments, doc_visible));
                         }
                     }
diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs
index 6e4c5ef1909..b0b29bc2eae 100644
--- a/compiler/rustc_resolve/src/lib.rs
+++ b/compiler/rustc_resolve/src/lib.rs
@@ -36,12 +36,12 @@ use late::{
 };
 use macros::{MacroRulesBinding, MacroRulesScope, MacroRulesScopeRef};
 use rustc_arena::{DroplessArena, TypedArena};
-use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::node_id::NodeMap;
 use rustc_ast::{
     self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, Expr, ExprKind, GenericArg, GenericArgs,
     LitKind, NodeId, Path, attr,
 };
+use rustc_attr_data_structures::StrippedCfgItem;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet};
 use rustc_data_structures::intern::Interned;
 use rustc_data_structures::steal::Steal;
@@ -65,7 +65,7 @@ use rustc_middle::query::Providers;
 use rustc_middle::span_bug;
 use rustc_middle::ty::{
     self, DelegationFnSig, Feed, MainDefinition, RegisteredTools, ResolverGlobalCtxt,
-    ResolverOutputs, TyCtxt, TyCtxtFeed,
+    ResolverOutputs, TyCtxt, TyCtxtFeed, Visibility,
 };
 use rustc_query_system::ich::StableHashingContext;
 use rustc_session::lint::builtin::PRIVATE_MACRO_USE;
@@ -579,7 +579,7 @@ struct ModuleData<'ra> {
     globs: RefCell<Vec<Import<'ra>>>,
 
     /// Used to memoize the traits in this module for faster searches through all traits in scope.
-    traits: RefCell<Option<Box<[(Ident, NameBinding<'ra>)]>>>,
+    traits: RefCell<Option<Box<[(Ident, NameBinding<'ra>, Option<Module<'ra>>)]>>>,
 
     /// Span of the module itself. Used for error reporting.
     span: Span,
@@ -641,7 +641,7 @@ impl<'ra> Module<'ra> {
         F: FnMut(&mut R, Ident, Namespace, NameBinding<'ra>),
     {
         for (key, name_resolution) in resolver.as_mut().resolutions(self).borrow().iter() {
-            if let Some(binding) = name_resolution.borrow().binding {
+            if let Some(binding) = name_resolution.borrow().best_binding() {
                 f(resolver, key.ident, key.ns, binding);
             }
         }
@@ -655,12 +655,12 @@ impl<'ra> Module<'ra> {
         let mut traits = self.traits.borrow_mut();
         if traits.is_none() {
             let mut collected_traits = Vec::new();
-            self.for_each_child(resolver, |_, name, ns, binding| {
+            self.for_each_child(resolver, |r, name, ns, binding| {
                 if ns != TypeNS {
                     return;
                 }
-                if let Res::Def(DefKind::Trait | DefKind::TraitAlias, _) = binding.res() {
-                    collected_traits.push((name, binding))
+                if let Res::Def(DefKind::Trait | DefKind::TraitAlias, def_id) = binding.res() {
+                    collected_traits.push((name, binding, r.as_mut().get_module(def_id)))
                 }
             });
             *traits = Some(collected_traits.into_boxed_slice());
@@ -674,7 +674,6 @@ impl<'ra> Module<'ra> {
         }
     }
 
-    // Public for rustdoc.
     fn def_id(self) -> DefId {
         self.opt_def_id().expect("`ModuleData::def_id` is called on a block module")
     }
@@ -749,7 +748,7 @@ struct NameBindingData<'ra> {
     warn_ambiguity: bool,
     expansion: LocalExpnId,
     span: Span,
-    vis: ty::Visibility<DefId>,
+    vis: Visibility<DefId>,
 }
 
 /// All name bindings are unique and allocated on a same arena,
@@ -769,20 +768,9 @@ impl std::hash::Hash for NameBindingData<'_> {
     }
 }
 
-trait ToNameBinding<'ra> {
-    fn to_name_binding(self, arenas: &'ra ResolverArenas<'ra>) -> NameBinding<'ra>;
-}
-
-impl<'ra> ToNameBinding<'ra> for NameBinding<'ra> {
-    fn to_name_binding(self, _: &'ra ResolverArenas<'ra>) -> NameBinding<'ra> {
-        self
-    }
-}
-
 #[derive(Clone, Copy, Debug)]
 enum NameBindingKind<'ra> {
     Res(Res),
-    Module(Module<'ra>),
     Import { binding: NameBinding<'ra>, import: Import<'ra> },
 }
 
@@ -875,19 +863,17 @@ struct AmbiguityError<'ra> {
 }
 
 impl<'ra> NameBindingData<'ra> {
-    fn module(&self) -> Option<Module<'ra>> {
+    fn res(&self) -> Res {
         match self.kind {
-            NameBindingKind::Module(module) => Some(module),
-            NameBindingKind::Import { binding, .. } => binding.module(),
-            _ => None,
+            NameBindingKind::Res(res) => res,
+            NameBindingKind::Import { binding, .. } => binding.res(),
         }
     }
 
-    fn res(&self) -> Res {
+    fn import_source(&self) -> NameBinding<'ra> {
         match self.kind {
-            NameBindingKind::Res(res) => res,
-            NameBindingKind::Module(module) => module.res().unwrap(),
-            NameBindingKind::Import { binding, .. } => binding.res(),
+            NameBindingKind::Import { binding, .. } => binding,
+            _ => unreachable!(),
         }
     }
 
@@ -914,7 +900,7 @@ impl<'ra> NameBindingData<'ra> {
                 DefKind::Variant | DefKind::Ctor(CtorOf::Variant, ..),
                 _,
             )) => true,
-            NameBindingKind::Res(..) | NameBindingKind::Module(..) => false,
+            NameBindingKind::Res(..) => false,
         }
     }
 
@@ -923,11 +909,7 @@ impl<'ra> NameBindingData<'ra> {
             NameBindingKind::Import { import, .. } => {
                 matches!(import.kind, ImportKind::ExternCrate { .. })
             }
-            NameBindingKind::Module(module)
-                if let ModuleKind::Def(DefKind::Mod, def_id, _) = module.kind =>
-            {
-                def_id.is_crate_root()
-            }
+            NameBindingKind::Res(Res::Def(_, def_id)) => def_id.is_crate_root(),
             _ => false,
         }
     }
@@ -1101,7 +1083,7 @@ pub struct Resolver<'ra, 'tcx> {
     /// Maps glob imports to the names of items actually imported.
     glob_map: FxIndexMap<LocalDefId, FxIndexSet<Symbol>>,
     glob_error: Option<ErrorGuaranteed>,
-    visibilities_for_hashing: Vec<(LocalDefId, ty::Visibility)>,
+    visibilities_for_hashing: Vec<(LocalDefId, Visibility)>,
     used_imports: FxHashSet<NodeId>,
     maybe_unused_trait_imports: FxIndexSet<LocalDefId>,
 
@@ -1174,7 +1156,7 @@ pub struct Resolver<'ra, 'tcx> {
     /// Table for mapping struct IDs into struct constructor IDs,
     /// it's not used during normal resolution, only for better error reporting.
     /// Also includes of list of each fields visibility
-    struct_constructors: LocalDefIdMap<(Res, ty::Visibility<DefId>, Vec<ty::Visibility<DefId>>)>,
+    struct_constructors: LocalDefIdMap<(Res, Visibility<DefId>, Vec<Visibility<DefId>>)>,
 
     lint_buffer: LintBuffer,
 
@@ -1248,6 +1230,32 @@ pub struct ResolverArenas<'ra> {
 }
 
 impl<'ra> ResolverArenas<'ra> {
+    fn new_res_binding(
+        &'ra self,
+        res: Res,
+        vis: Visibility<DefId>,
+        span: Span,
+        expansion: LocalExpnId,
+    ) -> NameBinding<'ra> {
+        self.alloc_name_binding(NameBindingData {
+            kind: NameBindingKind::Res(res),
+            ambiguity: None,
+            warn_ambiguity: false,
+            vis,
+            span,
+            expansion,
+        })
+    }
+
+    fn new_pub_res_binding(
+        &'ra self,
+        res: Res,
+        span: Span,
+        expn_id: LocalExpnId,
+    ) -> NameBinding<'ra> {
+        self.new_res_binding(res, Visibility::Public, span, expn_id)
+    }
+
     fn new_module(
         &'ra self,
         parent: Option<Module<'ra>>,
@@ -1271,8 +1279,8 @@ impl<'ra> ResolverArenas<'ra> {
         }
         if let Some(def_id) = def_id {
             module_map.insert(def_id, module);
-            let vis = ty::Visibility::<DefId>::Public;
-            let binding = (module, vis, module.span, LocalExpnId::ROOT).to_name_binding(self);
+            let res = module.res().unwrap();
+            let binding = self.new_pub_res_binding(res, module.span, LocalExpnId::ROOT);
             module_self_bindings.insert(module, binding);
         }
         module
@@ -1463,8 +1471,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         }
 
         let registered_tools = tcx.registered_tools(());
-
-        let pub_vis = ty::Visibility::<DefId>::Public;
         let edition = tcx.sess.edition();
 
         let mut resolver = Resolver {
@@ -1513,12 +1519,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             macro_expanded_macro_export_errors: BTreeSet::new(),
 
             arenas,
-            dummy_binding: (Res::Err, pub_vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(arenas),
+            dummy_binding: arenas.new_pub_res_binding(Res::Err, DUMMY_SP, LocalExpnId::ROOT),
             builtin_types_bindings: PrimTy::ALL
                 .iter()
                 .map(|prim_ty| {
-                    let binding = (Res::PrimTy(*prim_ty), pub_vis, DUMMY_SP, LocalExpnId::ROOT)
-                        .to_name_binding(arenas);
+                    let res = Res::PrimTy(*prim_ty);
+                    let binding = arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
                     (prim_ty.name(), binding)
                 })
                 .collect(),
@@ -1526,16 +1532,15 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 .iter()
                 .map(|builtin_attr| {
                     let res = Res::NonMacroAttr(NonMacroAttrKind::Builtin(builtin_attr.name));
-                    let binding =
-                        (res, pub_vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(arenas);
+                    let binding = arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT);
                     (builtin_attr.name, binding)
                 })
                 .collect(),
             registered_tool_bindings: registered_tools
                 .iter()
                 .map(|ident| {
-                    let binding = (Res::ToolMod, pub_vis, ident.span, LocalExpnId::ROOT)
-                        .to_name_binding(arenas);
+                    let res = Res::ToolMod;
+                    let binding = arenas.new_pub_res_binding(res, ident.span, LocalExpnId::ROOT);
                     (*ident, binding)
                 })
                 .collect(),
@@ -1598,7 +1603,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
 
         let root_parent_scope = ParentScope::module(graph_root, &resolver);
         resolver.invocation_parent_scopes.insert(LocalExpnId::ROOT, root_parent_scope);
-        resolver.feed_visibility(crate_feed, ty::Visibility::Public);
+        resolver.feed_visibility(crate_feed, Visibility::Public);
 
         resolver
     }
@@ -1652,7 +1657,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         Default::default()
     }
 
-    fn feed_visibility(&mut self, feed: Feed<'tcx, LocalDefId>, vis: ty::Visibility) {
+    fn feed_visibility(&mut self, feed: Feed<'tcx, LocalDefId>, vis: Visibility) {
         let feed = feed.upgrade(self.tcx);
         feed.visibility(vis.to_def_id());
         self.visibilities_for_hashing.push((feed.def_id(), vis));
@@ -1830,10 +1835,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
     ) {
         module.ensure_traits(self);
         let traits = module.traits.borrow();
-        for (trait_name, trait_binding) in traits.as_ref().unwrap().iter() {
-            if self.trait_may_have_item(trait_binding.module(), assoc_item) {
+        for &(trait_name, trait_binding, trait_module) in traits.as_ref().unwrap().iter() {
+            if self.trait_may_have_item(trait_module, assoc_item) {
                 let def_id = trait_binding.res().def_id();
-                let import_ids = self.find_transitive_imports(&trait_binding.kind, *trait_name);
+                let import_ids = self.find_transitive_imports(&trait_binding.kind, trait_name);
                 found_traits.push(TraitCandidate { def_id, import_ids });
             }
         }
@@ -2103,11 +2108,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
         self.pat_span_map.insert(node, span);
     }
 
-    fn is_accessible_from(
-        &self,
-        vis: ty::Visibility<impl Into<DefId>>,
-        module: Module<'ra>,
-    ) -> bool {
+    fn is_accessible_from(&self, vis: Visibility<impl Into<DefId>>, module: Module<'ra>) -> bool {
         vis.is_accessible_from(module.nearest_parent_mod(), self.tcx)
     }
 
@@ -2167,9 +2168,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
                 } else {
                     self.crate_loader(|c| c.maybe_process_path_extern(ident.name))?
                 };
-                let crate_root = self.expect_module(crate_id.as_def_id());
-                let vis = ty::Visibility::<DefId>::Public;
-                (crate_root, vis, DUMMY_SP, LocalExpnId::ROOT).to_name_binding(self.arenas)
+                let res = Res::Def(DefKind::Mod, crate_id.as_def_id());
+                self.arenas.new_pub_res_binding(res, DUMMY_SP, LocalExpnId::ROOT)
             })
         });
 
diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs
index 89bbe8dad98..c17d74659db 100644
--- a/compiler/rustc_resolve/src/macros.rs
+++ b/compiler/rustc_resolve/src/macros.rs
@@ -5,10 +5,9 @@ use std::cell::Cell;
 use std::mem;
 use std::sync::Arc;
 
-use rustc_ast::expand::StrippedCfgItem;
 use rustc_ast::{self as ast, Crate, NodeId, attr};
 use rustc_ast_pretty::pprust;
-use rustc_attr_data_structures::StabilityLevel;
+use rustc_attr_data_structures::{CfgEntry, StabilityLevel, StrippedCfgItem};
 use rustc_errors::{Applicability, DiagCtxtHandle, StashKey};
 use rustc_expand::base::{
     Annotatable, DeriveResolution, Indeterminate, ResolverExpand, SyntaxExtension,
@@ -21,10 +20,10 @@ use rustc_expand::expand::{
 use rustc_hir::def::{self, DefKind, Namespace, NonMacroAttrKind};
 use rustc_hir::def_id::{CrateNum, DefId, LocalDefId};
 use rustc_middle::middle::stability;
-use rustc_middle::ty::{RegisteredTools, TyCtxt, Visibility};
+use rustc_middle::ty::{RegisteredTools, TyCtxt};
 use rustc_session::lint::BuiltinLintDiag;
 use rustc_session::lint::builtin::{
-    LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+    LEGACY_DERIVE_HELPERS, OUT_OF_SCOPE_MACRO_CALLS, UNKNOWN_DIAGNOSTIC_ATTRIBUTES,
     UNUSED_MACRO_RULES, UNUSED_MACROS,
 };
 use rustc_session::parse::feature_err;
@@ -42,7 +41,7 @@ use crate::imports::Import;
 use crate::{
     BindingKey, DeriveData, Determinacy, Finalize, InvocationParent, MacroData, ModuleKind,
     ModuleOrUniformRoot, NameBinding, NameBindingKind, ParentScope, PathResult, ResolutionError,
-    Resolver, ScopeSet, Segment, ToNameBinding, Used,
+    Resolver, ScopeSet, Segment, Used,
 };
 
 type Res = def::Res<NodeId>;
@@ -437,8 +436,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
             .iter()
             .map(|(_, ident)| {
                 let res = Res::NonMacroAttr(NonMacroAttrKind::DeriveHelper);
-                let binding = (res, Visibility::<DefId>::Public, ident.span, expn_id)
-                    .to_name_binding(self.arenas);
+                let binding = self.arenas.new_pub_res_binding(res, ident.span, expn_id);
                 (*ident, binding)
             })
             .collect();
@@ -485,8 +483,18 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> {
         self.proc_macros.push(self.local_def_id(id))
     }
 
-    fn append_stripped_cfg_item(&mut self, parent_node: NodeId, ident: Ident, cfg: ast::MetaItem) {
-        self.stripped_cfg_items.push(StrippedCfgItem { parent_module: parent_node, ident, cfg });
+    fn append_stripped_cfg_item(
+        &mut self,
+        parent_node: NodeId,
+        ident: Ident,
+        cfg: CfgEntry,
+        cfg_span: Span,
+    ) {
+        self.stripped_cfg_items.push(StrippedCfgItem {
+            parent_module: parent_node,
+            ident,
+            cfg: (cfg, cfg_span),
+        });
     }
 
     fn registered_tools(&self) -> &RegisteredTools {
@@ -689,7 +697,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> {
             );
 
             self.tcx.sess.psess.buffer_lint(
-                UNKNOWN_OR_MALFORMED_DIAGNOSTIC_ATTRIBUTES,
+                UNKNOWN_DIAGNOSTIC_ATTRIBUTES,
                 attribute.span(),
                 node_id,
                 BuiltinLintDiag::UnknownDiagnosticAttribute { span: attribute.span(), typo_name },