From 1887b9cd74c7a08ac5e7969449a5ce0edad86de2 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 24 Mar 2025 14:39:35 +0000 Subject: [PATCH 1/4] Split trait item resolving into its own method --- compiler/rustc_resolve/src/late.rs | 156 ++++++++++++++--------------- 1 file changed, 78 insertions(+), 78 deletions(-) diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index e8bd3abdc621e..f18fc7e6feca5 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -3321,6 +3321,14 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { let trait_assoc_items = replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items)); + for item in trait_items { + self.resolve_trait_item(item); + } + + self.diag_metadata.current_trait_assoc_items = trait_assoc_items; + } + + fn resolve_trait_item(&mut self, item: &'ast Item) { let walk_assoc_item = |this: &mut Self, generics: &Generics, kind, item: &'ast AssocItem| { this.with_generic_param_rib( @@ -3333,87 +3341,79 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { ); }; - for item in trait_items { - self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); - match &item.kind { - AssocItemKind::Const(ast::ConstItem { - generics, - ty, - rhs_kind, - define_opaque, - .. - }) => { - self.with_generic_param_rib( - &generics.params, - RibKind::AssocItem, - item.id, - LifetimeBinderKind::ConstItem, - generics.span, - |this| { - this.with_lifetime_rib( - LifetimeRibKind::StaticIfNoLifetimeInScope { - lint_id: item.id, - emit_lint: false, - }, - |this| { - this.visit_generics(generics); - if rhs_kind.is_type_const() - && !this.r.tcx.features().generic_const_parameter_types() - { - this.with_rib(TypeNS, RibKind::ConstParamTy, |this| { - this.with_rib(ValueNS, RibKind::ConstParamTy, |this| { - this.with_lifetime_rib( - LifetimeRibKind::ConstParamTy, - |this| this.visit_ty(ty), - ) - }) - }); - } else { - this.visit_ty(ty); - } - - // Only impose the restrictions of `ConstRibKind` for an - // actual constant expression in a provided default. - // - // We allow arbitrary const expressions inside of associated consts, - // even if they are potentially not const evaluatable. - // - // Type parameters can already be used and as associated consts are - // not used as part of the type system, this is far less surprising. - this.resolve_const_item_rhs(rhs_kind, None); - }, - ) - }, - ); + self.resolve_doc_links(&item.attrs, MaybeExported::Ok(item.id)); + match &item.kind { + AssocItemKind::Const(ast::ConstItem { + generics, ty, rhs_kind, define_opaque, .. + }) => { + self.with_generic_param_rib( + &generics.params, + RibKind::AssocItem, + item.id, + LifetimeBinderKind::ConstItem, + generics.span, + |this| { + this.with_lifetime_rib( + LifetimeRibKind::StaticIfNoLifetimeInScope { + lint_id: item.id, + emit_lint: false, + }, + |this| { + this.visit_generics(generics); + if rhs_kind.is_type_const() + && !this.r.tcx.features().generic_const_parameter_types() + { + this.with_rib(TypeNS, RibKind::ConstParamTy, |this| { + this.with_rib(ValueNS, RibKind::ConstParamTy, |this| { + this.with_lifetime_rib( + LifetimeRibKind::ConstParamTy, + |this| this.visit_ty(ty), + ) + }) + }); + } else { + this.visit_ty(ty); + } - self.resolve_define_opaques(define_opaque); - } - AssocItemKind::Fn(Fn { generics, define_opaque, .. }) => { - walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); + // Only impose the restrictions of `ConstRibKind` for an + // actual constant expression in a provided default. + // + // We allow arbitrary const expressions inside of associated consts, + // even if they are potentially not const evaluatable. + // + // Type parameters can already be used and as associated consts are + // not used as part of the type system, this is far less surprising. + this.resolve_const_item_rhs(rhs_kind, None); + }, + ) + }, + ); - self.resolve_define_opaques(define_opaque); - } - AssocItemKind::Delegation(delegation) => { - self.with_generic_param_rib( - &[], - RibKind::AssocItem, - item.id, - LifetimeBinderKind::Function, - delegation.path.segments.last().unwrap().ident.span, - |this| this.resolve_delegation(delegation, item.id, false), - ); - } - AssocItemKind::Type(TyAlias { generics, .. }) => self - .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { - walk_assoc_item(this, generics, LifetimeBinderKind::Item, item) - }), - AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => { - panic!("unexpanded macro in resolve!") - } - }; - } + self.resolve_define_opaques(define_opaque); + } + AssocItemKind::Fn(Fn { generics, define_opaque, .. }) => { + walk_assoc_item(self, generics, LifetimeBinderKind::Function, item); - self.diag_metadata.current_trait_assoc_items = trait_assoc_items; + self.resolve_define_opaques(define_opaque); + } + AssocItemKind::Delegation(delegation) => { + self.with_generic_param_rib( + &[], + RibKind::AssocItem, + item.id, + LifetimeBinderKind::Function, + delegation.path.segments.last().unwrap().ident.span, + |this| this.resolve_delegation(delegation, item.id, false), + ); + } + AssocItemKind::Type(TyAlias { generics, .. }) => self + .with_lifetime_rib(LifetimeRibKind::AnonymousReportError, |this| { + walk_assoc_item(this, generics, LifetimeBinderKind::Item, item) + }), + AssocItemKind::MacCall(_) | AssocItemKind::DelegationMac(..) => { + panic!("unexpanded macro in resolve!") + } + }; } /// This is called to resolve a trait reference from an `impl` (i.e., `impl Trait for Foo`). From 66a2b8565fdd172cb2917fedd6d2611adc90ef3a Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Mon, 4 May 2026 17:56:47 +0200 Subject: [PATCH 2/4] Make `UnordItems::flat_map` take `UnordItems` as args, too --- compiler/rustc_data_structures/src/unord.rs | 19 ++++++++++++++++--- .../rustc_resolve/src/late/diagnostics.rs | 7 ++++++- .../clippy_lints/src/len_without_is_empty.rs | 3 ++- .../clippy_lints/src/pass_by_ref_or_value.rs | 3 ++- 4 files changed, 26 insertions(+), 6 deletions(-) diff --git a/compiler/rustc_data_structures/src/unord.rs b/compiler/rustc_data_structures/src/unord.rs index 93e05a0402a56..806d52be92a9c 100644 --- a/compiler/rustc_data_structures/src/unord.rs +++ b/compiler/rustc_data_structures/src/unord.rs @@ -34,6 +34,11 @@ use crate::stable_hash::{ pub struct UnordItems>(I); impl> UnordItems { + #[inline] + pub fn new(iter: I) -> UnordItems { + UnordItems(iter) + } + #[inline] pub fn map U>(self, f: F) -> UnordItems> { UnordItems(self.0.map(f)) @@ -62,6 +67,14 @@ impl> UnordItems { UnordItems(self.0.filter_map(f)) } + #[inline] + pub fn chain( + self, + other: UnordItems>, + ) -> UnordItems> { + UnordItems(self.0.chain(other.0)) + } + #[inline] pub fn max(self) -> Option where @@ -102,10 +115,10 @@ impl> UnordItems { #[inline] pub fn flat_map(self, f: F) -> UnordItems> where - U: IntoIterator, - F: Fn(T) -> U, + U: Iterator, + F: Fn(T) -> UnordItems, { - UnordItems(self.0.flat_map(f)) + UnordItems(self.0.flat_map(move |x| f(x).0)) } pub fn collect>>(self) -> C { diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index 10c864226d220..f600cbe5437fe 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -12,6 +12,7 @@ use rustc_ast::{ }; use rustc_ast_pretty::pprust::{path_to_string, where_bound_predicate_to_string}; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet}; +use rustc_data_structures::unord::UnordItems; use rustc_errors::codes::*; use rustc_errors::{ Applicability, Diag, Diagnostic, ErrorGuaranteed, MultiSpan, SuggestionStyle, pluralize, @@ -2670,7 +2671,11 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { .extern_crate_map .items() // FIXME: This doesn't include impls like `impl Default for String`. - .flat_map(|(_, crate_)| self.r.tcx.implementations_of_trait((*crate_, default_trait))) + .flat_map(|(_, crate_)| { + UnordItems::new( + self.r.tcx.implementations_of_trait((*crate_, default_trait)).into_iter(), + ) + }) .filter_map(|(_, simplified_self_ty)| *simplified_self_ty) .filter_map(|simplified_self_ty| match simplified_self_ty { SimplifiedType::Adt(did) => Some(did), diff --git a/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs b/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs index 8ae91bbcd2a91..4b188709a8be3 100644 --- a/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs +++ b/src/tools/clippy/clippy_lints/src/len_without_is_empty.rs @@ -1,6 +1,7 @@ use clippy_utils::diagnostics::{span_lint, span_lint_and_then}; use clippy_utils::res::MaybeDef; use clippy_utils::{fulfill_or_allowed, get_parent_as_impl, sym}; +use rustc_data_structures::unord::UnordItems; use rustc_hir::def::Res; use rustc_hir::def_id::{DefId, DefIdSet}; use rustc_hir::{ @@ -130,7 +131,7 @@ fn check_trait_items(cx: &LateContext<'_>, visited_trait: &Item<'_>, ident: Iden fill_trait_set(visited_trait.owner_id.to_def_id(), &mut current_and_super_traits, cx); let is_empty_method_found = current_and_super_traits .items() - .flat_map(|&i| cx.tcx.associated_items(i).filter_by_name_unhygienic(sym::is_empty)) + .flat_map(|&i| UnordItems::new(cx.tcx.associated_items(i).filter_by_name_unhygienic(sym::is_empty))) .any(|i| i.is_method() && cx.tcx.fn_sig(i.def_id).skip_binder().inputs().skip_binder().len() == 1); if !is_empty_method_found { diff --git a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs index 6b81b9d117a37..039da4cc4757a 100644 --- a/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs +++ b/src/tools/clippy/clippy_lints/src/pass_by_ref_or_value.rs @@ -6,6 +6,7 @@ use clippy_utils::{is_self, is_self_ty}; use core::ops::ControlFlow; use rustc_abi::ExternAbi; use rustc_data_structures::fx::FxHashSet; +use rustc_data_structures::unord::UnordItems; use rustc_errors::Applicability; use rustc_hir as hir; use rustc_hir::attrs::InlineAttr; @@ -181,7 +182,7 @@ impl PassByRefOrValue { || typeck .adjustments() .items() - .flat_map(|(_, a)| a) + .flat_map(|(_, a)| UnordItems::new(a.iter())) .any(|a| matches!(a.kind, Adjust::Pointer(PointerCoercion::UnsafeFnPointer)))) { continue; From adb2b0fd57924d931e569a88e7cd33a805d51c18 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Tue, 17 Feb 2026 11:57:28 +0000 Subject: [PATCH 3/4] Split the resolver tables into per-owner tables, starting with `node_id_to_def_id` --- compiler/rustc_ast_lowering/src/item.rs | 2 +- compiler/rustc_ast_lowering/src/lib.rs | 37 ++++-- compiler/rustc_middle/src/ty/mod.rs | 15 ++- compiler/rustc_passes/src/lang_items.rs | 6 +- .../rustc_resolve/src/build_reduced_graph.rs | 14 ++- compiler/rustc_resolve/src/check_unused.rs | 13 +- compiler/rustc_resolve/src/def_collector.rs | 90 +++++++++---- compiler/rustc_resolve/src/diagnostics.rs | 7 +- .../src/effective_visibilities.rs | 8 +- compiler/rustc_resolve/src/late.rs | 118 ++++++++++-------- compiler/rustc_resolve/src/lib.rs | 100 ++++++++++++--- compiler/rustc_resolve/src/macros.rs | 6 +- 12 files changed, 286 insertions(+), 130 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index 249f8e579eee9..ef9f1f10da8d2 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -98,7 +98,7 @@ impl<'hir> ItemLowerer<'_, 'hir> { match node { AstOwner::NonOwner => {} AstOwner::Crate(c) => { - assert_eq!(self.resolver.local_def_id(CRATE_NODE_ID), CRATE_DEF_ID); + assert_eq!(self.resolver.owner_def_id(CRATE_NODE_ID), CRATE_DEF_ID); self.with_lctx(CRATE_NODE_ID, |lctx| { let module = lctx.lower_mod(&c.items, &c.spans); // FIXME(jdonszelman): is dummy span ever a problem here? diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 1dcbc47449718..09ae64057af1a 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -61,7 +61,7 @@ use rustc_index::{Idx, IndexSlice, IndexVec}; use rustc_macros::extension; use rustc_middle::hir::{self as mid_hir}; use rustc_middle::span_bug; -use rustc_middle::ty::{DelegationInfo, ResolverAstLowering, TyCtxt}; +use rustc_middle::ty::{DelegationInfo, PerOwnerResolverData, ResolverAstLowering, TyCtxt}; use rustc_session::errors::add_feature_diagnostics; use rustc_span::symbol::{Ident, Symbol, kw, sym}; use rustc_span::{DUMMY_SP, DesugaringKind, Span}; @@ -126,6 +126,7 @@ struct LoweringContext<'a, 'hir> { is_in_dyn_type: bool, current_hir_id_owner: hir::OwnerId, + owner: &'a PerOwnerResolverData, item_local_id_counter: hir::ItemLocalId, trait_map: ItemLocalMap<&'hir [TraitCandidate<'hir>]>, @@ -173,6 +174,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { tcx, resolver, current_disambiguator: Default::default(), + owner: &resolver.owners[&CRATE_NODE_ID], arena: tcx.hir_arena, // HirId handling. @@ -316,12 +318,8 @@ impl<'tcx> ResolverAstLowering<'tcx> { self.delegation_infos.get(&id) } - fn opt_local_def_id(&self, id: NodeId) -> Option { - self.node_id_to_def_id.get(&id).copied() - } - - fn local_def_id(&self, id: NodeId) -> LocalDefId { - self.opt_local_def_id(id).expect("must have def_id") + fn owner_def_id(&self, id: NodeId) -> LocalDefId { + self.owners[&id].node_id_to_def_id[&id] } fn lifetime_elision_allowed(&self, id: NodeId) -> bool { @@ -489,20 +487,20 @@ fn index_crate<'a, 'b>( } fn visit_item(&mut self, item: &'a ast::Item) { - let def_id = self.resolver.local_def_id(item.id); + let def_id = self.resolver.owner_def_id(item.id); *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::Item(item); visit::walk_item(self, item) } fn visit_assoc_item(&mut self, item: &'a ast::AssocItem, ctxt: visit::AssocCtxt) { - let def_id = self.resolver.local_def_id(item.id); + let def_id = self.resolver.owner_def_id(item.id); *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::AssocItem(item, ctxt); visit::walk_assoc_item(self, item, ctxt); } fn visit_foreign_item(&mut self, item: &'a ast::ForeignItem) { - let def_id = self.resolver.local_def_id(item.id); + let def_id = self.resolver.owner_def_id(item.id); *self.index.ensure_contains_elem(def_id, || AstOwner::NonOwner) = AstOwner::ForeignItem(item); visit::walk_item(self, item); @@ -668,12 +666,23 @@ impl<'hir> LoweringContext<'_, 'hir> { fn opt_local_def_id(&self, node: NodeId) -> Option { self.node_id_to_def_id .get(&node) - .or_else(|| self.resolver.node_id_to_def_id.get(&node)) + .or_else(|| self.owner.node_id_to_def_id.get(&node)) .copied() } fn local_def_id(&self, node: NodeId) -> LocalDefId { - self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) + self.opt_local_def_id(node).unwrap_or_else(|| { + self.resolver.owners.items().any(|(id, items)| { + items.node_id_to_def_id.items().any(|(node_id, def_id)| { + if *node_id == node { + let actual_owner = items.node_id_to_def_id.get(id); + panic!("{def_id:?} ({node_id}) was found in {actual_owner:?} ({id})",) + } + false + }) + }); + panic!("no entry for node id: `{node:?}`"); + }) } fn get_partial_res(&self, id: NodeId) -> Option { @@ -685,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Given the id of an owner node in the AST, returns the corresponding `OwnerId`. fn owner_id(&self, node: NodeId) -> hir::OwnerId { - hir::OwnerId { def_id: self.local_def_id(node) } + hir::OwnerId { def_id: self.resolver.owners[&node].node_id_to_def_id[&node] } } /// Freshen the `LoweringContext` and ready it to lower a nested item. @@ -710,6 +719,7 @@ impl<'hir> LoweringContext<'_, 'hir> { .unwrap_or_else(|| PerParentDisambiguatorState::new(def_id)); let disambiguator = std::mem::replace(&mut self.current_disambiguator, new_disambig); + let current_ast_owner = std::mem::replace(&mut self.owner, &self.resolver.owners[&owner]); let current_attrs = std::mem::take(&mut self.attrs); let current_bodies = std::mem::take(&mut self.bodies); let current_define_opaque = std::mem::take(&mut self.define_opaque); @@ -745,6 +755,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let info = self.make_owner_info(item); self.current_disambiguator = disambiguator; + self.owner = current_ast_owner; self.attrs = current_attrs; self.bodies = current_bodies; self.define_opaque = current_define_opaque; diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 16933cb4ea8ff..113fa9ec7c103 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -198,6 +198,19 @@ pub struct ResolverGlobalCtxt { pub stripped_cfg_items: Vec, } +#[derive(Debug)] +pub struct PerOwnerResolverData { + pub node_id_to_def_id: NodeMap, + /// The id of the owner + pub id: ast::NodeId, +} + +impl PerOwnerResolverData { + pub fn new(id: ast::NodeId) -> PerOwnerResolverData { + PerOwnerResolverData { node_id_to_def_id: Default::default(), id } + } +} + /// Resolutions that should only be used for lowering. /// This struct is meant to be consumed by lowering. #[derive(Debug)] @@ -215,7 +228,7 @@ pub struct ResolverAstLowering<'tcx> { pub next_node_id: ast::NodeId, - pub node_id_to_def_id: NodeMap, + pub owners: NodeMap, pub trait_map: NodeMap<&'tcx [hir::TraitCandidate<'tcx>]>, /// List functions and methods for which lifetime elision was successful. diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index 527c618c7a264..d6d21a8bcf104 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -295,7 +295,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { self.check_for_lang( target, - self.resolver.node_id_to_def_id[&i.id], + self.resolver.owners[&i.id].node_id_to_def_id[&i.id], &i.attrs, i.span, i.opt_generics(), @@ -309,7 +309,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { fn visit_variant(&mut self, variant: &'ast ast::Variant) { self.check_for_lang( Target::Variant, - self.resolver.node_id_to_def_id[&variant.id], + self.resolver.owners[&self.parent_item.unwrap().id].node_id_to_def_id[&variant.id], &variant.attrs, variant.span, None, @@ -348,7 +348,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { self.check_for_lang( target, - self.resolver.node_id_to_def_id[&i.id], + self.resolver.owners[&i.id].node_id_to_def_id[&i.id], &i.attrs, i.span, generics, diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 96d4b06ea2c84..283f443bb1f0d 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -743,12 +743,14 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { } ast::UseTreeKind::Nested { ref items, .. } => { for &(ref tree, id) in items { - let feed = self.create_def(id, None, DefKind::Use, use_tree.span()); - self.build_reduced_graph_for_use_tree( - // This particular use tree - tree, id, &prefix, true, false, // The whole `use` item - item, vis, root_span, feed, - ); + self.with_owner(id, |this| { + let feed = this.create_def(id, None, DefKind::Use, use_tree.span()); + this.build_reduced_graph_for_use_tree( + // This particular use tree + tree, id, &prefix, true, false, // The whole `use` item + item, vis, root_span, feed, + ) + }); } // Empty groups `a::b::{}` are turned into synthetic `self` imports diff --git a/compiler/rustc_resolve/src/check_unused.rs b/compiler/rustc_resolve/src/check_unused.rs index 8ab0087ae6158..d39dcb1fa280b 100644 --- a/compiler/rustc_resolve/src/check_unused.rs +++ b/compiler/rustc_resolve/src/check_unused.rs @@ -31,6 +31,7 @@ use rustc_data_structures::fx::{FxHashMap, FxIndexMap, FxIndexSet}; use rustc_data_structures::unord::UnordSet; use rustc_errors::{DiagArgValue, Diagnostic, MultiSpan}; use rustc_hir::def::{DefKind, Res}; +use rustc_hir::def_id::LocalDefId; use rustc_session::lint::builtin::{ MACRO_USE_EXTERN_CRATE, UNUSED_EXTERN_CRATES, UNUSED_IMPORTS, UNUSED_QUALIFICATIONS, }; @@ -81,9 +82,8 @@ struct ExternCrateToLint { impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { // We have information about whether `use` (import) items are actually // used now. If an import is not used at all, we signal a lint error. - fn check_import(&mut self, id: ast::NodeId) { + fn check_import(&mut self, id: ast::NodeId, def_id: LocalDefId) { let used = self.r.used_imports.contains(&id); - let def_id = self.r.local_def_id(id); if !used { if self.r.maybe_unused_trait_imports.contains(&def_id) { // Check later. @@ -102,7 +102,8 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { } fn check_use_tree(&mut self, use_tree: &'a ast::UseTree, id: ast::NodeId) { - if self.r.effective_visibilities.is_exported(self.r.local_def_id(id)) { + let def_id = self.r.owner_def_id(id); + if self.r.effective_visibilities.is_exported(def_id) { self.check_import_as_underscore(use_tree, id); return; } @@ -112,7 +113,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { self.unused_import(self.base_id).add(id); } } else { - self.check_import(id); + self.check_import(id, def_id); } } @@ -212,7 +213,7 @@ impl<'a, 'ra, 'tcx> UnusedImportCheckVisitor<'a, 'ra, 'tcx> { let module = self .r - .get_nearest_non_block_module(self.r.local_def_id(extern_crate.id).to_def_id()); + .get_nearest_non_block_module(self.r.owner_def_id(extern_crate.id).to_def_id()); if module.no_implicit_prelude { // If the module has `no_implicit_prelude`, then we don't suggest // replacing the extern crate with a use, as it would not be @@ -494,7 +495,7 @@ impl Resolver<'_, '_> { None } else { let parent_module = visitor.r.get_nearest_non_block_module( - visitor.r.local_def_id(unused.use_tree_id).to_def_id(), + visitor.r.owner_def_id(unused.use_tree_id).to_def_id(), ); match module_to_string(parent_module) { Some(module) diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 06c9038d90430..2a597f399402f 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -11,12 +11,15 @@ use rustc_hir::def::DefKind; use rustc_hir::def::Namespace::{TypeNS, ValueNS}; use rustc_hir::def_id::LocalDefId; use rustc_middle::span_bug; -use rustc_middle::ty::TyCtxtFeed; +use rustc_middle::ty::{PerOwnerResolverData, TyCtxtFeed}; use rustc_span::{Span, Symbol, sym}; use tracing::{debug, instrument}; use crate::macros::MacroRulesScopeRef; -use crate::{ConstArgContext, ImplTraitContext, InvocationParent, ParentScope, Resolver}; +use crate::{ + ConstArgContext, ImplTraitContext, InvocationParent, ParentScope, Resolver, with_owner, + with_owner_tables, +}; pub(crate) fn collect_definitions<'ra>( resolver: &mut Resolver<'ra, '_>, @@ -25,9 +28,13 @@ pub(crate) fn collect_definitions<'ra>( ) -> MacroRulesScopeRef<'ra> { let invocation_parent = resolver.invocation_parents[&parent_scope.expansion]; debug!("new fragment to visit with invocation_parent: {invocation_parent:?}"); - let mut visitor = DefCollector { r: resolver, invocation_parent, parent_scope }; - fragment.visit_with(&mut visitor); - visitor.parent_scope.macro_rules + debug_assert_eq!(resolver.current_owner.id, DUMMY_NODE_ID); + with_owner(resolver, invocation_parent.owner, |r| { + let mut visitor = DefCollector { r, invocation_parent, parent_scope }; + fragment.visit_with(&mut visitor); + + visitor.parent_scope.macro_rules + }) } /// Creates `DefId`s for nodes in the AST. @@ -66,6 +73,27 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { self.invocation_parent.parent_def = orig_parent_def; } + pub(super) fn with_owner(&mut self, owner: NodeId, f: F) { + debug_assert_ne!(owner, DUMMY_NODE_ID); + if owner == CRATE_NODE_ID { + // Special case: we always have an invocation parent (set in `collect_definitions`) + // of at least the crate root, even for visiting the crate root, + // which would then remove the crate root from the tables + // list twice and try to insert it twice afterwards. + debug_assert_eq!(self.r.current_owner.id, CRATE_NODE_ID); + return f(self); + } + // We only get here if the owner didn't exist yet. After the owner has been created, + // future invocations of `collect_definitions` will get the owner out of the `owners` + // table. + let tables = PerOwnerResolverData::new(owner); + + let orig_invoc_owner = mem::replace(&mut self.invocation_parent.owner, owner); + with_owner_tables(self, owner, tables, f); + let old = mem::replace(&mut self.invocation_parent.owner, orig_invoc_owner); + assert_eq!(old, owner); + } + fn with_impl_trait( &mut self, impl_trait_context: ImplTraitContext, @@ -172,9 +200,10 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, ItemKind::Use(_) => { - let feed = self.create_def(i.id, None, DefKind::Use, i.span); - self.brg_visit_item(i, feed); - return; + return self.with_owner(i.id, |this| { + let feed = this.create_def(i.id, None, DefKind::Use, i.span); + this.brg_visit_item(i, feed); + }); } ItemKind::MacCall(..) => { self.visit_macro_invoc(i.id); @@ -183,14 +212,19 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } ItemKind::DelegationMac(..) => unreachable!(), }; - let feed = self.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span); + self.with_owner(i.id, |this| { + let feed = + this.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span); - if let Some(ext) = opt_syn_ext { - self.r.local_macro_map.insert(feed.def_id(), self.r.arenas.alloc_macro(ext)); - } + if let Some(ext) = opt_syn_ext { + this.r.local_macro_map.insert(feed.def_id(), self.r.arenas.alloc_macro(ext)); + } - self.with_parent(feed.def_id(), |this| { - this.with_impl_trait(ImplTraitContext::Existential, |this| this.brg_visit_item(i, feed)) + this.with_parent(feed.def_id(), |this| { + this.with_impl_trait(ImplTraitContext::Existential, |this| { + this.brg_visit_item(i, feed) + }) + }); }); } @@ -282,12 +316,14 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } }; - let def = self.create_def(fi.id, Some(ident.name), def_kind, fi.span); + self.with_owner(fi.id, |this| { + let def = this.create_def(fi.id, Some(ident.name), def_kind, fi.span); - self.with_parent(def.def_id(), |this| { - this.build_reduced_graph_for_foreign_item(fi, ident, def); - visit::walk_item(this, fi) - }); + this.with_parent(def.def_id(), |this| { + this.build_reduced_graph_for_foreign_item(fi, ident, def); + visit::walk_item(this, fi) + }); + }) } fn visit_variant(&mut self, v: &'a Variant) { @@ -366,8 +402,12 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } }; - let feed = self.create_def(i.id, Some(ident.name), def_kind, i.span); - self.with_parent(feed.def_id(), |this| this.brg_visit_assoc_item(i, ctxt, ident, ns, feed)); + self.with_owner(i.id, |this| { + let feed = this.create_def(i.id, Some(ident.name), def_kind, i.span); + this.with_parent(feed.def_id(), |this| { + this.brg_visit_assoc_item(i, ctxt, ident, ns, feed) + }); + }) } fn visit_pat(&mut self, pat: &'a Pat) { @@ -564,9 +604,11 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } else { // Visit attributes after items for backward compatibility. // This way they can use `macro_rules` defined later. - visit::walk_list!(self, visit_item, &krate.items); - visit::walk_list!(self, visit_attribute, &krate.attrs); - self.contains_macro_use(&krate.attrs); + self.with_owner(CRATE_NODE_ID, |this| { + visit::walk_list!(this, visit_item, &krate.items); + visit::walk_list!(this, visit_attribute, &krate.attrs); + this.contains_macro_use(&krate.attrs); + }) } } diff --git a/compiler/rustc_resolve/src/diagnostics.rs b/compiler/rustc_resolve/src/diagnostics.rs index 4ba6106bf09e6..85e8d6711e075 100644 --- a/compiler/rustc_resolve/src/diagnostics.rs +++ b/compiler/rustc_resolve/src/diagnostics.rs @@ -3261,7 +3261,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .stripped_cfg_items .iter() .filter_map(|item| { - let parent_scope = self.opt_local_def_id(item.parent_scope)?.to_def_id(); + let parent_scope = self.local_modules.iter().find_map(|m| match m.kind { + ModuleKind::Def(_, def_id, node_id, _) if node_id == item.parent_scope => { + Some(def_id) + } + _ => None, + })?; Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg.clone() }) }) .collect::>(); diff --git a/compiler/rustc_resolve/src/effective_visibilities.rs b/compiler/rustc_resolve/src/effective_visibilities.rs index f3b47f04c90a6..c7c46a41de442 100644 --- a/compiler/rustc_resolve/src/effective_visibilities.rs +++ b/compiler/rustc_resolve/src/effective_visibilities.rs @@ -214,7 +214,7 @@ impl<'a, 'ra, 'tcx> EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> { fn visit_item(&mut self, item: &'a ast::Item) { - let def_id = self.r.local_def_id(item.id); + let def_id = self.r.owner_def_id(item.id); // Update effective visibilities of nested items. // If it's a mod, also make the visitor walk all of its items match item.kind { @@ -237,16 +237,16 @@ impl<'a, 'ra, 'tcx> Visitor<'a> for EffectiveVisibilitiesVisitor<'a, 'ra, 'tcx> ast::ItemKind::Enum(_, _, EnumDef { ref variants }) => { self.set_bindings_effective_visibilities(def_id); for variant in variants { - let variant_def_id = self.r.local_def_id(variant.id); + let variant_def_id = self.r.child_def_id(item.id, variant.id); for field in variant.data.fields() { - self.update_field(self.r.local_def_id(field.id), variant_def_id); + self.update_field(self.r.child_def_id(item.id, field.id), variant_def_id); } } } ast::ItemKind::Struct(_, _, ref def) | ast::ItemKind::Union(_, _, ref def) => { for field in def.fields() { - self.update_field(self.r.local_def_id(field.id), def_id); + self.update_field(self.r.child_def_id(item.id, field.id), def_id); } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index f18fc7e6feca5..39cad6f3ff91b 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -42,7 +42,7 @@ use tracing::{debug, instrument, trace}; use crate::{ BindingError, BindingKey, Decl, DelegationFnSig, Finalize, IdentKey, LateDecl, LocalModule, Module, ModuleOrUniformRoot, ParentScope, PathResult, Res, ResolutionError, Resolver, Segment, - Stage, TyCtxt, UseError, Used, errors, path_names_to_string, rustdoc, + Stage, TyCtxt, UseError, Used, errors, path_names_to_string, rustdoc, with_owner, }; mod diagnostics; @@ -823,6 +823,17 @@ struct LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { lifetime_uses: FxHashMap, } +impl<'ra, 'tcx> AsRef> for LateResolutionVisitor<'_, '_, 'ra, 'tcx> { + fn as_ref(&self) -> &Resolver<'ra, 'tcx> { + &self.r + } +} +impl<'ra, 'tcx> AsMut> for LateResolutionVisitor<'_, '_, 'ra, 'tcx> { + fn as_mut(&mut self) -> &mut Resolver<'ra, 'tcx> { + &mut self.r + } +} + /// Walks the whole crate in DFS order, visiting each item, resolving names as it goes. impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { fn visit_attribute(&mut self, _: &'ast Attribute) { @@ -833,7 +844,9 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc let prev = replace(&mut self.diag_metadata.current_item, Some(item)); // Always report errors in items we just entered. let old_ignore = replace(&mut self.in_func_body, false); - self.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item)); + with_owner(self, item.id, |this| { + this.with_lifetime_rib(LifetimeRibKind::Item, |this| this.resolve_item(item)) + }); self.in_func_body = old_ignore; self.diag_metadata.current_item = prev; } @@ -1042,36 +1055,38 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc ); } fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { - self.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id)); - let def_kind = self.r.local_def_kind(foreign_item.id); - match foreign_item.kind { - ForeignItemKind::TyAlias(TyAlias { ref generics, .. }) => { - self.with_generic_param_rib( - &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), - foreign_item.id, - LifetimeBinderKind::Item, - generics.span, - |this| visit::walk_item(this, foreign_item), - ); - } - ForeignItemKind::Fn(Fn { ref generics, .. }) => { - self.with_generic_param_rib( - &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), - foreign_item.id, - LifetimeBinderKind::Function, - generics.span, - |this| visit::walk_item(this, foreign_item), - ); - } - ForeignItemKind::Static(..) => { - self.with_static_rib(def_kind, |this| visit::walk_item(this, foreign_item)) - } - ForeignItemKind::MacCall(..) => { - panic!("unexpanded macro in resolve!") + with_owner(self, foreign_item.id, |this| { + this.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id)); + let def_kind = this.r.local_def_kind(foreign_item.id); + match foreign_item.kind { + ForeignItemKind::TyAlias(TyAlias { ref generics, .. }) => { + this.with_generic_param_rib( + &generics.params, + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), + foreign_item.id, + LifetimeBinderKind::Item, + generics.span, + |this| visit::walk_item(this, foreign_item), + ); + } + ForeignItemKind::Fn(Fn { ref generics, .. }) => { + this.with_generic_param_rib( + &generics.params, + RibKind::Item(HasGenericParams::Yes(generics.span), def_kind), + foreign_item.id, + LifetimeBinderKind::Function, + generics.span, + |this| visit::walk_item(this, foreign_item), + ); + } + ForeignItemKind::Static(..) => { + this.with_static_rib(def_kind, |this| visit::walk_item(this, foreign_item)) + } + ForeignItemKind::MacCall(..) => { + panic!("unexpanded macro in resolve!") + } } - } + }) } fn visit_fn(&mut self, fn_kind: FnKind<'ast>, _: &AttrVec, sp: Span, fn_id: NodeId) { let previous_value = self.diag_metadata.current_function; @@ -3322,7 +3337,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { replace(&mut self.diag_metadata.current_trait_assoc_items, Some(trait_items)); for item in trait_items { - self.resolve_trait_item(item); + with_owner(self, item.id, |this| this.resolve_trait_item(item)); } self.diag_metadata.current_trait_assoc_items = trait_assoc_items; @@ -3528,7 +3543,9 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { debug!("resolve_implementation with_self_rib_ns(ValueNS, ...)"); let mut seen_trait_items = Default::default(); for item in impl_items { - this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id, of_trait.is_some()); + with_owner(this, item.id, |this| { + this.resolve_impl_item(&**item, &mut seen_trait_items, trait_id, of_trait.is_some()); + }) } }); }); @@ -5052,7 +5069,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { && let ItemKind::MacroDef(..) = item.kind { num_macro_definition_ribs += 1; - let res = self.r.local_def_id(item.id).to_def_id(); + let res = self.r.owner_def_id(item.id).to_def_id(); self.ribs[ValueNS].push(Rib::new(RibKind::MacroDefinition(res))); self.label_ribs.push(Rib::new(RibKind::MacroDefinition(res))); } @@ -5547,7 +5564,7 @@ impl ItemInfoCollector<'_, '_, '_> { fn collect_fn_info(&mut self, decl: &FnDecl, id: NodeId) { self.r .delegation_fn_sigs - .insert(self.r.local_def_id(id), DelegationFnSig { has_self: decl.has_self() }); + .insert(self.r.owner_def_id(id), DelegationFnSig { has_self: decl.has_self() }); } } @@ -5593,7 +5610,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { self.collect_fn_info(&sig.decl, item.id); } - let def_id = self.r.local_def_id(item.id); + let def_id = self.r.owner_def_id(item.id); let count = generics .params .iter() @@ -5635,7 +5652,7 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { } if let AssocItemKind::Type(ast::TyAlias { generics, .. }) = &item.kind { - let def_id = self.r.local_def_id(item.id); + let def_id = self.r.owner_def_id(item.id); if let Some(suggestion) = required_generic_args_suggestion(generics) { self.r.item_required_generic_args_suggestions.insert(def_id, suggestion); } @@ -5646,18 +5663,21 @@ impl<'ast> Visitor<'ast> for ItemInfoCollector<'_, '_, '_> { impl<'ra, 'tcx> Resolver<'ra, 'tcx> { pub(crate) fn late_resolve_crate(&mut self, krate: &Crate) { - visit::walk_crate(&mut ItemInfoCollector { r: self }, krate); - let mut late_resolution_visitor = LateResolutionVisitor::new(self); - late_resolution_visitor.resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); - visit::walk_crate(&mut late_resolution_visitor, krate); - for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { - self.lint_buffer.buffer_lint( - lint::builtin::UNUSED_LABELS, - *id, - *span, - errors::UnusedLabel, - ); - } + with_owner(self, CRATE_NODE_ID, |this| { + visit::walk_crate(&mut ItemInfoCollector { r: this }, krate); + let mut late_resolution_visitor = LateResolutionVisitor::new(this); + late_resolution_visitor + .resolve_doc_links(&krate.attrs, MaybeExported::Ok(CRATE_NODE_ID)); + visit::walk_crate(&mut late_resolution_visitor, krate); + for (id, span) in late_resolution_visitor.diag_metadata.unused_labels.iter() { + this.lint_buffer.buffer_lint( + lint::builtin::UNUSED_LABELS, + *id, + *span, + errors::UnusedLabel, + ); + } + }) } } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index 32bc59de711ed..f0918fa4939a3 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -22,9 +22,9 @@ use std::cell::Ref; use std::collections::BTreeSet; -use std::fmt; use std::ops::ControlFlow; use std::sync::Arc; +use std::{fmt, mem}; use diagnostics::{ImportSuggestion, LabelSuggestion, StructCtor, Suggestion}; use effective_visibilities::EffectiveVisibilitiesVisitor; @@ -39,8 +39,8 @@ use macros::{MacroRulesDecl, MacroRulesScope, MacroRulesScopeRef}; use rustc_arena::{DroplessArena, TypedArena}; use rustc_ast::node_id::NodeMap; use rustc_ast::{ - self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, Expr, ExprKind, GenericArg, GenericArgs, - Generics, NodeId, Path, attr, + self as ast, AngleBracketedArg, CRATE_NODE_ID, Crate, DUMMY_NODE_ID, Expr, ExprKind, + GenericArg, GenericArgs, Generics, NodeId, Path, attr, }; use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, default}; use rustc_data_structures::intern::Interned; @@ -65,8 +65,8 @@ use rustc_middle::metadata::{AmbigModChild, ModChild, Reexport}; use rustc_middle::middle::privacy::EffectiveVisibilities; use rustc_middle::query::Providers; use rustc_middle::ty::{ - self, DelegationInfo, MainDefinition, RegisteredTools, ResolverAstLowering, ResolverGlobalCtxt, - TyCtxt, TyCtxtFeed, Visibility, + self, DelegationInfo, MainDefinition, PerOwnerResolverData, RegisteredTools, + ResolverAstLowering, ResolverGlobalCtxt, TyCtxt, TyCtxtFeed, Visibility, }; use rustc_middle::{bug, span_bug}; use rustc_session::config::CrateType; @@ -74,7 +74,7 @@ use rustc_session::lint::builtin::PRIVATE_MACRO_USE; use rustc_span::hygiene::{ExpnId, LocalExpnId, MacroKind, SyntaxContext, Transparency}; use rustc_span::{DUMMY_SP, Ident, Span, Symbol, kw, sym}; use smallvec::{SmallVec, smallvec}; -use tracing::debug; +use tracing::{debug, instrument}; type Res = def::Res; @@ -188,6 +188,7 @@ struct InvocationParent { impl_trait_context: ImplTraitContext, in_attr: bool, const_arg_context: ConstArgContext, + owner: NodeId, } impl InvocationParent { @@ -196,6 +197,7 @@ impl InvocationParent { impl_trait_context: ImplTraitContext::Existential, in_attr: false, const_arg_context: ConstArgContext::NonDirect, + owner: CRATE_NODE_ID, }; } @@ -1499,7 +1501,11 @@ pub struct Resolver<'ra, 'tcx> { next_node_id: NodeId = CRATE_NODE_ID, - node_id_to_def_id: NodeMap, + /// Preserves per owner data once the owner is finished resolving. + owners: NodeMap, + + /// An entry of `owners` that gets taken out and reinserted whenever an owner is handled. + current_owner: PerOwnerResolverData, disambiguators: LocalDefIdMap, @@ -1639,10 +1645,26 @@ impl<'ra, 'tcx> AsRef> for Resolver<'ra, 'tcx> { } impl<'tcx> Resolver<'_, 'tcx> { + /// Only call this in analyses after the resolver has finished. + /// Panics if the node id is currently not in the owner storage, + /// e.g. because it's further up in the current visitor stack. + fn owner_def_id(&self, node: NodeId) -> LocalDefId { + self.child_def_id(node, node) + } + + /// Only call this in analyses after the resolver has finished. + /// Panics if the node id is currently not in the owner storage, + /// e.g. because it's further up in the current visitor stack. + fn child_def_id(&self, owner: NodeId, id: NodeId) -> LocalDefId { + self.owners[&owner].node_id_to_def_id[&id] + } + + /// Get the `DefId` of a child of the current owner fn opt_local_def_id(&self, node: NodeId) -> Option { - self.node_id_to_def_id.get(&node).copied() + self.current_owner.node_id_to_def_id.get(&node).copied() } + /// Get the `DefId` of a child of the current owner fn local_def_id(&self, node: NodeId) -> LocalDefId { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } @@ -1662,12 +1684,14 @@ impl<'tcx> Resolver<'_, 'tcx> { span: Span, ) -> TyCtxtFeed<'tcx, LocalDefId> { assert!( - !self.node_id_to_def_id.contains_key(&node_id), + !self.current_owner.node_id_to_def_id.contains_key(&node_id), "adding a def for node-id {:?}, name {:?}, data {:?} but a previous def exists: {:?}", node_id, name, def_kind, - self.tcx.definitions_untracked().def_key(self.node_id_to_def_id[&node_id]), + self.tcx + .definitions_untracked() + .def_key(self.current_owner.node_id_to_def_id[&node_id]), ); let disambiguator = self.disambiguators.get_or_create(parent); @@ -1691,7 +1715,7 @@ impl<'tcx> Resolver<'_, 'tcx> { // we don't need a mapping from `NodeId` to `LocalDefId`. if node_id != ast::DUMMY_NODE_ID { debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); - self.node_id_to_def_id.insert(node_id, def_id); + self.current_owner.node_id_to_def_id.insert(node_id, def_id); } feed @@ -1736,12 +1760,15 @@ impl<'tcx> Resolver<'_, 'tcx> { } /// This function is very slow, as it iterates over the entire - /// [Resolver::node_id_to_def_id] map just to find the [NodeId] + /// [PerOwnerResolverData::node_id_to_def_id] map for all [Resolver::owners] + /// just to find the [NodeId] /// that corresponds to the given [LocalDefId]. Only use this in - /// diagnostics code paths. + /// diagnostics code paths. Do not use this during macro expansion, + /// as it will not find any node ids within your current expansion's stack. fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId { - self.node_id_to_def_id + self.owners .items() + .flat_map(|(_, data)| data.node_id_to_def_id.items()) .filter(|(_, v)| **v == def_id) .map(|(k, _)| *k) .get_only() @@ -1779,11 +1806,13 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { arenas, ); - let mut node_id_to_def_id = NodeMap::default(); + let mut owner_data = PerOwnerResolverData::new(CRATE_NODE_ID); let crate_feed = tcx.create_local_crate_def_id(crate_span); crate_feed.def_kind(DefKind::Mod); - node_id_to_def_id.insert(CRATE_NODE_ID, CRATE_DEF_ID); + owner_data.node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed.key()); + let mut owners = NodeMap::default(); + owners.insert(CRATE_NODE_ID, owner_data); let mut invocation_parents = FxHashMap::default(); invocation_parents.insert(LocalExpnId::ROOT, InvocationParent::ROOT); @@ -1846,7 +1875,8 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { single_segment_macro_resolutions: Default::default(), multi_segment_macro_resolutions: Default::default(), lint_buffer: LintBuffer::default(), - node_id_to_def_id, + owners, + current_owner: PerOwnerResolverData::new(DUMMY_NODE_ID), invocation_parents, trait_impls: Default::default(), confused_type_with_std_module: Default::default(), @@ -1948,7 +1978,12 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .stripped_cfg_items .into_iter() .filter_map(|item| { - let parent_scope = self.node_id_to_def_id.get(&item.parent_scope)?.to_def_id(); + let parent_scope = self + .owners + .get(&item.parent_scope)? + .node_id_to_def_id + .get(&item.parent_scope)? + .to_def_id(); Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg }) }) .collect(); @@ -1983,7 +2018,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { lifetimes_res_map: self.lifetimes_res_map, extra_lifetime_params_map: self.extra_lifetime_params_map, next_node_id: self.next_node_id, - node_id_to_def_id: self.node_id_to_def_id, + owners: self.owners, trait_map: self.trait_map, lifetime_elision_allowed: self.lifetime_elision_allowed, lint_buffer: Steal::new(self.lint_buffer), @@ -2644,6 +2679,33 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { } } +fn with_owner<'ra, 'tcx, R: AsMut>, T>( + this: &mut R, + owner: NodeId, + work: impl FnOnce(&mut R) -> T, +) -> T { + let tables = this.as_mut().owners.remove(&owner).unwrap(); + with_owner_tables(this, owner, tables, work) +} + +#[instrument(level = "debug", skip(this, work))] +fn with_owner_tables<'ra, 'tcx, R: AsMut>, T>( + this: &mut R, + owner: NodeId, + tables: PerOwnerResolverData, + work: impl FnOnce(&mut R) -> T, +) -> T { + debug_assert!(!this.as_mut().owners.contains_key(&owner)); + let resolver = this.as_mut(); + let old_owner = mem::replace(&mut resolver.current_owner, tables); + let ret = work(this); + let resolver = this.as_mut(); + let overwritten = + resolver.owners.insert(owner, mem::replace(&mut resolver.current_owner, old_owner)); + assert!(overwritten.is_none()); + ret +} + fn build_extern_prelude<'tcx, 'ra>( tcx: TyCtxt<'tcx>, attrs: &[ast::Attribute], diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index 206e32f61b485..ee45edda12f9c 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -165,7 +165,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn mark_scope_with_compile_error(&mut self, id: NodeId) { - if let Some(id) = self.opt_local_def_id(id) + if let Some(id) = self.owners.get(&id).map(|i| i.node_id_to_def_id[&id]) && self.tcx.def_kind(id).is_module_like() { self.mods_with_parse_errors.insert(id.to_def_id()); @@ -215,7 +215,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { parent_module_id: Option, ) -> LocalExpnId { let parent_module = - parent_module_id.map(|module_id| self.local_def_id(module_id).to_def_id()); + parent_module_id.map(|module_id| self.owner_def_id(module_id).to_def_id()); let expn_id = self.tcx.with_stable_hashing_context(|hcx| { LocalExpnId::fresh( ExpnData::allow_unstable( @@ -489,7 +489,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn declare_proc_macro(&mut self, id: NodeId) { - self.proc_macros.push(self.local_def_id(id)) + self.proc_macros.push(self.owner_def_id(id)) } fn append_stripped_cfg_item( From 3a2ae6a2040b117b091595cbee61f4cb1753ba49 Mon Sep 17 00:00:00 2001 From: Oli Scherer Date: Thu, 7 May 2026 15:31:23 +0200 Subject: [PATCH 4/4] Stop putting owner's `DefId` into their own `node_id_to_def_id` map Now they unfortunately land in their parent, which is not necessary --- compiler/rustc_ast_lowering/src/delegation.rs | 6 +- .../src/delegation/generics.rs | 4 +- compiler/rustc_ast_lowering/src/item.rs | 6 +- compiler/rustc_ast_lowering/src/lib.rs | 12 +-- compiler/rustc_middle/src/ty/mod.rs | 6 +- compiler/rustc_passes/src/lang_items.rs | 10 +-- .../rustc_resolve/src/build_reduced_graph.rs | 3 +- compiler/rustc_resolve/src/def_collector.rs | 88 +++++++++++-------- compiler/rustc_resolve/src/late.rs | 30 ++++--- .../rustc_resolve/src/late/diagnostics.rs | 5 +- compiler/rustc_resolve/src/lib.rs | 31 +++---- compiler/rustc_resolve/src/macros.rs | 2 +- 12 files changed, 104 insertions(+), 99 deletions(-) diff --git a/compiler/rustc_ast_lowering/src/delegation.rs b/compiler/rustc_ast_lowering/src/delegation.rs index adde518af0f41..df5ea7c3168ff 100644 --- a/compiler/rustc_ast_lowering/src/delegation.rs +++ b/compiler/rustc_ast_lowering/src/delegation.rs @@ -122,8 +122,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let span = self.lower_span(delegation.path.segments.last().unwrap().ident.span); // Delegation can be unresolved in illegal places such as function bodies in extern blocks (see #151356) - let sig_id = if let Some(delegation_info) = - self.resolver.delegation_info(self.local_def_id(item_id)) + let sig_id = if let Some(delegation_info) = self.resolver.delegation_info(self.owner.def_id) { self.get_sig_id(delegation_info.resolution_node, span) } else { @@ -143,8 +142,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let (param_count, c_variadic) = self.param_count(sig_id); - let mut generics = - self.uplift_delegation_generics(delegation, sig_id, item_id, is_method); + let mut generics = self.uplift_delegation_generics(delegation, sig_id, is_method); let body_id = self.lower_delegation_body( delegation, diff --git a/compiler/rustc_ast_lowering/src/delegation/generics.rs b/compiler/rustc_ast_lowering/src/delegation/generics.rs index afffc20adf4b3..c2c3bd740e3cf 100644 --- a/compiler/rustc_ast_lowering/src/delegation/generics.rs +++ b/compiler/rustc_ast_lowering/src/delegation/generics.rs @@ -231,11 +231,9 @@ impl<'hir> LoweringContext<'_, 'hir> { &mut self, delegation: &Delegation, sig_id: DefId, - item_id: NodeId, is_method: bool, ) -> GenericsGenerationResults<'hir> { - let delegation_parent_kind = - self.tcx.def_kind(self.tcx.local_parent(self.local_def_id(item_id))); + let delegation_parent_kind = self.tcx.def_kind(self.tcx.local_parent(self.owner.def_id)); let segments = &delegation.path.segments; let len = segments.len(); diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ef9f1f10da8d2..a673069ae5a72 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -445,7 +445,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ty, ImplTraitContext::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias { - parent: this.local_def_id(id), + parent: this.owner.def_id, in_assoc_ty: false, }, }, @@ -598,7 +598,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ItemKind::MacroDef(ident, MacroDef { body, macro_rules, eii_declaration: _ }) => { let ident = self.lower_ident(*ident); let body = Box::new(self.lower_delim_args(body)); - let def_id = self.local_def_id(id); + let def_id = self.owner.def_id; let def_kind = self.tcx.def_kind(def_id); let DefKind::Macro(macro_kinds) = def_kind else { unreachable!( @@ -1282,7 +1282,7 @@ impl<'hir> LoweringContext<'_, 'hir> { ty, ImplTraitContext::OpaqueTy { origin: hir::OpaqueTyOrigin::TyAlias { - parent: this.local_def_id(i.id), + parent: this.owner.def_id, in_assoc_ty: true, }, }, diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 09ae64057af1a..3da133f5e1136 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -319,7 +319,7 @@ impl<'tcx> ResolverAstLowering<'tcx> { } fn owner_def_id(&self, id: NodeId) -> LocalDefId { - self.owners[&id].node_id_to_def_id[&id] + self.owners[&id].def_id } fn lifetime_elision_allowed(&self, id: NodeId) -> bool { @@ -694,7 +694,7 @@ impl<'hir> LoweringContext<'_, 'hir> { /// Given the id of an owner node in the AST, returns the corresponding `OwnerId`. fn owner_id(&self, node: NodeId) -> hir::OwnerId { - hir::OwnerId { def_id: self.resolver.owners[&node].node_id_to_def_id[&node] } + hir::OwnerId { def_id: self.resolver.owners[&node].def_id } } /// Freshen the `LoweringContext` and ready it to lower a nested item. @@ -1804,7 +1804,7 @@ impl<'hir> LoweringContext<'_, 'hir> { let output = match coro { Some(coro) => { - let fn_def_id = self.local_def_id(fn_node_id); + let fn_def_id = self.owner.def_id; self.lower_coroutine_fn_ret_ty(&decl.output, fn_def_id, coro, kind) } None => match &decl.output { @@ -1812,19 +1812,19 @@ impl<'hir> LoweringContext<'_, 'hir> { let itctx = match kind { FnDeclKind::Fn | FnDeclKind::Inherent => ImplTraitContext::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn { - parent: self.local_def_id(fn_node_id), + parent: self.owner.def_id, in_trait_or_impl: None, }, }, FnDeclKind::Trait => ImplTraitContext::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn { - parent: self.local_def_id(fn_node_id), + parent: self.owner.def_id, in_trait_or_impl: Some(hir::RpitContext::Trait), }, }, FnDeclKind::Impl => ImplTraitContext::OpaqueTy { origin: hir::OpaqueTyOrigin::FnReturn { - parent: self.local_def_id(fn_node_id), + parent: self.owner.def_id, in_trait_or_impl: Some(hir::RpitContext::TraitImpl), }, }, diff --git a/compiler/rustc_middle/src/ty/mod.rs b/compiler/rustc_middle/src/ty/mod.rs index 113fa9ec7c103..47d6802d8e873 100644 --- a/compiler/rustc_middle/src/ty/mod.rs +++ b/compiler/rustc_middle/src/ty/mod.rs @@ -203,11 +203,13 @@ pub struct PerOwnerResolverData { pub node_id_to_def_id: NodeMap, /// 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) -> PerOwnerResolverData { - PerOwnerResolverData { node_id_to_def_id: Default::default(), id } + pub fn new(id: ast::NodeId, def_id: LocalDefId) -> PerOwnerResolverData { + PerOwnerResolverData { node_id_to_def_id: Default::default(), id, def_id } } } diff --git a/compiler/rustc_passes/src/lang_items.rs b/compiler/rustc_passes/src/lang_items.rs index d6d21a8bcf104..c274ca48df622 100644 --- a/compiler/rustc_passes/src/lang_items.rs +++ b/compiler/rustc_passes/src/lang_items.rs @@ -295,7 +295,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { self.check_for_lang( target, - self.resolver.owners[&i.id].node_id_to_def_id[&i.id], + self.resolver.owners[&i.id].def_id, &i.attrs, i.span, i.opt_generics(), @@ -346,13 +346,7 @@ impl<'ast, 'tcx> visit::Visitor<'ast> for LanguageItemCollector<'ast, 'tcx> { } }; - self.check_for_lang( - target, - self.resolver.owners[&i.id].node_id_to_def_id[&i.id], - &i.attrs, - i.span, - generics, - ); + self.check_for_lang(target, self.resolver.owners[&i.id].def_id, &i.attrs, i.span, generics); visit::walk_assoc_item(self, i, ctxt); } diff --git a/compiler/rustc_resolve/src/build_reduced_graph.rs b/compiler/rustc_resolve/src/build_reduced_graph.rs index 283f443bb1f0d..43443e0ac3052 100644 --- a/compiler/rustc_resolve/src/build_reduced_graph.rs +++ b/compiler/rustc_resolve/src/build_reduced_graph.rs @@ -743,8 +743,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { } ast::UseTreeKind::Nested { ref items, .. } => { for &(ref tree, id) in items { - self.with_owner(id, |this| { - let feed = this.create_def(id, None, DefKind::Use, use_tree.span()); + self.with_owner(id, None, DefKind::Use, use_tree.span(), |this, feed| { this.build_reduced_graph_for_use_tree( // This particular use tree tree, id, &prefix, true, false, // The whole `use` item diff --git a/compiler/rustc_resolve/src/def_collector.rs b/compiler/rustc_resolve/src/def_collector.rs index 2a597f399402f..cdc2df5bf2945 100644 --- a/compiler/rustc_resolve/src/def_collector.rs +++ b/compiler/rustc_resolve/src/def_collector.rs @@ -32,7 +32,6 @@ pub(crate) fn collect_definitions<'ra>( with_owner(resolver, invocation_parent.owner, |r| { let mut visitor = DefCollector { r, invocation_parent, parent_scope }; fragment.visit_with(&mut visitor); - visitor.parent_scope.macro_rules }) } @@ -64,6 +63,7 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { def_kind, self.parent_scope.expansion.to_expn_id(), span.with_parent(None), + false, ) } @@ -73,23 +73,33 @@ impl<'a, 'ra, 'tcx> DefCollector<'a, 'ra, 'tcx> { self.invocation_parent.parent_def = orig_parent_def; } - pub(super) fn with_owner(&mut self, owner: NodeId, f: F) { + pub(super) fn with_owner)>( + &mut self, + owner: NodeId, + name: Option, + def_kind: DefKind, + span: Span, + f: F, + ) { debug_assert_ne!(owner, DUMMY_NODE_ID); - if owner == CRATE_NODE_ID { - // Special case: we always have an invocation parent (set in `collect_definitions`) - // of at least the crate root, even for visiting the crate root, - // which would then remove the crate root from the tables - // list twice and try to insert it twice afterwards. - debug_assert_eq!(self.r.current_owner.id, CRATE_NODE_ID); - return f(self); - } + debug_assert_ne!(owner, CRATE_NODE_ID); // We only get here if the owner didn't exist yet. After the owner has been created, // future invocations of `collect_definitions` will get the owner out of the `owners` // table. - let tables = PerOwnerResolverData::new(owner); + let parent_def = self.invocation_parent.parent_def; + let feed = self.r.create_def( + parent_def, + owner, + name, + def_kind, + self.parent_scope.expansion.to_expn_id(), + span.with_parent(None), + true, + ); + let tables = PerOwnerResolverData::new(owner, feed.key()); let orig_invoc_owner = mem::replace(&mut self.invocation_parent.owner, owner); - with_owner_tables(self, owner, tables, f); + with_owner_tables(self, owner, tables, |this| f(this, feed)); let old = mem::replace(&mut self.invocation_parent.owner, orig_invoc_owner); assert_eq!(old, owner); } @@ -200,8 +210,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } ItemKind::GlobalAsm(..) => DefKind::GlobalAsm, ItemKind::Use(_) => { - return self.with_owner(i.id, |this| { - let feed = this.create_def(i.id, None, DefKind::Use, i.span); + return self.with_owner(i.id, None, DefKind::Use, i.span, |this, feed| { this.brg_visit_item(i, feed); }); } @@ -212,20 +221,23 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } ItemKind::DelegationMac(..) => unreachable!(), }; - self.with_owner(i.id, |this| { - let feed = - this.create_def(i.id, i.kind.ident().map(|ident| ident.name), def_kind, i.span); - - if let Some(ext) = opt_syn_ext { - this.r.local_macro_map.insert(feed.def_id(), self.r.arenas.alloc_macro(ext)); - } + self.with_owner( + i.id, + i.kind.ident().map(|ident| ident.name), + def_kind, + i.span, + |this, feed| { + if let Some(ext) = opt_syn_ext { + this.r.local_macro_map.insert(feed.def_id(), self.r.arenas.alloc_macro(ext)); + } - this.with_parent(feed.def_id(), |this| { - this.with_impl_trait(ImplTraitContext::Existential, |this| { - this.brg_visit_item(i, feed) - }) - }); - }); + this.with_parent(feed.def_id(), |this| { + this.with_impl_trait(ImplTraitContext::Existential, |this| { + this.brg_visit_item(i, feed) + }) + }); + }, + ); } fn visit_block(&mut self, block: &'a Block) { @@ -316,9 +328,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } }; - self.with_owner(fi.id, |this| { - let def = this.create_def(fi.id, Some(ident.name), def_kind, fi.span); - + self.with_owner(fi.id, Some(ident.name), def_kind, fi.span, |this, def| { this.with_parent(def.def_id(), |this| { this.build_reduced_graph_for_foreign_item(fi, ident, def); visit::walk_item(this, fi) @@ -402,8 +412,7 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } }; - self.with_owner(i.id, |this| { - let feed = this.create_def(i.id, Some(ident.name), def_kind, i.span); + self.with_owner(i.id, Some(ident.name), def_kind, i.span, |this, feed| { this.with_parent(feed.def_id(), |this| { this.brg_visit_assoc_item(i, ctxt, ident, ns, feed) }); @@ -604,11 +613,16 @@ impl<'a, 'ra, 'tcx> visit::Visitor<'a> for DefCollector<'a, 'ra, 'tcx> { } else { // Visit attributes after items for backward compatibility. // This way they can use `macro_rules` defined later. - self.with_owner(CRATE_NODE_ID, |this| { - visit::walk_list!(this, visit_item, &krate.items); - visit::walk_list!(this, visit_attribute, &krate.attrs); - this.contains_macro_use(&krate.attrs); - }) + + // We always have an invocation parent (set in `collect_definitions`) + // of at least the crate root, even for visiting the crate root, + // which would then remove the crate root from the tables + // list twice and try to insert it twice afterwards. + debug_assert_eq!(self.r.current_owner.id, CRATE_NODE_ID); + + visit::walk_list!(self, visit_item, &krate.items); + visit::walk_list!(self, visit_attribute, &krate.attrs); + self.contains_macro_use(&krate.attrs); } } diff --git a/compiler/rustc_resolve/src/late.rs b/compiler/rustc_resolve/src/late.rs index 39cad6f3ff91b..664d1632fb59d 100644 --- a/compiler/rustc_resolve/src/late.rs +++ b/compiler/rustc_resolve/src/late.rs @@ -692,7 +692,11 @@ enum MaybeExported<'a> { impl MaybeExported<'_> { fn eval(self, r: &Resolver<'_, '_>) -> bool { let def_id = match self { - MaybeExported::Ok(node_id) => Some(r.local_def_id(node_id)), + MaybeExported::Ok(node_id) => Some(if r.current_owner.id == node_id { + r.current_owner.def_id + } else { + r.current_owner.node_id_to_def_id[&node_id] + }), MaybeExported::Impl(Some(trait_def_id)) | MaybeExported::ImplItem(Ok(trait_def_id)) => { trait_def_id.as_local() } @@ -1057,7 +1061,7 @@ impl<'ast, 'ra, 'tcx> Visitor<'ast> for LateResolutionVisitor<'_, 'ast, 'ra, 'tc fn visit_foreign_item(&mut self, foreign_item: &'ast ForeignItem) { with_owner(self, foreign_item.id, |this| { this.resolve_doc_links(&foreign_item.attrs, MaybeExported::Ok(foreign_item.id)); - let def_kind = this.r.local_def_kind(foreign_item.id); + let def_kind = this.r.tcx.def_kind(this.r.current_owner.def_id); match foreign_item.kind { ForeignItemKind::TyAlias(TyAlias { ref generics, .. }) => { this.with_generic_param_rib( @@ -2760,7 +2764,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { fn resolve_adt(&mut self, item: &'ast Item, generics: &'ast Generics) { debug!("resolve_adt"); - let kind = self.r.local_def_kind(item.id); + let kind = self.r.tcx.def_kind(self.r.current_owner.def_id); self.with_current_self_item(item, |this| { this.with_generic_param_rib( &generics.params, @@ -2769,7 +2773,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { LifetimeBinderKind::Item, generics.span, |this| { - let item_def_id = this.r.local_def_id(item.id).to_def_id(); + let item_def_id = this.r.current_owner.def_id.to_def_id(); this.with_self_rib( Res::SelfTyAlias { alias_to: item_def_id, is_trait_impl: false }, |this| { @@ -2830,7 +2834,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { debug!("(resolving item) resolving {:?} ({:?})", item.kind.ident(), item.kind); - let def_kind = self.r.local_def_kind(item.id); + let def_kind = self.r.tcx.def_kind(self.r.current_owner.def_id); match &item.kind { ItemKind::TyAlias(TyAlias { generics, .. }) => { self.with_generic_param_rib( @@ -2886,7 +2890,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { LifetimeBinderKind::Item, generics.span, |this| { - let local_def_id = this.r.local_def_id(item.id).to_def_id(); + let local_def_id = this.r.current_owner.def_id.to_def_id(); this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::SuperTraits); @@ -2905,7 +2909,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { LifetimeBinderKind::Item, generics.span, |this| { - let local_def_id = this.r.local_def_id(item.id).to_def_id(); + let local_def_id = this.r.current_owner.def_id.to_def_id(); this.with_self_rib(Res::SelfTyParam { trait_: local_def_id }, |this| { this.visit_generics(generics); walk_list!(this, visit_param_bound, bounds, BoundKind::Bound); @@ -2915,7 +2919,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { } ItemKind::Mod(..) => { - let module = self.r.expect_module(self.r.local_def_id(item.id).to_def_id()); + let module = self.r.expect_module(self.r.current_owner.def_id.to_def_id()); let orig_module = replace(&mut self.parent_scope.module, module); self.with_rib(ValueNS, RibKind::Module(module.expect_local()), |this| { this.with_rib(TypeNS, RibKind::Module(module.expect_local()), |this| { @@ -3041,7 +3045,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // Maintain macro_rules scopes in the same way as during early resolution // for diagnostics and doc links. if macro_def.macro_rules { - let def_id = self.r.local_def_id(item.id); + let def_id = self.r.current_owner.def_id; self.parent_scope.macro_rules = self.r.macro_rules_scopes[&def_id]; } @@ -3491,7 +3495,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // If applicable, create a rib for the type parameters. self.with_generic_param_rib( &generics.params, - RibKind::Item(HasGenericParams::Yes(generics.span), self.r.local_def_kind(item_id)), + RibKind::Item(HasGenericParams::Yes(generics.span), self.r.tcx.def_kind(self.r.current_owner.def_id)), item_id, LifetimeBinderKind::ImplBlock, generics.span, @@ -3511,7 +3515,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { |this, trait_id| { this.resolve_doc_links(attrs, MaybeExported::Impl(trait_id)); - let item_def_id = this.r.local_def_id(item_id); + let item_def_id = this.r.current_owner.def_id; // Register the trait definitions from here. if let Some(trait_id) = trait_id { @@ -3789,7 +3793,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { // HACK: because we don't want to track the `TyCtxtFeed` through the resolver to here // in a hash-map, we instead conjure a `TyCtxtFeed` for any `DefId` here, but prevent // it from being used generally. - this.r.tcx.feed_visibility_for_trait_impl_item(this.r.local_def_id(id), vis); + this.r.tcx.feed_visibility_for_trait_impl_item(this.r.current_owner.def_id, vis); }; let Some(decl) = decl else { @@ -3904,7 +3908,7 @@ impl<'a, 'ast, 'ra, 'tcx> LateResolutionVisitor<'a, 'ast, 'ra, 'tcx> { self.visit_path(&delegation.path); self.r.delegation_infos.insert( - self.r.local_def_id(item_id), + self.r.current_owner.def_id, DelegationInfo { resolution_node: if is_in_trait_impl { item_id } else { delegation.id }, }, diff --git a/compiler/rustc_resolve/src/late/diagnostics.rs b/compiler/rustc_resolve/src/late/diagnostics.rs index f600cbe5437fe..c83689f37da59 100644 --- a/compiler/rustc_resolve/src/late/diagnostics.rs +++ b/compiler/rustc_resolve/src/late/diagnostics.rs @@ -2778,8 +2778,9 @@ impl<'ast, 'ra, 'tcx> LateResolutionVisitor<'_, 'ast, 'ra, 'tcx> { ast::AssocItemKind::Delegation(..) if self .r - .delegation_fn_sigs - .get(&self.r.local_def_id(assoc_item.id)) + .owners + .get(&assoc_item.id) + .and_then(|o| self.r.delegation_fn_sigs.get(&o.def_id)) .is_some_and(|sig| sig.has_self) => { AssocSuggestion::MethodWithSelf { called } diff --git a/compiler/rustc_resolve/src/lib.rs b/compiler/rustc_resolve/src/lib.rs index f0918fa4939a3..efe973c4a7064 100644 --- a/compiler/rustc_resolve/src/lib.rs +++ b/compiler/rustc_resolve/src/lib.rs @@ -46,7 +46,7 @@ use rustc_data_structures::fx::{FxHashMap, FxHashSet, FxIndexMap, FxIndexSet, de use rustc_data_structures::intern::Interned; use rustc_data_structures::steal::Steal; use rustc_data_structures::sync::{FreezeReadGuard, FreezeWriteGuard}; -use rustc_data_structures::unord::{UnordMap, UnordSet}; +use rustc_data_structures::unord::{UnordItems, UnordMap, UnordSet}; use rustc_errors::{Applicability, Diag, ErrCode, ErrorGuaranteed, LintBuffer}; use rustc_expand::base::{DeriveResolution, SyntaxExtension, SyntaxExtensionKind}; use rustc_feature::BUILTIN_ATTRIBUTES; @@ -1648,8 +1648,8 @@ impl<'tcx> Resolver<'_, 'tcx> { /// Only call this in analyses after the resolver has finished. /// Panics if the node id is currently not in the owner storage, /// e.g. because it's further up in the current visitor stack. - fn owner_def_id(&self, node: NodeId) -> LocalDefId { - self.child_def_id(node, node) + fn owner_def_id(&self, owner: NodeId) -> LocalDefId { + self.owners[&owner].def_id } /// Only call this in analyses after the resolver has finished. @@ -1669,10 +1669,6 @@ impl<'tcx> Resolver<'_, 'tcx> { self.opt_local_def_id(node).unwrap_or_else(|| panic!("no entry for node id: `{node:?}`")) } - fn local_def_kind(&self, node: NodeId) -> DefKind { - self.tcx.def_kind(self.local_def_id(node)) - } - /// Adds a definition with a parent definition. fn create_def( &mut self, @@ -1682,6 +1678,7 @@ impl<'tcx> Resolver<'_, 'tcx> { def_kind: DefKind, expn_id: ExpnId, span: Span, + is_owner: bool, ) -> TyCtxtFeed<'tcx, LocalDefId> { assert!( !self.current_owner.node_id_to_def_id.contains_key(&node_id), @@ -1713,7 +1710,7 @@ impl<'tcx> Resolver<'_, 'tcx> { // Some things for which we allocate `LocalDefId`s don't correspond to // anything in the AST, so they don't have a `NodeId`. For these cases // we don't need a mapping from `NodeId` to `LocalDefId`. - if node_id != ast::DUMMY_NODE_ID { + if node_id != ast::DUMMY_NODE_ID && !is_owner { debug!("create_def: def_id_to_node_id[{:?}] <-> {:?}", def_id, node_id); self.current_owner.node_id_to_def_id.insert(node_id, def_id); } @@ -1768,7 +1765,11 @@ impl<'tcx> Resolver<'_, 'tcx> { fn def_id_to_node_id(&self, def_id: LocalDefId) -> NodeId { self.owners .items() - .flat_map(|(_, data)| data.node_id_to_def_id.items()) + .flat_map(|(_, data)| { + data.node_id_to_def_id + .items() + .chain(UnordItems::new([(&data.id, &data.def_id)].into_iter())) + }) .filter(|(_, v)| **v == def_id) .map(|(k, _)| *k) .get_only() @@ -1806,11 +1807,10 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { arenas, ); - let mut owner_data = PerOwnerResolverData::new(CRATE_NODE_ID); + let owner_data = PerOwnerResolverData::new(CRATE_NODE_ID, CRATE_DEF_ID); let crate_feed = tcx.create_local_crate_def_id(crate_span); crate_feed.def_kind(DefKind::Mod); - owner_data.node_id_to_def_id.insert(CRATE_NODE_ID, crate_feed.key()); let mut owners = NodeMap::default(); owners.insert(CRATE_NODE_ID, owner_data); @@ -1876,7 +1876,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { multi_segment_macro_resolutions: Default::default(), lint_buffer: LintBuffer::default(), owners, - current_owner: PerOwnerResolverData::new(DUMMY_NODE_ID), + current_owner: PerOwnerResolverData::new(DUMMY_NODE_ID, CRATE_DEF_ID), invocation_parents, trait_impls: Default::default(), confused_type_with_std_module: Default::default(), @@ -1978,12 +1978,7 @@ impl<'ra, 'tcx> Resolver<'ra, 'tcx> { .stripped_cfg_items .into_iter() .filter_map(|item| { - let parent_scope = self - .owners - .get(&item.parent_scope)? - .node_id_to_def_id - .get(&item.parent_scope)? - .to_def_id(); + let parent_scope = self.owners.get(&item.parent_scope)?.def_id.to_def_id(); Some(StrippedCfgItem { parent_scope, ident: item.ident, cfg: item.cfg }) }) .collect(); diff --git a/compiler/rustc_resolve/src/macros.rs b/compiler/rustc_resolve/src/macros.rs index ee45edda12f9c..d1822b1cb15e4 100644 --- a/compiler/rustc_resolve/src/macros.rs +++ b/compiler/rustc_resolve/src/macros.rs @@ -165,7 +165,7 @@ impl<'ra, 'tcx> ResolverExpand for Resolver<'ra, 'tcx> { } fn mark_scope_with_compile_error(&mut self, id: NodeId) { - if let Some(id) = self.owners.get(&id).map(|i| i.node_id_to_def_id[&id]) + if let Some(id) = self.owners.get(&id).map(|i| i.def_id) && self.tcx.def_kind(id).is_module_like() { self.mods_with_parse_errors.insert(id.to_def_id());