Auto merge of #89124 - cjgillot:owner-info, r=michaelwoerister

Index and hash HIR as part of lowering

Part of https://github.com/rust-lang/rust/pull/88186
~Based on https://github.com/rust-lang/rust/pull/88880 (see merge commit).~

Once HIR is lowered, it is later indexed by the `index_hir` query and hashed for `crate_hash`. This PR moves those post-processing steps to lowering itself. As a side objective, the HIR crate data structure is refactored as an `IndexVec<LocalDefId, Option<OwnerInfo<'hir>>>` where `OwnerInfo` stores all the relevant information for an HIR owner.

r? `@michaelwoerister`
cc `@petrochenkov`
This commit is contained in:
bors
2021-10-18 19:53:05 +00:00
28 changed files with 550 additions and 597 deletions

View File

@@ -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;
@@ -9,6 +9,7 @@ use rustc_ast::{Attribute, FloatTy, IntTy, Label, LitKind, StrStyle, TraitObject
pub use rustc_ast::{BorrowKind, ImplPolarity, IsAuto};
pub use rustc_ast::{CaptureBy, Movability, Mutability};
use rustc_ast::{InlineAsmOptions, InlineAsmTemplatePiece};
use rustc_data_structures::fingerprint::Fingerprint;
use rustc_data_structures::fx::FxHashMap;
use rustc_index::vec::IndexVec;
use rustc_macros::HashStable_Generic;
@@ -662,6 +663,74 @@ 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>,
}
/// Attributes owned by a HIR owner.
#[derive(Debug)]
pub struct AttributeMap<'tcx> {
pub map: BTreeMap<ItemLocalId, &'tcx [Attribute]>,
pub hash: Fingerprint,
}
impl<'tcx> AttributeMap<'tcx> {
pub const EMPTY: &'static AttributeMap<'static> =
&AttributeMap { map: BTreeMap::new(), hash: Fingerprint::ZERO };
#[inline]
pub fn get(&self, id: ItemLocalId) -> &'tcx [Attribute] {
self.map.get(&id).copied().unwrap_or(&[])
}
}
/// Map of all HIR nodes inside the current owner.
/// These nodes are mapped by `ItemLocalId` alongside the index of their parent node.
/// The HIR tree, including bodies, is pre-hashed.
#[derive(Debug)]
pub struct OwnerNodes<'tcx> {
/// Pre-computed hash of the full HIR.
pub hash_including_bodies: Fingerprint,
/// Pre-computed hash of the item signature, sithout recursing into the body.
pub hash_without_bodies: Fingerprint,
/// Full HIR for the current owner.
// The zeroth node's parent should never be accessed: the owner's parent is computed by the
// hir_owner_parent query. It is set to `ItemLocalId::INVALID` to force an ICE if accidentally
// used.
pub nodes: IndexVec<ItemLocalId, Option<ParentedNode<'tcx>>>,
/// Content of local bodies.
pub bodies: IndexVec<ItemLocalId, Option<&'tcx Body<'tcx>>>,
}
/// Full information resulting from lowering an AST node.
#[derive(Debug, HashStable_Generic)]
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>,
/// Collected attributes of the HIR nodes.
pub attrs: AttributeMap<'hir>,
/// 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
/// the crate currently being compiled.
///
@@ -670,41 +739,8 @@ pub struct WhereEqPredicate<'hir> {
/// [rustc dev guide]: https://rustc-dev-guide.rust-lang.org/hir.html
#[derive(Debug)]
pub struct Crate<'hir> {
pub owners: IndexVec<LocalDefId, Option<OwnerNode<'hir>>>,
pub bodies: BTreeMap<BodyId, Body<'hir>>,
/// Map indicating what traits are in scope for places where this
/// is relevant; generated by resolve.
pub trait_map: FxHashMap<LocalDefId, FxHashMap<ItemLocalId, Box<[TraitCandidate]>>>,
/// Collected attributes from HIR nodes.
pub attrs: BTreeMap<HirId, &'hir [Attribute]>,
}
impl Crate<'hir> {
pub fn module(&self) -> &'hir Mod<'hir> {
if let Some(OwnerNode::Crate(m)) = self.owners[CRATE_DEF_ID] { m } else { panic!() }
}
pub fn item(&self, id: ItemId) -> &'hir Item<'hir> {
self.owners[id.def_id].as_ref().unwrap().expect_item()
}
pub fn trait_item(&self, id: TraitItemId) -> &'hir TraitItem<'hir> {
self.owners[id.def_id].as_ref().unwrap().expect_trait_item()
}
pub fn impl_item(&self, id: ImplItemId) -> &'hir ImplItem<'hir> {
self.owners[id.def_id].as_ref().unwrap().expect_impl_item()
}
pub fn foreign_item(&self, id: ForeignItemId) -> &'hir ForeignItem<'hir> {
self.owners[id.def_id].as_ref().unwrap().expect_foreign_item()
}
pub fn body(&self, id: BodyId) -> &Body<'hir> {
&self.bodies[&id]
}
pub owners: IndexVec<LocalDefId, Option<OwnerInfo<'hir>>>,
pub hir_hash: Fingerprint,
}
/// A block of statements `{ .. }`, which may have a label (in this case the