diff --git a/compiler/rustc_ast_lowering/src/item.rs b/compiler/rustc_ast_lowering/src/item.rs index ed3abbd5b4d3d..8b4a0840df583 100644 --- a/compiler/rustc_ast_lowering/src/item.rs +++ b/compiler/rustc_ast_lowering/src/item.rs @@ -105,12 +105,11 @@ impl<'hir> LoweringContext<'_, 'hir> { ) -> T { let old_len = self.in_scope_lifetimes.len(); - let parent_generics = - match self.owners[parent_hir_id].as_ref().unwrap().node().expect_item().kind { - hir::ItemKind::Impl(hir::Impl { ref generics, .. }) - | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params, - _ => &[], - }; + let parent_generics = match self.owners[parent_hir_id].unwrap().node().expect_item().kind { + hir::ItemKind::Impl(hir::Impl { ref generics, .. }) + | hir::ItemKind::Trait(_, _, ref generics, ..) => generics.params, + _ => &[], + }; let lt_def_names = parent_generics.iter().filter_map(|param| match param.kind { hir::GenericParamKind::Lifetime { .. } => Some(param.name.normalize_to_macros_2_0()), _ => None, @@ -480,6 +479,12 @@ impl<'hir> LoweringContext<'_, 'hir> { .node_id_to_hir_id .insert(new_node_id, hir::HirId::make_owner(new_id)); debug_assert!(_old.is_none()); + self.owners.ensure_contains_elem(new_id, || hir::MaybeOwner::Phantom); + let _old = std::mem::replace( + &mut self.owners[new_id], + hir::MaybeOwner::NonOwner(hir::HirId::make_owner(new_id)), + ); + debug_assert!(matches!(_old, hir::MaybeOwner::Phantom)); continue; }; let ident = *ident; diff --git a/compiler/rustc_ast_lowering/src/lib.rs b/compiler/rustc_ast_lowering/src/lib.rs index 32cec3a295a4e..f21f0b895adb6 100644 --- a/compiler/rustc_ast_lowering/src/lib.rs +++ b/compiler/rustc_ast_lowering/src/lib.rs @@ -98,7 +98,7 @@ struct LoweringContext<'a, 'hir: 'a> { arena: &'hir Arena<'hir>, /// The items being lowered are collected here. - owners: IndexVec>>, + owners: IndexVec>>, /// Bodies inside the owner being lowered. bodies: Vec<(hir::ItemLocalId, &'hir hir::Body<'hir>)>, /// Attributes inside the owner being lowered. @@ -291,7 +291,8 @@ pub fn lower_crate<'a, 'hir>( ) -> &'hir hir::Crate<'hir> { let _prof_timer = sess.prof.verbose_generic_activity("hir_lowering"); - let owners = IndexVec::from_fn_n(|_| None, resolver.definitions().def_index_count()); + let owners = + IndexVec::from_fn_n(|_| hir::MaybeOwner::Phantom, resolver.definitions().def_index_count()); LoweringContext { sess, resolver, @@ -402,19 +403,6 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { let hir_hash = self.compute_hir_hash(); - let mut def_id_to_hir_id = IndexVec::default(); - - for (node_id, hir_id) in self.node_id_to_hir_id.into_iter_enumerated() { - if let Some(def_id) = self.resolver.opt_local_def_id(node_id) { - if def_id_to_hir_id.len() <= def_id.index() { - def_id_to_hir_id.resize(def_id.index() + 1, None); - } - def_id_to_hir_id[def_id] = hir_id; - } - } - - self.resolver.definitions().init_def_id_to_hir_id_mapping(def_id_to_hir_id); - let krate = hir::Crate { owners: self.owners, hir_hash }; self.arena.alloc(krate) } @@ -427,7 +415,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { .owners .iter_enumerated() .filter_map(|(def_id, info)| { - let info = info.as_ref()?; + let info = info.as_owner()?; let def_path_hash = definitions.def_path_hash(def_id); Some((def_path_hash, info)) }) @@ -469,8 +457,8 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { self.current_hir_id_owner = current_owner; self.item_local_id_counter = current_local_counter; - let _old = self.owners.insert(def_id, info); - debug_assert!(_old.is_none()); + self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); + self.owners[def_id] = hir::MaybeOwner::Owner(self.arena.alloc(info)); def_id } @@ -488,6 +476,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> { None } else { let def_id = self.resolver.opt_local_def_id(node_id)?; + self.owners.ensure_contains_elem(def_id, || hir::MaybeOwner::Phantom); + if let o @ hir::MaybeOwner::Phantom = &mut self.owners[def_id] { + // Do not override a `MaybeOwner::Owner` that may already here. + *o = hir::MaybeOwner::NonOwner(hir_id); + } Some((hir_id.local_id, def_id)) } }) diff --git a/compiler/rustc_hir/src/definitions.rs b/compiler/rustc_hir/src/definitions.rs index 74d6b05ca5fc5..d655f12f5e1d1 100644 --- a/compiler/rustc_hir/src/definitions.rs +++ b/compiler/rustc_hir/src/definitions.rs @@ -7,7 +7,6 @@ pub use crate::def_id::DefPathHash; use crate::def_id::{CrateNum, DefIndex, LocalDefId, StableCrateId, CRATE_DEF_INDEX, LOCAL_CRATE}; use crate::def_path_hash_map::DefPathHashMap; -use crate::hir; use rustc_data_structures::fx::FxHashMap; use rustc_data_structures::stable_hasher::StableHasher; @@ -101,13 +100,6 @@ impl DefPathTable { pub struct Definitions { table: DefPathTable, - /// Only [`LocalDefId`]s for items and item-like are HIR owners. - /// The associated `HirId` has a `local_id` of `0`. - /// Generic parameters and closures are also assigned a `LocalDefId` but are not HIR owners. - /// Their `HirId`s are defined by their position while lowering the enclosing owner. - // FIXME(cjgillot) Some `LocalDefId`s from `use` items are dropped during lowering and lack a `HirId`. - pub(super) def_id_to_hir_id: IndexVec>, - /// Item with a given `LocalDefId` was defined during macro expansion with ID `ExpnId`. expansions_that_defined: FxHashMap, @@ -322,12 +314,6 @@ impl Definitions { }) } - #[inline] - #[track_caller] - pub fn local_def_id_to_hir_id(&self, id: LocalDefId) -> hir::HirId { - self.def_id_to_hir_id[id].unwrap() - } - /// Adds a root definition (no parent) and a few other reserved definitions. pub fn new(stable_crate_id: StableCrateId, crate_span: Span) -> Definitions { let key = DefKey { @@ -354,7 +340,6 @@ impl Definitions { Definitions { table, - def_id_to_hir_id: Default::default(), expansions_that_defined: Default::default(), def_id_to_span, stable_crate_id, @@ -406,20 +391,6 @@ impl Definitions { def_id } - /// Initializes the `LocalDefId` to `HirId` mapping once it has been generated during - /// AST to HIR lowering. - pub fn init_def_id_to_hir_id_mapping( - &mut self, - mapping: IndexVec>, - ) { - assert!( - self.def_id_to_hir_id.is_empty(), - "trying to initialize `LocalDefId` <-> `HirId` mappings twice" - ); - - self.def_id_to_hir_id = mapping; - } - pub fn expansion_that_defined(&self, id: LocalDefId) -> ExpnId { self.expansions_that_defined.get(&id).copied().unwrap_or_else(ExpnId::root) } @@ -431,7 +402,7 @@ impl Definitions { } pub fn iter_local_def_id(&self) -> impl Iterator + '_ { - self.def_id_to_hir_id.iter_enumerated().map(|(k, _)| k) + self.table.def_path_hashes.indices().map(|local_def_index| LocalDefId { local_def_index }) } #[inline(always)] diff --git a/compiler/rustc_hir/src/hir.rs b/compiler/rustc_hir/src/hir.rs index a0ed72c9e9e50..67398c80f360c 100644 --- a/compiler/rustc_hir/src/hir.rs +++ b/compiler/rustc_hir/src/hir.rs @@ -711,6 +711,15 @@ pub struct OwnerNodes<'tcx> { pub local_id_to_def_id: SortedMap, } +impl<'tcx> OwnerNodes<'tcx> { + pub fn node(&self) -> OwnerNode<'tcx> { + use rustc_index::vec::Idx; + let node = self.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; + let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. + node + } +} + /// Full information resulting from lowering an AST node. #[derive(Debug, HashStable_Generic)] pub struct OwnerInfo<'hir> { @@ -728,10 +737,39 @@ pub struct OwnerInfo<'hir> { impl<'tcx> OwnerInfo<'tcx> { #[inline] pub fn node(&self) -> OwnerNode<'tcx> { - use rustc_index::vec::Idx; - let node = self.nodes.nodes[ItemLocalId::new(0)].as_ref().unwrap().node; - let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode. - node + self.nodes.node() + } +} + +#[derive(Copy, Clone, Debug, HashStable_Generic)] +pub enum MaybeOwner { + Owner(T), + NonOwner(HirId), + /// Used as a placeholder for unused LocalDefId. + Phantom, +} + +impl MaybeOwner { + pub fn as_owner(self) -> Option { + match self { + MaybeOwner::Owner(i) => Some(i), + MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => None, + } + } + + pub fn map(self, f: impl FnOnce(T) -> U) -> MaybeOwner { + match self { + MaybeOwner::Owner(i) => MaybeOwner::Owner(f(i)), + MaybeOwner::NonOwner(hir_id) => MaybeOwner::NonOwner(hir_id), + MaybeOwner::Phantom => MaybeOwner::Phantom, + } + } + + pub fn unwrap(self) -> T { + match self { + MaybeOwner::Owner(i) => i, + MaybeOwner::NonOwner(_) | MaybeOwner::Phantom => panic!("Not a HIR owner"), + } } } @@ -743,7 +781,7 @@ impl<'tcx> OwnerInfo<'tcx> { /// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html #[derive(Debug)] pub struct Crate<'hir> { - pub owners: IndexVec>>, + pub owners: IndexVec>>, pub hir_hash: Fingerprint, } diff --git a/compiler/rustc_hir/src/hir_id.rs b/compiler/rustc_hir/src/hir_id.rs index 5b486819c35e8..dee391b9cce21 100644 --- a/compiler/rustc_hir/src/hir_id.rs +++ b/compiler/rustc_hir/src/hir_id.rs @@ -30,6 +30,11 @@ impl HirId { if self.local_id.index() == 0 { Some(self.owner) } else { None } } + #[inline] + pub fn is_owner(self) -> bool { + self.local_id.index() == 0 + } + #[inline] pub fn make_owner(owner: LocalDefId) -> Self { Self { owner, local_id: ItemLocalId::from_u32(0) } diff --git a/compiler/rustc_middle/src/hir/map/mod.rs b/compiler/rustc_middle/src/hir/map/mod.rs index 1885df6ac5d96..649cb34bd5f3c 100644 --- a/compiler/rustc_middle/src/hir/map/mod.rs +++ b/compiler/rustc_middle/src/hir/map/mod.rs @@ -162,7 +162,7 @@ impl<'hir> Map<'hir> { pub fn items(&self) -> impl Iterator> + 'hir { let krate = self.krate(); - krate.owners.iter().filter_map(|owner| match owner.as_ref()?.node() { + krate.owners.iter().filter_map(|owner| match owner.as_owner()?.node() { OwnerNode::Item(item) => Some(item), _ => None, }) @@ -205,7 +205,8 @@ impl<'hir> Map<'hir> { Some(hir_id.owner) } else { self.tcx - .hir_owner_nodes(hir_id.owner)? + .hir_owner_nodes(hir_id.owner) + .as_owner()? .local_id_to_def_id .get(&hir_id.local_id) .copied() @@ -214,8 +215,7 @@ impl<'hir> Map<'hir> { #[inline] pub fn local_def_id_to_hir_id(&self, def_id: LocalDefId) -> HirId { - // FIXME(#85914) is this access safe for incr. comp.? - self.tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id) + self.tcx.local_def_id_to_hir_id(def_id) } pub fn iter_local_def_id(&self) -> impl Iterator + '_ { @@ -321,7 +321,7 @@ impl<'hir> Map<'hir> { if id.local_id == ItemLocalId::from_u32(0) { Some(self.tcx.hir_owner_parent(id.owner)) } else { - let owner = self.tcx.hir_owner_nodes(id.owner)?; + let owner = self.tcx.hir_owner_nodes(id.owner).as_owner()?; let node = owner.nodes[id.local_id].as_ref()?; let hir_id = HirId { owner: id.owner, local_id: node.parent }; Some(hir_id) @@ -338,7 +338,7 @@ impl<'hir> Map<'hir> { let owner = self.tcx.hir_owner(id.owner)?; Some(owner.node.into()) } else { - let owner = self.tcx.hir_owner_nodes(id.owner)?; + let owner = self.tcx.hir_owner_nodes(id.owner).as_owner()?; let node = owner.nodes[id.local_id].as_ref()?; Some(node.node) } @@ -522,7 +522,7 @@ impl<'hir> Map<'hir> { .owners .iter_enumerated() .flat_map(move |(owner, owner_info)| { - let bodies = &owner_info.as_ref()?.nodes.bodies; + let bodies = &owner_info.as_owner()?.nodes.bodies; Some(bodies.iter().map(move |&(local_id, _)| { let hir_id = HirId { owner, local_id }; let body_id = BodyId { hir_id }; @@ -539,7 +539,7 @@ impl<'hir> Map<'hir> { par_iter(&self.krate().owners.raw).enumerate().for_each(|(owner, owner_info)| { let owner = LocalDefId::new(owner); - if let Some(owner_info) = owner_info { + if let MaybeOwner::Owner(owner_info) = owner_info { par_iter(owner_info.nodes.bodies.range(..)).for_each(|(local_id, _)| { let hir_id = HirId { owner, local_id: *local_id }; let body_id = BodyId { hir_id }; @@ -601,7 +601,7 @@ impl<'hir> Map<'hir> { pub fn walk_attributes(self, visitor: &mut impl Visitor<'hir>) { let krate = self.krate(); for (owner, info) in krate.owners.iter_enumerated() { - if let Some(info) = info { + if let MaybeOwner::Owner(info) = info { for (local_id, attrs) in info.attrs.map.iter() { let id = HirId { owner, local_id: *local_id }; for a in *attrs { @@ -625,7 +625,7 @@ impl<'hir> Map<'hir> { V: itemlikevisit::ItemLikeVisitor<'hir>, { let krate = self.krate(); - for owner in krate.owners.iter().filter_map(Option::as_ref) { + for owner in krate.owners.iter().filter_map(|i| i.as_owner()) { match owner.node() { OwnerNode::Item(item) => visitor.visit_item(item), OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item), @@ -642,12 +642,14 @@ impl<'hir> Map<'hir> { V: itemlikevisit::ParItemLikeVisitor<'hir> + Sync + Send, { let krate = self.krate(); - par_for_each_in(&krate.owners.raw, |owner| match owner.as_ref().map(OwnerInfo::node) { - Some(OwnerNode::Item(item)) => visitor.visit_item(item), - Some(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item), - Some(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item), - Some(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), - Some(OwnerNode::Crate(_)) | None => {} + par_for_each_in(&krate.owners.raw, |owner| match owner.map(OwnerInfo::node) { + MaybeOwner::Owner(OwnerNode::Item(item)) => visitor.visit_item(item), + MaybeOwner::Owner(OwnerNode::ForeignItem(item)) => visitor.visit_foreign_item(item), + MaybeOwner::Owner(OwnerNode::ImplItem(item)) => visitor.visit_impl_item(item), + MaybeOwner::Owner(OwnerNode::TraitItem(item)) => visitor.visit_trait_item(item), + MaybeOwner::Owner(OwnerNode::Crate(_)) + | MaybeOwner::NonOwner(_) + | MaybeOwner::Phantom => {} }) } @@ -1121,7 +1123,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh { .owners .iter_enumerated() .filter_map(|(def_id, info)| { - let _ = info.as_ref()?; + let _ = info.as_owner()?; let def_path_hash = definitions.def_path_hash(def_id); let span = definitions.def_span(def_id); debug_assert_eq!(span.parent(), None); diff --git a/compiler/rustc_middle/src/hir/mod.rs b/compiler/rustc_middle/src/hir/mod.rs index b4c7bb7eba79c..1053f0cefbedd 100644 --- a/compiler/rustc_middle/src/hir/mod.rs +++ b/compiler/rustc_middle/src/hir/mod.rs @@ -65,20 +65,27 @@ pub fn provide(providers: &mut Providers) { providers.crate_hash = map::crate_hash; providers.hir_module_items = map::hir_module_items; providers.hir_owner = |tcx, id| { - let owner = tcx.hir_crate(()).owners.get(id)?.as_ref()?; + let owner = tcx.hir_crate(()).owners.get(id)?.as_owner()?; let node = owner.node(); Some(Owner { node, hash_without_bodies: owner.nodes.hash_without_bodies }) }; - providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|i| &i.nodes); + providers.local_def_id_to_hir_id = |tcx, id| { + let owner = tcx.hir_crate(()).owners[id].map(|_| ()); + match owner { + MaybeOwner::Owner(_) => HirId::make_owner(id), + MaybeOwner::Phantom => bug!("No HirId for {:?}", id), + MaybeOwner::NonOwner(hir_id) => hir_id, + } + }; + providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].map(|i| &i.nodes); providers.hir_owner_parent = |tcx, id| { // Accessing the def_key is ok since its value is hashed as part of `id`'s DefPathHash. let parent = tcx.untracked_resolutions.definitions.def_key(id).parent; let parent = parent.map_or(CRATE_HIR_ID, |local_def_index| { let def_id = LocalDefId { local_def_index }; - let mut parent_hir_id = - tcx.untracked_resolutions.definitions.local_def_id_to_hir_id(def_id); + let mut parent_hir_id = tcx.hir().local_def_id_to_hir_id(def_id); if let Some(local_id) = - tcx.hir_crate(()).owners[parent_hir_id.owner].as_ref().unwrap().parenting.get(&id) + tcx.hir_crate(()).owners[parent_hir_id.owner].unwrap().parenting.get(&id) { parent_hir_id.local_id = *local_id; } @@ -87,7 +94,7 @@ pub fn provide(providers: &mut Providers) { parent }; providers.hir_attrs = - |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map_or(AttributeMap::EMPTY, |o| &o.attrs); + |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map_or(AttributeMap::EMPTY, |o| &o.attrs); providers.source_span = |tcx, def_id| tcx.resolutions(()).definitions.def_span(def_id); providers.def_span = |tcx, def_id| tcx.hir().span_if_local(def_id).unwrap_or(DUMMY_SP); providers.fn_arg_names = |tcx, id| { @@ -111,4 +118,6 @@ pub fn provide(providers: &mut Providers) { let id = id.expect_local(); tcx.resolutions(()).definitions.expansion_that_defined(id) }; + providers.in_scope_traits_map = + |tcx, id| tcx.hir_crate(()).owners[id].as_owner().map(|owner_info| &owner_info.trait_map); } diff --git a/compiler/rustc_middle/src/query/mod.rs b/compiler/rustc_middle/src/query/mod.rs index 715a1fa25a1c6..c01e7177760f9 100644 --- a/compiler/rustc_middle/src/query/mod.rs +++ b/compiler/rustc_middle/src/query/mod.rs @@ -56,6 +56,14 @@ rustc_queries! { desc { |tcx| "HIR owner of `{}`", tcx.def_path_str(key.to_def_id()) } } + /// Gives access to the HIR ID for the given `LocalDefId` owner `key`. + /// + /// This can be conveniently accessed by methods on `tcx.hir()`. + /// Avoid calling this query directly. + query local_def_id_to_hir_id(key: LocalDefId) -> hir::HirId { + desc { |tcx| "HIR ID of `{}`", tcx.def_path_str(key.to_def_id()) } + } + /// Gives access to the HIR node's parent for the HIR owner `key`. /// /// This can be conveniently accessed by methods on `tcx.hir()`. @@ -68,7 +76,7 @@ rustc_queries! { /// /// This can be conveniently accessed by methods on `tcx.hir()`. /// Avoid calling this query directly. - query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> { + query hir_owner_nodes(key: LocalDefId) -> hir::MaybeOwner<&'tcx hir::OwnerNodes<'tcx>> { desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) } } diff --git a/compiler/rustc_middle/src/ty/context.rs b/compiler/rustc_middle/src/ty/context.rs index 6c8573805cb94..75f1318e36314 100644 --- a/compiler/rustc_middle/src/ty/context.rs +++ b/compiler/rustc_middle/src/ty/context.rs @@ -2875,8 +2875,6 @@ fn ptr_eq(t: *const T, u: *const U) -> bool { } pub fn provide(providers: &mut ty::query::Providers) { - providers.in_scope_traits_map = - |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|owner_info| &owner_info.trait_map); providers.resolutions = |tcx, ()| &tcx.untracked_resolutions; providers.module_reexports = |tcx, id| tcx.resolutions(()).reexport_map.get(&id).map(|v| &v[..]); diff --git a/compiler/rustc_mir_transform/src/coverage/mod.rs b/compiler/rustc_mir_transform/src/coverage/mod.rs index 82455654a8860..2bb9f48f9b7c8 100644 --- a/compiler/rustc_mir_transform/src/coverage/mod.rs +++ b/compiler/rustc_mir_transform/src/coverage/mod.rs @@ -579,7 +579,7 @@ fn hash_mir_source<'tcx>(tcx: TyCtxt<'tcx>, hir_body: &'tcx rustc_hir::Body<'tcx let mut hcx = tcx.create_no_span_stable_hashing_context(); let mut stable_hasher = StableHasher::new(); let owner = hir_body.id().hir_id.owner; - let bodies = &tcx.hir_owner_nodes(owner).as_ref().unwrap().bodies; + let bodies = &tcx.hir_owner_nodes(owner).unwrap().bodies; hcx.with_hir_bodies(false, owner, bodies, |hcx| { hir_body.value.hash_stable(hcx, &mut stable_hasher) }); diff --git a/compiler/rustc_resolve/src/late/lifetimes.rs b/compiler/rustc_resolve/src/late/lifetimes.rs index 4c7bdb33fb87a..6ef85c426be70 100644 --- a/compiler/rustc_resolve/src/late/lifetimes.rs +++ b/compiler/rustc_resolve/src/late/lifetimes.rs @@ -1019,15 +1019,7 @@ impl<'a, 'tcx> Visitor<'tcx> for LifetimeContext<'a, 'tcx> { let hir_id = self.tcx.hir().local_def_id_to_hir_id(def_id); // Ensure that the parent of the def is an item, not HRTB let parent_id = self.tcx.hir().get_parent_node(hir_id); - // FIXME(cjgillot) Can this check be replaced by - // `let parent_is_item = parent_id.is_owner();`? - let parent_is_item = if let Some(parent_def_id) = parent_id.as_owner() { - matches!(self.tcx.hir().krate().owners.get(parent_def_id), Some(Some(_)),) - } else { - false - }; - - if !parent_is_item { + if !parent_id.is_owner() { if !self.trait_definition_only { struct_span_err!( self.tcx.sess,