Perform indexing during lowering.
Do not access DefId<->HirId maps before they are initialized.
This commit is contained in:
parent
c09eaea484
commit
1c7f85f17c
@ -1,5 +1,3 @@
|
||||
use crate::hir::map::Map;
|
||||
use crate::hir::{IndexedHir, OwnerNodes, ParentedNode};
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_hir as hir;
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
@ -12,16 +10,16 @@ use rustc_span::source_map::SourceMap;
|
||||
use rustc_span::{Span, DUMMY_SP};
|
||||
|
||||
use std::iter::repeat;
|
||||
use tracing::debug;
|
||||
|
||||
/// A visitor that walks over the HIR and collects `Node`s into a HIR map.
|
||||
pub(super) struct NodeCollector<'a, 'hir> {
|
||||
/// The crate
|
||||
krate: &'hir Crate<'hir>,
|
||||
|
||||
/// Source map
|
||||
source_map: &'a SourceMap,
|
||||
bodies: &'a IndexVec<ItemLocalId, Option<&'hir Body<'hir>>>,
|
||||
|
||||
nodes: OwnerNodes<'hir>,
|
||||
/// Outputs
|
||||
nodes: IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>,
|
||||
parenting: FxHashMap<LocalDefId, ItemLocalId>,
|
||||
|
||||
/// The parent of this node
|
||||
@ -42,28 +40,21 @@ fn insert_vec_map<K: Idx, V: Clone>(map: &mut IndexVec<K, Option<V>>, k: K, v: V
|
||||
map[k] = Some(v);
|
||||
}
|
||||
|
||||
pub(super) fn collect<'a, 'hir: 'a>(
|
||||
sess: &'a Session,
|
||||
krate: &'hir Crate<'hir>,
|
||||
definitions: &'a definitions::Definitions,
|
||||
owner: LocalDefId,
|
||||
) -> Option<IndexedHir<'hir>> {
|
||||
let info = krate.owners.get(owner)?.as_ref()?;
|
||||
let item = info.node;
|
||||
pub(super) fn index_hir<'hir>(
|
||||
sess: &Session,
|
||||
definitions: &definitions::Definitions,
|
||||
item: hir::OwnerNode<'hir>,
|
||||
bodies: &IndexVec<ItemLocalId, Option<&'hir Body<'hir>>>,
|
||||
) -> (IndexVec<ItemLocalId, Option<ParentedNode<'hir>>>, FxHashMap<LocalDefId, ItemLocalId>) {
|
||||
let mut nodes = IndexVec::new();
|
||||
nodes.push(Some(ParentedNode { parent: ItemLocalId::new(0), node: item.into() }));
|
||||
let mut collector = NodeCollector {
|
||||
krate,
|
||||
source_map: sess.source_map(),
|
||||
owner,
|
||||
parent_node: ItemLocalId::new(0),
|
||||
definitions,
|
||||
nodes: OwnerNodes {
|
||||
hash: info.hash,
|
||||
node_hash: info.node_hash,
|
||||
nodes,
|
||||
bodies: &info.bodies,
|
||||
},
|
||||
owner: item.def_id(),
|
||||
parent_node: ItemLocalId::new(0),
|
||||
nodes,
|
||||
bodies,
|
||||
parenting: FxHashMap::default(),
|
||||
};
|
||||
|
||||
@ -75,7 +66,7 @@ pub(super) fn collect<'a, 'hir: 'a>(
|
||||
OwnerNode::ForeignItem(item) => collector.visit_foreign_item(item),
|
||||
};
|
||||
|
||||
Some(IndexedHir { nodes: collector.nodes, parenting: collector.parenting })
|
||||
(collector.nodes, collector.parenting)
|
||||
}
|
||||
|
||||
impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||
@ -87,17 +78,11 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||
// owner of that node.
|
||||
if cfg!(debug_assertions) {
|
||||
if hir_id.owner != self.owner {
|
||||
let node_str = match self.definitions.opt_hir_id_to_local_def_id(hir_id) {
|
||||
Some(def_id) => self.definitions.def_path(def_id).to_string_no_crate_verbose(),
|
||||
None => format!("{:?}", node),
|
||||
};
|
||||
|
||||
span_bug!(
|
||||
span,
|
||||
"inconsistent DepNode at `{:?}` for `{}`: \
|
||||
panic!(
|
||||
"inconsistent DepNode at `{:?}` for `{:?}`: \
|
||||
current_dep_node_owner={} ({:?}), hir_id.owner={} ({:?})",
|
||||
self.source_map.span_to_diagnostic_string(span),
|
||||
node_str,
|
||||
node,
|
||||
self.definitions.def_path(self.owner).to_string_no_crate_verbose(),
|
||||
self.owner,
|
||||
self.definitions.def_path(hir_id.owner).to_string_no_crate_verbose(),
|
||||
@ -107,7 +92,7 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||
}
|
||||
|
||||
insert_vec_map(
|
||||
&mut self.nodes.nodes,
|
||||
&mut self.nodes,
|
||||
hir_id.local_id,
|
||||
ParentedNode { parent: self.parent_node, node: node },
|
||||
);
|
||||
@ -122,18 +107,12 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
|
||||
}
|
||||
|
||||
fn insert_nested(&mut self, item: LocalDefId) {
|
||||
let dk_parent = self.definitions.def_key(item).parent.unwrap();
|
||||
let dk_parent = LocalDefId { local_def_index: dk_parent };
|
||||
let dk_parent = self.definitions.local_def_id_to_hir_id(dk_parent);
|
||||
debug_assert_eq!(dk_parent.owner, self.owner, "Different parents for {:?}", item);
|
||||
if dk_parent.local_id != self.parent_node {
|
||||
self.parenting.insert(item, self.parent_node);
|
||||
}
|
||||
self.parenting.insert(item, self.parent_node);
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
type Map = Map<'hir>;
|
||||
type Map = !;
|
||||
|
||||
/// Because we want to track parent items and so forth, enable
|
||||
/// deep walking so that we walk nested items in the context of
|
||||
@ -161,8 +140,8 @@ impl<'a, 'hir> Visitor<'hir> for NodeCollector<'a, 'hir> {
|
||||
}
|
||||
|
||||
fn visit_nested_body(&mut self, id: BodyId) {
|
||||
let body = self.krate.body(id);
|
||||
debug_assert_eq!(id.hir_id.owner, self.owner);
|
||||
let body = self.bodies[id.hir_id.local_id].unwrap();
|
||||
self.visit_body(body);
|
||||
}
|
||||
|
@ -101,7 +101,7 @@ impl<'hir> LoweringContext<'_, 'hir> {
|
||||
let old_len = self.in_scope_lifetimes.len();
|
||||
|
||||
let parent_generics =
|
||||
match self.owners[parent_hir_id].as_ref().unwrap().node.expect_item().kind {
|
||||
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,
|
||||
_ => &[],
|
||||
|
@ -33,6 +33,7 @@
|
||||
#![feature(crate_visibility_modifier)]
|
||||
#![feature(box_patterns)]
|
||||
#![feature(iter_zip)]
|
||||
#![feature(never_type)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
use rustc_ast::token::{self, Token};
|
||||
@ -78,6 +79,7 @@ macro_rules! arena_vec {
|
||||
mod asm;
|
||||
mod block;
|
||||
mod expr;
|
||||
mod index;
|
||||
mod item;
|
||||
mod pat;
|
||||
mod path;
|
||||
@ -434,6 +436,7 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
self.local_node_ids.push(owner);
|
||||
|
||||
let item = f(self);
|
||||
debug_assert_eq!(def_id, item.def_id());
|
||||
let info = self.make_owner_info(item);
|
||||
|
||||
self.attrs = current_attrs;
|
||||
@ -470,8 +473,11 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
}
|
||||
|
||||
let (hash, node_hash) = self.hash_body(node, &bodies);
|
||||
let (nodes, parenting) =
|
||||
index::index_hir(self.sess, self.resolver.definitions(), node, &bodies);
|
||||
let nodes = hir::OwnerNodes { hash, node_hash, nodes, bodies };
|
||||
|
||||
hir::OwnerInfo { hash, node_hash, node, attrs, bodies, trait_map }
|
||||
hir::OwnerInfo { nodes, parenting, attrs, trait_map }
|
||||
}
|
||||
|
||||
/// Hash the HIR node twice, one deep and one shallow hash. This allows to differentiate
|
||||
|
@ -37,6 +37,7 @@ macro_rules! arena_types {
|
||||
[few] llvm_inline_asm: rustc_hir::LlvmInlineAsm<$tcx>,
|
||||
[] local: rustc_hir::Local<$tcx>,
|
||||
[few] mod_: rustc_hir::Mod<$tcx>,
|
||||
[] owner_info: rustc_hir::OwnerInfo<$tcx>,
|
||||
[] param: rustc_hir::Param<$tcx>,
|
||||
[] pat: rustc_hir::Pat<$tcx>,
|
||||
[] path: rustc_hir::Path<$tcx>,
|
||||
|
@ -1,5 +1,5 @@
|
||||
use crate::def::{CtorKind, DefKind, Res};
|
||||
use crate::def_id::{DefId, CRATE_DEF_ID};
|
||||
use crate::def_id::DefId;
|
||||
crate use crate::hir_id::{HirId, ItemLocalId};
|
||||
use crate::LangItem;
|
||||
|
||||
@ -663,18 +663,49 @@ pub struct WhereEqPredicate<'hir> {
|
||||
pub rhs_ty: &'hir Ty<'hir>,
|
||||
}
|
||||
|
||||
/// HIR node coupled with its parent's id in the same HIR owner.
|
||||
///
|
||||
/// The parent is trash when the node is a HIR owner.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParentedNode<'tcx> {
|
||||
pub parent: ItemLocalId,
|
||||
pub node: Node<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OwnerInfo<'hir> {
|
||||
pub node: OwnerNode<'hir>,
|
||||
pub attrs: BTreeMap<ItemLocalId, &'hir [Attribute]>,
|
||||
pub bodies: IndexVec<ItemLocalId, Option<&'hir Body<'hir>>>,
|
||||
/// Map indicating what traits are in scope for places where this
|
||||
/// is relevant; generated by resolve.
|
||||
pub trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
|
||||
pub struct OwnerNodes<'tcx> {
|
||||
/// Pre-computed hash of the full HIR.
|
||||
pub hash: Fingerprint,
|
||||
/// Pre-computed hash of the top node.
|
||||
pub node_hash: Fingerprint,
|
||||
/// Full HIR for the current owner.
|
||||
// The zeroth node's parent is trash, but is never accessed.
|
||||
pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
|
||||
/// Content of local bodies.
|
||||
pub bodies: IndexVec<ItemLocalId, Option<&'tcx Body<'tcx>>>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OwnerInfo<'hir> {
|
||||
/// Contents of the HIR.
|
||||
pub nodes: OwnerNodes<'hir>,
|
||||
/// Map from each nested owner to its parent's local id.
|
||||
pub parenting: FxHashMap<LocalDefId, ItemLocalId>,
|
||||
|
||||
pub attrs: BTreeMap<ItemLocalId, &'hir [Attribute]>,
|
||||
/// Map indicating what traits are in scope for places where this
|
||||
/// is relevant; generated by resolve.
|
||||
pub trait_map: FxHashMap<ItemLocalId, Box<[TraitCandidate]>>,
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
}
|
||||
|
||||
/// The top-level data structure that stores the entire contents of
|
||||
@ -688,39 +719,6 @@ pub struct Crate<'hir> {
|
||||
pub owners: IndexVec<LocalDefId, Option<OwnerInfo<'hir>>>,
|
||||
}
|
||||
|
||||
impl Crate<'hir> {
|
||||
pub fn module(&self) -> &'hir Mod<'hir> {
|
||||
let i = self.owners[CRATE_DEF_ID].as_ref().unwrap().node;
|
||||
if let OwnerNode::Crate(m) = i { m } else { panic!() }
|
||||
}
|
||||
|
||||
pub fn item(&self, id: ItemId) -> &'hir Item<'hir> {
|
||||
self.owners[id.def_id].as_ref().unwrap().node.expect_item()
|
||||
}
|
||||
|
||||
pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
|
||||
self.owners[id.def_id].as_ref().unwrap().node.expect_trait_item()
|
||||
}
|
||||
|
||||
pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
|
||||
self.owners[id.def_id].as_ref().unwrap().node.expect_impl_item()
|
||||
}
|
||||
|
||||
pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
|
||||
self.owners[id.def_id].as_ref().unwrap().node.expect_foreign_item()
|
||||
}
|
||||
|
||||
pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
|
||||
let HirId { owner, local_id } = id.hir_id;
|
||||
self.owners[owner].as_ref().unwrap().bodies[local_id].unwrap()
|
||||
}
|
||||
|
||||
pub fn attrs(&self, id: HirId) -> &'hir [Attribute] {
|
||||
let HirId { owner, local_id } = id;
|
||||
&self.owners[owner].as_ref().unwrap().attrs.get(&local_id).map(|la| *la).unwrap_or(&[])
|
||||
}
|
||||
}
|
||||
|
||||
/// A block of statements `{ .. }`, which may have a label (in this case the
|
||||
/// `targeted_by_break` field will be `true`) and may be `unsafe` by means of
|
||||
/// the `rules` being anything but `DefaultBlock`.
|
||||
|
@ -130,6 +130,28 @@ pub trait Map<'hir> {
|
||||
fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir>;
|
||||
}
|
||||
|
||||
// Used when no map is actually available, forcing manual implementation of nested visitors.
|
||||
impl Map<'hir> for ! {
|
||||
fn find(&self, _: HirId) -> Option<Node<'hir>> {
|
||||
unreachable!()
|
||||
}
|
||||
fn body(&self, _: BodyId) -> &'hir Body<'hir> {
|
||||
unreachable!()
|
||||
}
|
||||
fn item(&self, _: ItemId) -> &'hir Item<'hir> {
|
||||
unreachable!()
|
||||
}
|
||||
fn trait_item(&self, _: TraitItemId) -> &'hir TraitItem<'hir> {
|
||||
unreachable!()
|
||||
}
|
||||
fn impl_item(&self, _: ImplItemId) -> &'hir ImplItem<'hir> {
|
||||
unreachable!()
|
||||
}
|
||||
fn foreign_item(&self, _: ForeignItemId) -> &'hir ForeignItem<'hir> {
|
||||
unreachable!()
|
||||
}
|
||||
}
|
||||
|
||||
/// An erased version of `Map<'hir>`, using dynamic dispatch.
|
||||
/// NOTE: This type is effectively only usable with `NestedVisitorMap::None`.
|
||||
pub struct ErasedMap<'hir>(&'hir dyn Map<'hir>);
|
||||
|
@ -6,6 +6,7 @@
|
||||
#![feature(in_band_lifetimes)]
|
||||
#![feature(once_cell)]
|
||||
#![feature(min_specialization)]
|
||||
#![feature(never_type)]
|
||||
#![recursion_limit = "256"]
|
||||
|
||||
#[macro_use]
|
||||
|
@ -1,8 +1,8 @@
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher, ToStableHashKey};
|
||||
|
||||
use crate::hir::{
|
||||
BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, TraitItem,
|
||||
TraitItemId, Ty, VisibilityKind,
|
||||
BodyId, Expr, ForeignItem, ForeignItemId, ImplItem, ImplItemId, Item, ItemId, Mod, OwnerNodes,
|
||||
TraitItem, TraitItemId, Ty, VisibilityKind,
|
||||
};
|
||||
use crate::hir_id::{HirId, ItemLocalId};
|
||||
use rustc_span::def_id::DefPathHash;
|
||||
@ -209,3 +209,12 @@ impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for Item<'_> {
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
impl<HirCtx: crate::HashStableContext> HashStable<HirCtx> for OwnerNodes<'tcx> {
|
||||
fn hash_stable(&self, hcx: &mut HirCtx, hasher: &mut StableHasher) {
|
||||
// We ignore the `nodes` and `bodies` fields since these refer to information included in
|
||||
// `hash` which is hashed in the collector and used for the crate hash.
|
||||
let OwnerNodes { hash, node_hash: _, nodes: _, bodies: _ } = *self;
|
||||
hash.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
@ -92,9 +92,6 @@ macro_rules! arena_types {
|
||||
[] tys: rustc_middle::ty::TyS<$tcx>,
|
||||
[] predicates: rustc_middle::ty::PredicateInner<$tcx>,
|
||||
|
||||
// HIR query types
|
||||
[] indexed_hir: rustc_middle::hir::IndexedHir<$tcx>,
|
||||
|
||||
// Note that this deliberately duplicates items in the `rustc_hir::arena`,
|
||||
// since we need to allocate this type on both the `rustc_hir` arena
|
||||
// (during lowering) and the `librustc_middle` arena (for decoding MIR)
|
||||
|
@ -1,4 +1,4 @@
|
||||
use crate::hir::{IndexedHir, ModuleItems, Owner};
|
||||
use crate::hir::{ModuleItems, Owner};
|
||||
use crate::ty::TyCtxt;
|
||||
use rustc_ast as ast;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
@ -21,7 +21,6 @@ use rustc_target::spec::abi::Abi;
|
||||
use std::collections::VecDeque;
|
||||
|
||||
pub mod blocks;
|
||||
mod collector;
|
||||
|
||||
fn fn_decl<'hir>(node: Node<'hir>) -> Option<&'hir FnDecl<'hir>> {
|
||||
match node {
|
||||
@ -164,7 +163,7 @@ impl<'hir> Map<'hir> {
|
||||
|
||||
pub fn items(&self) -> impl Iterator<Item = &'hir Item<'hir>> + '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_ref()?.node() {
|
||||
OwnerNode::Item(item) => Some(item),
|
||||
_ => None,
|
||||
})
|
||||
@ -497,7 +496,7 @@ impl<'hir> Map<'hir> {
|
||||
.owners
|
||||
.iter_enumerated()
|
||||
.flat_map(move |(owner, owner_info)| {
|
||||
let bodies = &owner_info.as_ref()?.bodies;
|
||||
let bodies = &owner_info.as_ref()?.nodes.bodies;
|
||||
Some(bodies.iter_enumerated().filter_map(move |(local_id, body)| {
|
||||
if body.is_none() {
|
||||
return None;
|
||||
@ -518,7 +517,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 {
|
||||
par_iter(&owner_info.bodies.raw).enumerate().for_each(|(local_id, body)| {
|
||||
par_iter(&owner_info.nodes.bodies.raw).enumerate().for_each(|(local_id, body)| {
|
||||
if body.is_some() {
|
||||
let local_id = ItemLocalId::new(local_id);
|
||||
let hir_id = HirId { owner, local_id };
|
||||
@ -605,7 +604,7 @@ impl<'hir> Map<'hir> {
|
||||
{
|
||||
let krate = self.krate();
|
||||
for owner in krate.owners.iter().filter_map(Option::as_ref) {
|
||||
match owner.node {
|
||||
match owner.node() {
|
||||
OwnerNode::Item(item) => visitor.visit_item(item),
|
||||
OwnerNode::ForeignItem(item) => visitor.visit_foreign_item(item),
|
||||
OwnerNode::ImplItem(item) => visitor.visit_impl_item(item),
|
||||
@ -621,7 +620,7 @@ 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(|o| o.node) {
|
||||
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),
|
||||
@ -1065,20 +1064,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
|
||||
}
|
||||
}
|
||||
|
||||
pub(super) fn index_hir<'tcx>(
|
||||
tcx: TyCtxt<'tcx>,
|
||||
owner: LocalDefId,
|
||||
) -> Option<&'tcx IndexedHir<'tcx>> {
|
||||
let map = collector::collect(
|
||||
tcx.sess,
|
||||
tcx.untracked_crate,
|
||||
&tcx.untracked_resolutions.definitions,
|
||||
owner,
|
||||
)?;
|
||||
|
||||
Some(&*tcx.arena.alloc(map))
|
||||
}
|
||||
|
||||
pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
|
||||
debug_assert_eq!(crate_num, LOCAL_CRATE);
|
||||
let mut hir_body_nodes: Vec<_> = tcx
|
||||
@ -1088,7 +1073,7 @@ pub(super) fn crate_hash(tcx: TyCtxt<'_>, crate_num: CrateNum) -> Svh {
|
||||
.all_def_path_hashes_and_def_ids()
|
||||
.filter_map(|(def_path_hash, local_def_index)| {
|
||||
let def_id = LocalDefId { local_def_index };
|
||||
let hash = tcx.index_hir(def_id).as_ref()?.nodes.hash;
|
||||
let hash = tcx.hir_crate(()).owners[def_id].as_ref()?.nodes.hash;
|
||||
Some((def_path_hash, hash, def_id))
|
||||
})
|
||||
.collect();
|
||||
|
@ -10,24 +10,13 @@ use crate::ty::query::Providers;
|
||||
use crate::ty::TyCtxt;
|
||||
use rustc_ast::Attribute;
|
||||
use rustc_data_structures::fingerprint::Fingerprint;
|
||||
use rustc_data_structures::fx::FxHashMap;
|
||||
use rustc_data_structures::stable_hasher::{HashStable, StableHasher};
|
||||
use rustc_hir::def_id::LocalDefId;
|
||||
use rustc_hir::*;
|
||||
use rustc_index::vec::{Idx, IndexVec};
|
||||
use rustc_query_system::ich::StableHashingContext;
|
||||
use rustc_span::DUMMY_SP;
|
||||
use std::collections::BTreeMap;
|
||||
|
||||
/// Result of HIR indexing for a given HIR owner.
|
||||
#[derive(Debug, HashStable)]
|
||||
pub struct IndexedHir<'hir> {
|
||||
/// Contents of the HIR.
|
||||
nodes: OwnerNodes<'hir>,
|
||||
/// Map from each nested owner to its parent's local id.
|
||||
parenting: FxHashMap<LocalDefId, ItemLocalId>,
|
||||
}
|
||||
|
||||
/// Top-level HIR node for current owner. This only contains the node for which
|
||||
/// `HirId::local_id == 0`, and excludes bodies.
|
||||
///
|
||||
@ -47,38 +36,6 @@ impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for Owner<'tcx> {
|
||||
}
|
||||
}
|
||||
|
||||
/// HIR node coupled with its parent's id in the same HIR owner.
|
||||
///
|
||||
/// The parent is trash when the node is a HIR owner.
|
||||
#[derive(Clone, Debug)]
|
||||
pub struct ParentedNode<'tcx> {
|
||||
parent: ItemLocalId,
|
||||
node: Node<'tcx>,
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct OwnerNodes<'tcx> {
|
||||
/// Pre-computed hash of the full HIR.
|
||||
hash: Fingerprint,
|
||||
/// Pre-computed hash of the top node.
|
||||
node_hash: Fingerprint,
|
||||
/// Full HIR for the current owner.
|
||||
// The zeroth node's parent is trash, but is never accessed.
|
||||
nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
|
||||
/// Content of local bodies.
|
||||
bodies: &'tcx IndexVec<ItemLocalId, Option<&'tcx Body<'tcx>>>,
|
||||
}
|
||||
|
||||
impl<'a, 'tcx> HashStable<StableHashingContext<'a>> for OwnerNodes<'tcx> {
|
||||
#[inline]
|
||||
fn hash_stable(&self, hcx: &mut StableHashingContext<'a>, hasher: &mut StableHasher) {
|
||||
// We ignore the `nodes` and `bodies` fields since these refer to information included in
|
||||
// `hash` which is hashed in the collector and used for the crate hash.
|
||||
let OwnerNodes { hash, node_hash: _, nodes: _, bodies: _ } = *self;
|
||||
hash.hash_stable(hcx, hasher);
|
||||
}
|
||||
}
|
||||
|
||||
/// Attributes owner by a HIR owner.
|
||||
#[derive(Copy, Clone, Debug, HashStable)]
|
||||
pub struct AttributeMap<'tcx> {
|
||||
@ -125,23 +82,23 @@ pub fn provide(providers: &mut Providers) {
|
||||
hir.local_def_id(hir.get_module_parent_node(hir.local_def_id_to_hir_id(id)))
|
||||
};
|
||||
providers.hir_crate = |tcx, ()| tcx.untracked_crate;
|
||||
providers.index_hir = map::index_hir;
|
||||
providers.crate_hash = map::crate_hash;
|
||||
providers.hir_module_items = map::hir_module_items;
|
||||
providers.hir_owner = |tcx, id| {
|
||||
let owner = tcx.index_hir(id)?;
|
||||
let node = owner.nodes.nodes[ItemLocalId::new(0)].as_ref().unwrap().node;
|
||||
let node = node.as_owner().unwrap(); // Indexing must ensure it is an OwnerNode.
|
||||
let owner = tcx.hir_crate(()).owners[id].as_ref()?;
|
||||
let node = owner.node();
|
||||
Some(Owner { node, node_hash: owner.nodes.node_hash })
|
||||
};
|
||||
providers.hir_owner_nodes = |tcx, id| tcx.index_hir(id).map(|i| &i.nodes);
|
||||
providers.hir_owner_nodes = |tcx, id| tcx.hir_crate(()).owners[id].as_ref().map(|i| &i.nodes);
|
||||
providers.hir_owner_parent = |tcx, id| {
|
||||
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);
|
||||
if let Some(local_id) = tcx.index_hir(parent_hir_id.owner).unwrap().parenting.get(&id) {
|
||||
if let Some(local_id) =
|
||||
tcx.hir_crate(()).owners[parent_hir_id.owner].as_ref().unwrap().parenting.get(&id)
|
||||
{
|
||||
parent_hir_id.local_id = *local_id;
|
||||
}
|
||||
parent_hir_id
|
||||
|
@ -40,13 +40,6 @@ rustc_queries! {
|
||||
desc { "get the crate HIR" }
|
||||
}
|
||||
|
||||
/// The indexed HIR. This can be conveniently accessed by `tcx.hir()`.
|
||||
/// Avoid calling this query directly.
|
||||
query index_hir(_: LocalDefId) -> Option<&'tcx crate::hir::IndexedHir<'tcx>> {
|
||||
eval_always
|
||||
desc { "index HIR" }
|
||||
}
|
||||
|
||||
/// The items in a module.
|
||||
///
|
||||
/// This can be conveniently accessed by `tcx.hir().visit_item_likes_in_module`.
|
||||
@ -76,7 +69,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 crate::hir::OwnerNodes<'tcx>> {
|
||||
query hir_owner_nodes(key: LocalDefId) -> Option<&'tcx hir::OwnerNodes<'tcx>> {
|
||||
desc { |tcx| "HIR owner items in `{}`", tcx.def_path_str(key.to_def_id()) }
|
||||
}
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user