From 1c2fe35629cbf2138ed80337aac0ab5af48788ae Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 2 Jun 2026 13:59:11 +0200 Subject: [PATCH 1/2] Track trait map per-owner --- compiler/rustc_ast_lowering/src/lib.rs | 6 +++--- compiler/rustc_middle/src/ty/mod.rs | 12 ++++++------ compiler/rustc_resolve/src/late.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 8 +++----- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 4045f08c053ed..9f6aad45c327a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -126,7 +126,7 @@ struct LoweringContext<'a, 'hir> { is_in_dyn_type: bool, current_hir_id_owner: hir::OwnerId, - owner: &'a PerOwnerResolverData, + owner: &'a PerOwnerResolverData<'hir>, item_local_id_counter: hir::ItemLocalId, trait_map: ItemLocalMap<&'hir [TraitCandidate<'hir>]>, @@ -810,8 +810,8 @@ impl<'hir> LoweringContext<'_, 'hir> { self.children.push((def_id, hir::MaybeOwner::NonOwner(hir_id))); } - if let Some(traits) = self.resolver.trait_map.get(&ast_node_id) { - self.trait_map.insert(hir_id.local_id, &traits[..]); + if let Some(traits) = self.owner.trait_map.get(&ast_node_id) { + self.trait_map.insert(hir_id.local_id, *traits); } // Check whether the same `NodeId` is lowered more than once. diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 6df1ed82d260a..db02b720b5e9a 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -204,7 +204,7 @@ pub struct ResolverGlobalCtxt { } #[derive(Debug)] -pub struct PerOwnerResolverData { +pub struct PerOwnerResolverData<'tcx> { pub node_id_to_def_id: NodeMap = Default::default(), /// Whether lifetime elision was successful. pub lifetime_elision_allowed: bool = false, @@ -214,14 +214,16 @@ pub struct PerOwnerResolverData { /// Resolutions for lifetimes. pub lifetimes_res_map: NodeMap = Default::default(), + pub trait_map: NodeMap<&'tcx [hir::TraitCandidate<'tcx>]> = Default::default(), + /// The id of the owner pub id: ast::NodeId, /// The `DefId` of the owner, can't be found in `node_id_to_def_id`. pub def_id: LocalDefId, } -impl PerOwnerResolverData { - pub fn new(id: ast::NodeId, def_id: LocalDefId) -> PerOwnerResolverData { +impl<'tcx> PerOwnerResolverData<'tcx> { + pub fn new(id: ast::NodeId, def_id: LocalDefId) -> PerOwnerResolverData<'tcx> { PerOwnerResolverData { id, def_id, .. } } @@ -249,9 +251,7 @@ pub struct ResolverAstLowering<'tcx> { pub next_node_id: ast::NodeId, - pub owners: NodeMap, - - pub trait_map: NodeMap<&'tcx [hir::TraitCandidate<'tcx>]>, + pub owners: NodeMap>, /// Lints that were emitted by the resolver and early lints. pub lint_buffer: Steal, diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 58899ffd53ab9..9e2cfa57e5809 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -5388,7 +5388,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ident.span, Some((ident.name, ValueNS)), ); - self.r.trait_map.insert(node_id, traits); + self.r.current_owner.trait_map.insert(node_id, traits); } fn resolve_and_cache_rustdoc_path(&mut self, path_str: &str, ns: Namespace) -> Option { diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index ffb2181bae3a9..712e9d4b5317f 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1375,7 +1375,6 @@ pub struct Resolver<'ra, 'tcx> { extern_crate_map: UnordMap = Default::default(), module_children: LocalDefIdMap> = Default::default(), ambig_module_children: LocalDefIdMap> = Default::default(), - trait_map: NodeMap<&'tcx [TraitCandidate<'tcx>]> = Default::default(), /// A map from nodes to anonymous modules. /// Anonymous modules are pseudo-modules that are implicitly created around items @@ -1490,10 +1489,10 @@ pub struct Resolver<'ra, 'tcx> { next_node_id: NodeId = CRATE_NODE_ID, /// Preserves per owner data once the owner is finished resolving. - owners: NodeMap, + owners: NodeMap>, /// An entry of `owners` that gets taken out and reinserted whenever an owner is handled. - current_owner: PerOwnerResolverData, + current_owner: PerOwnerResolverData<'tcx>, disambiguators: LocalDefIdMap, @@ -2001,7 +2000,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { extra_lifetime_params_map: self.extra_lifetime_params_map, next_node_id: self.next_node_id, owners: self.owners, - trait_map: self.trait_map, lint_buffer: Steal::new(self.lint_buffer), delegation_infos: self.delegation_infos, disambiguators, @@ -2658,7 +2656,7 @@ fn with_owner<'ra, 'tcx, R: AsMut>, T>( fn with_owner_tables<'ra, 'tcx, R: AsMut>, T>( this: &mut R, owner: NodeId, - tables: PerOwnerResolverData, + tables: PerOwnerResolverData<'tcx>, work: impl FnOnce(&mut R) -> T, ) -> T { debug_assert!(!this.as_mut().owners.contains_key(&owner)); From 3fbaefd86287b7a25438afc6963d27b2ab22a619 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 2 Jun 2026 16:57:49 +0200 Subject: [PATCH 2/2] Track import map per-owner --- compiler/rustc_ast_lowering/src/lib.rs | 9 ++------- compiler/rustc_hir/src/def.rs | 3 ++- compiler/rustc_middle/src/ty/mod.rs | 7 ++++--- compiler/rustc_resolve/src/check_unused.rs | 10 ++++------ compiler/rustc_resolve/src/imports.rs | 2 +- compiler/rustc_resolve/src/lib.rs | 3 --- 6 files changed, 13 insertions(+), 21 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 9f6aad45c327a..c861b17c00c6f 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -288,11 +288,6 @@ impl<'tcx> ResolverAstLowering<'tcx> { .map(|fn_indexes| fn_indexes.iter().map(|(num, _)| *num).collect()) } - /// Obtains per-namespace resolutions for `use` statement with the given `NodeId`. - fn get_import_res(&self, id: NodeId) -> PerNS>> { - self.import_res_map.get(&id).copied().unwrap_or_default() - } - /// Obtain the list of lifetimes parameters to add to an item. /// /// Extra lifetime parameters should only be added in places that can appear @@ -856,8 +851,8 @@ impl<'hir> LoweringContext<'_, 'hir> { } fn lower_import_res(&mut self, id: NodeId, span: Span) -> PerNS> { - let per_ns = self.resolver.get_import_res(id); - let per_ns = per_ns.map(|res| res.map(|res| self.lower_res(res))); + debug_assert_eq!(id, self.owner.id); + let per_ns = self.owner.import_res.map(|res| res.map(|res| self.lower_res(res))); if per_ns.is_empty() { // Propagate the error to all namespaces, just to be sure. self.dcx().span_delayed_bug(span, "no resolution for an import"); diff --git a/compiler/rustc_hir/src/def.rs b/compiler/rustc_hir/src/def.rs index d275d5a28b88a..e473db48b04c2 100644 --- a/compiler/rustc_hir/src/def.rs +++ b/compiler/rustc_hir/src/def.rs @@ -717,7 +717,8 @@ impl IntoDiagArg for Namespace { } /// Just a helper ‒ separate structure for each namespace. -#[derive(Copy, Clone, Default, Debug, StableHash)] +#[derive(Copy, Clone, Debug, StableHash)] +#[derive_const(Default)] pub struct PerNS { pub value_ns: T, pub type_ns: T, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index db02b720b5e9a..d65f14e50db3d 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -27,9 +27,9 @@ pub use intrinsic::IntrinsicDef; use rustc_abi::{ Align, FieldIdx, Integer, IntegerType, ReprFlags, ReprOptions, ScalableElt, VariantIdx, }; -use rustc_ast as ast; use rustc_ast::expand::typetree::{FncTree, Kind, Type, TypeTree}; use rustc_ast::node_id::NodeMap; +use rustc_ast::{self as ast}; pub use rustc_ast_ir::{Movability, Mutability, try_visit}; use rustc_data_structures::fx::{FxIndexMap, FxIndexSet}; use rustc_data_structures::intern::Interned; @@ -216,6 +216,9 @@ pub struct PerOwnerResolverData<'tcx> { pub trait_map: NodeMap<&'tcx [hir::TraitCandidate<'tcx>]> = Default::default(), + /// Resolution for import nodes, which have multiple resolutions in different namespaces. + pub import_res: hir::def::PerNS>> = Default::default(), + /// The id of the owner pub id: ast::NodeId, /// The `DefId` of the owner, can't be found in `node_id_to_def_id`. @@ -244,8 +247,6 @@ impl<'tcx> PerOwnerResolverData<'tcx> { pub struct ResolverAstLowering<'tcx> { /// Resolutions for nodes that have a single resolution. pub partial_res_map: NodeMap, - /// Resolutions for import nodes, which have multiple resolutions in different namespaces. - pub import_res_map: NodeMap>>>, /// Lifetime parameters that lowering will have to introduce. pub extra_lifetime_params_map: NodeMap>, diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 84221cb8c2d5e..131b16d416ca9 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -134,12 +134,10 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { match item.kind { ast::UseTreeKind::Simple(Some(ident)) => { if ident.name == kw::Underscore - && !self.r.import_res_map.get(&id).is_some_and(|per_ns| { - matches!( - per_ns.type_ns, - Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) - ) - }) + && !matches!( + self.r.owners[&id].import_res.type_ns, + Some(Res::Def(DefKind::Trait | DefKind::TraitAlias, _)) + ) { self.unused_import(self.base_id).add(id); } diff --git a/compiler/rustc_resolve/src/imports.rs b/compiler/rustc_resolve/src/imports.rs index c95799758cd59..46cc163ca8ed2 100644 --- a/compiler/rustc_resolve/src/imports.rs +++ b/compiler/rustc_resolve/src/imports.rs @@ -1642,7 +1642,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { // purposes it's good enough to just favor one over the other. self.per_ns(|this, ns| { if let Some(binding) = bindings[ns].get().decl().map(|b| b.import_source()) { - this.import_res_map.entry(import_id).or_default()[ns] = Some(binding.res()); + this.owners.get_mut(&import_id).unwrap().import_res[ns] = Some(binding.res()); } }); diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 712e9d4b5317f..60978cf2ee936 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -1364,8 +1364,6 @@ pub struct Resolver<'ra, 'tcx> { /// Resolutions for nodes that have a single resolution. partial_res_map: NodeMap = Default::default(), - /// Resolutions for import nodes, which have multiple resolutions in different namespaces. - import_res_map: NodeMap>> = Default::default(), /// An import will be inserted into this map if it has been used. import_use_map: FxHashMap, Used> = default::fx_hash_map(), /// Lifetime parameters that lowering will have to introduce. @@ -1996,7 +1994,6 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { }; let ast_lowering = ty::ResolverAstLowering { partial_res_map: self.partial_res_map, - import_res_map: self.import_res_map, extra_lifetime_params_map: self.extra_lifetime_params_map, next_node_id: self.next_node_id, owners: self.owners,