1
Fork 0

Create Map after TyCtxt

This commit is contained in:
John Kåre Alsaker 2020-02-07 13:13:35 +01:00
parent 21386e1355
commit 518c78fbd3
8 changed files with 131 additions and 158 deletions

View file

@ -163,6 +163,8 @@ macro_rules! arena_types {
[] where_predicate: rustc_hir::WherePredicate<$tcx>,
// HIR query types
[few] hir_map: rustc::hir::map::Map<$tcx>,
[few] hir_definitions: rustc::hir::map::definitions::Definitions,
[] hir_owner: rustc::hir::HirOwner<$tcx>,
[] hir_owner_items: rustc::hir::HirOwnerItems<$tcx>,
], $tcx);

View file

@ -209,6 +209,12 @@ impl<'a, 'hir> NodeCollector<'a, 'hir> {
FxHashMap<DefIndex, &'hir mut HirOwnerItems<'hir>>,
Svh,
) {
// Insert bodies into the map
for (id, body) in self.krate.bodies.iter() {
let bodies = &mut self.owner_items_map.get_mut(&id.hir_id.owner).unwrap().bodies;
assert!(bodies.insert(id.hir_id.local_id, body).is_none());
}
self.hir_body_nodes.sort_unstable_by_key(|bn| bn.0);
let node_hashes = self.hir_body_nodes.iter().fold(

View file

@ -1,15 +1,15 @@
use crate::hir::map::Map;
use rustc_data_structures::fx::FxHashSet;
use crate::hir::map::EarlyMap;
/*use rustc_data_structures::fx::FxHashSet;
use rustc_data_structures::sync::{par_iter, Lock, ParallelIterator};
use rustc_hir as hir;
use rustc_hir::def_id::{DefId, DefIndex, CRATE_DEF_INDEX};
use rustc_hir::intravisit;
use rustc_hir::itemlikevisit::ItemLikeVisitor;
use rustc_hir::{HirId, ItemLocalId};
use rustc_hir::{HirId, ItemLocalId};*/
pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) {
pub fn check_crate(hir_map: &EarlyMap<'_>, sess: &rustc_session::Session) {
hir_map.dep_graph.assert_ignored();
/*
let errors = Lock::new(Vec::new());
par_iter(&hir_map.krate.modules).for_each(|(module_id, _)| {
@ -25,23 +25,23 @@ pub fn check_crate(hir_map: &Map<'_>, sess: &rustc_session::Session) {
if !errors.is_empty() {
let message = errors.iter().fold(String::new(), |s1, s2| s1 + "\n" + s2);
sess.delay_span_bug(rustc_span::DUMMY_SP, &message);
}
}*/
}
/*
struct HirIdValidator<'a, 'hir> {
hir_map: &'a Map<'hir>,
hir_map: &'a EarlyMap<'hir>,
owner_def_index: Option<DefIndex>,
hir_ids_seen: FxHashSet<ItemLocalId>,
errors: &'a Lock<Vec<String>>,
}
struct OuterVisitor<'a, 'hir> {
hir_map: &'a Map<'hir>,
hir_map: &'a EarlyMap<'hir>,
errors: &'a Lock<Vec<String>>,
}
impl<'a, 'hir> OuterVisitor<'a, 'hir> {
fn new_inner_visitor(&self, hir_map: &'a Map<'hir>) -> HirIdValidator<'a, 'hir> {
fn new_inner_visitor(&self, hir_map: &'a EarlyMap<'hir>) -> HirIdValidator<'a, 'hir> {
HirIdValidator {
hir_map,
owner_def_index: None,
@ -133,7 +133,7 @@ impl<'a, 'hir> HirIdValidator<'a, 'hir> {
}
impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
type Map = Map<'hir>;
type Map = EarlyMap<'hir>;
fn nested_visit_map(&mut self) -> intravisit::NestedVisitorMap<'_, Self::Map> {
intravisit::NestedVisitorMap::OnlyBodies(self.hir_map)
@ -173,3 +173,4 @@ impl<'a, 'hir> intravisit::Visitor<'hir> for HirIdValidator<'a, 'hir> {
// different owner.
}
}
*/

View file

@ -8,6 +8,7 @@ use crate::dep_graph::{DepGraph, DepKind, DepNode, DepNodeIndex};
use crate::hir::{HirOwner, HirOwnerItems};
use crate::middle::cstore::CrateStoreDyn;
use crate::ty::query::Providers;
use crate::ty::TyCtxt;
use rustc_ast::ast::{self, Name, NodeId};
use rustc_data_structures::fx::FxHashMap;
use rustc_data_structures::svh::Svh;
@ -138,9 +139,8 @@ impl<'hir> Entry<'hir> {
pub(super) type HirEntryMap<'hir> = IndexVec<DefIndex, IndexVec<ItemLocalId, Option<Entry<'hir>>>>;
/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
#[derive(Clone)]
pub struct Map<'hir> {
krate: &'hir Crate<'hir>,
pub struct EarlyMap<'hir> {
pub krate: &'hir Crate<'hir>,
pub dep_graph: DepGraph,
@ -150,12 +150,34 @@ pub struct Map<'hir> {
pub(super) owner_map: FxHashMap<DefIndex, &'hir HirOwner<'hir>>,
pub(super) owner_items_map: FxHashMap<DefIndex, &'hir HirOwnerItems<'hir>>,
map: HirEntryMap<'hir>,
pub(super) map: HirEntryMap<'hir>,
definitions: Definitions,
pub(crate) definitions: &'hir Definitions,
/// The reverse mapping of `node_to_hir_id`.
hir_to_node_id: FxHashMap<HirId, NodeId>,
pub(super) hir_to_node_id: FxHashMap<HirId, NodeId>,
}
/// Represents a mapping from `NodeId`s to AST elements and their parent `NodeId`s.
pub struct Map<'hir> {
pub(super) tcx: TyCtxt<'hir>,
pub(super) krate: &'hir Crate<'hir>,
pub dep_graph: DepGraph,
/// The SVH of the local crate.
pub crate_hash: Svh,
pub(super) owner_map: FxHashMap<DefIndex, &'hir HirOwner<'hir>>,
pub(super) owner_items_map: FxHashMap<DefIndex, &'hir HirOwnerItems<'hir>>,
pub(super) map: HirEntryMap<'hir>,
pub(super) definitions: &'hir Definitions,
/// The reverse mapping of `node_to_hir_id`.
pub(super) hir_to_node_id: FxHashMap<HirId, NodeId>,
}
/// An iterator that walks up the ancestor tree of a given `HirId`.
@ -406,11 +428,11 @@ impl<'hir> Map<'hir> {
}
pub fn body(&self, id: BodyId) -> &'hir Body<'hir> {
self.read(id.hir_id);
// N.B., intentionally bypass `self.krate()` so that we
// do not trigger a read of the whole krate here
self.krate.body(id)
self.tcx
.hir_owner_items(DefId::local(id.hir_id.owner))
.bodies
.get(&id.hir_id.local_id)
.unwrap()
}
pub fn fn_decl_by_hir_id(&self, hir_id: HirId) -> Option<&'hir FnDecl<'hir>> {
@ -966,45 +988,6 @@ impl<'hir> Map<'hir> {
attrs.unwrap_or(&[])
}
/// Returns an iterator that yields all the hir ids in the map.
fn all_ids<'a>(&'a self) -> impl Iterator<Item = HirId> + 'a {
// This code is a bit awkward because the map is implemented as 2 levels of arrays,
// see the comment on `HirEntryMap`.
// Iterate over all the indices and return a reference to
// local maps and their index given that they exist.
self.map.iter_enumerated().flat_map(move |(owner, local_map)| {
// Iterate over each valid entry in the local map.
local_map.iter_enumerated().filter_map(move |(i, entry)| {
entry.map(move |_| {
// Reconstruct the `HirId` based on the 3 indices we used to find it.
HirId { owner, local_id: i }
})
})
})
}
/// Returns an iterator that yields the node id's with paths that
/// match `parts`. (Requires `parts` is non-empty.)
///
/// For example, if given `parts` equal to `["bar", "quux"]`, then
/// the iterator will produce node id's for items with paths
/// such as `foo::bar::quux`, `bar::quux`, `other::bar::quux`, and
/// any other such items it can find in the map.
pub fn nodes_matching_suffix<'a>(
&'a self,
parts: &'a [String],
) -> impl Iterator<Item = NodeId> + 'a {
let nodes = NodesMatchingSuffix {
map: self,
item_name: parts.last().unwrap(),
in_which: &parts[..parts.len() - 1],
};
self.all_ids()
.filter(move |hir| nodes.matches_suffix(*hir))
.map(move |hir| self.hir_to_node_id(hir))
}
pub fn span(&self, hir_id: HirId) -> Span {
self.read(hir_id); // reveals span from node
match self.find_entry(hir_id).map(|entry| entry.node) {
@ -1087,82 +1070,6 @@ impl<'hir> intravisit::Map<'hir> for Map<'hir> {
}
}
pub struct NodesMatchingSuffix<'a> {
map: &'a Map<'a>,
item_name: &'a String,
in_which: &'a [String],
}
impl<'a> NodesMatchingSuffix<'a> {
/// Returns `true` only if some suffix of the module path for parent
/// matches `self.in_which`.
///
/// In other words: let `[x_0,x_1,...,x_k]` be `self.in_which`;
/// returns true if parent's path ends with the suffix
/// `x_0::x_1::...::x_k`.
fn suffix_matches(&self, parent: HirId) -> bool {
let mut cursor = parent;
for part in self.in_which.iter().rev() {
let (mod_id, mod_name) = match find_first_mod_parent(self.map, cursor) {
None => return false,
Some((node_id, name)) => (node_id, name),
};
if mod_name.as_str() != *part {
return false;
}
cursor = self.map.get_parent_item(mod_id);
}
return true;
// Finds the first mod in parent chain for `id`, along with
// that mod's name.
//
// If `id` itself is a mod named `m` with parent `p`, then
// returns `Some(id, m, p)`. If `id` has no mod in its parent
// chain, then returns `None`.
fn find_first_mod_parent(map: &Map<'_>, mut id: HirId) -> Option<(HirId, Name)> {
loop {
if let Node::Item(item) = map.find(id)? {
if item_is_mod(&item) {
return Some((id, item.ident.name));
}
}
let parent = map.get_parent_item(id);
if parent == id {
return None;
}
id = parent;
}
fn item_is_mod(item: &Item<'_>) -> bool {
match item.kind {
ItemKind::Mod(_) => true,
_ => false,
}
}
}
}
// We are looking at some node `n` with a given name and parent
// id; do their names match what I am seeking?
fn matches_names(&self, parent_of_n: HirId, name: Name) -> bool {
name.as_str() == *self.item_name && self.suffix_matches(parent_of_n)
}
fn matches_suffix(&self, hir: HirId) -> bool {
let name = match self.map.find_entry(hir).map(|entry| entry.node) {
Some(Node::Item(n)) => n.name(),
Some(Node::ForeignItem(n)) => n.name(),
Some(Node::TraitItem(n)) => n.name(),
Some(Node::ImplItem(n)) => n.name(),
Some(Node::Variant(n)) => n.name(),
Some(Node::Field(n)) => n.name(),
_ => return false,
};
self.matches_names(self.map.get_parent_item(hir), name)
}
}
trait Named {
fn name(&self) -> Name;
}
@ -1211,7 +1118,7 @@ pub fn map_crate<'hir>(
krate: &'hir Crate<'hir>,
dep_graph: DepGraph,
definitions: Definitions,
) -> Map<'hir> {
) -> EarlyMap<'hir> {
let _prof_timer = sess.prof.generic_activity("build_hir_map");
// Build the reverse mapping of `node_to_hir_id`.
@ -1233,7 +1140,7 @@ pub fn map_crate<'hir>(
collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args)
};
let map = Map {
let map = EarlyMap {
krate,
dep_graph,
crate_hash,
@ -1241,7 +1148,7 @@ pub fn map_crate<'hir>(
owner_map,
owner_items_map: owner_items_map.into_iter().map(|(k, v)| (k, &*v)).collect(),
hir_to_node_id,
definitions,
definitions: arena.alloc(definitions),
};
sess.time("validate_HIR_map", || {

View file

@ -7,6 +7,7 @@ pub mod map;
use crate::ty::query::Providers;
use crate::ty::TyCtxt;
use rustc_data_structures::cold_path;
use rustc_data_structures::fx::FxHashMap;
use rustc_hir::def_id::{DefId, LOCAL_CRATE};
use rustc_hir::print;
@ -68,7 +69,17 @@ impl<'hir> print::PpAnn for Hir<'hir> {
impl<'tcx> TyCtxt<'tcx> {
#[inline(always)]
pub fn hir(self) -> Hir<'tcx> {
Hir { tcx: self, map: &self.hir_map }
let map = self.late_hir_map.load();
let map = if unlikely!(map.is_none()) {
cold_path(|| {
let map = self.hir_map(LOCAL_CRATE);
self.late_hir_map.store(Some(map));
map
})
} else {
map.unwrap()
};
Hir { tcx: self, map }
}
pub fn parent_module(self, id: HirId) -> DefId {
@ -81,6 +92,35 @@ pub fn provide(providers: &mut Providers<'_>) {
let hir = tcx.hir();
hir.local_def_id(hir.get_module_parent_node(hir.as_local_hir_id(id).unwrap()))
};
providers.hir_crate = |tcx, _| tcx.hir_map.untracked_krate();
providers.hir_crate = |tcx, _| tcx.hir_map(LOCAL_CRATE).untracked_krate();
providers.hir_map = |tcx, id| {
assert_eq!(id, LOCAL_CRATE);
let early = tcx.hir_map.steal();
tcx.arena.alloc(map::Map {
tcx,
krate: early.krate,
dep_graph: early.dep_graph,
crate_hash: early.crate_hash,
owner_map: early.owner_map,
owner_items_map: early.owner_items_map,
map: early.map,
definitions: early.definitions,
hir_to_node_id: early.hir_to_node_id,
})
};
providers.hir_owner = |tcx, id| {
assert_eq!(id.krate, LOCAL_CRATE);
*tcx.hir().map.owner_map.get(&id.index).unwrap()
};
providers.hir_owner_items = |tcx, id| {
assert_eq!(id.krate, LOCAL_CRATE);
*tcx.hir().map.owner_items_map.get(&id.index).unwrap()
};
map::provide(providers);
}

View file

@ -55,6 +55,12 @@ rustc_queries! {
desc { "get the crate HIR" }
}
query hir_map(_: CrateNum) -> &'tcx map::Map<'tcx> {
eval_always
no_hash
desc { "index HIR" }
}
query hir_owner(key: DefId) -> &'tcx HirOwner<'tcx> {
eval_always
}

View file

@ -5,6 +5,7 @@ use crate::dep_graph::DepGraph;
use crate::dep_graph::{self, DepConstructor};
use crate::hir::exports::Export;
use crate::hir::map as hir_map;
use crate::hir::map::definitions::Definitions;
use crate::hir::map::{DefPathData, DefPathHash};
use crate::ich::{NodeIdHashingMode, StableHashingContext};
use crate::infer::canonical::{Canonical, CanonicalVarInfo, CanonicalVarInfos};
@ -52,7 +53,7 @@ use rustc_data_structures::sharded::{IntoPointer, ShardedHashMap};
use rustc_data_structures::stable_hasher::{
hash_stable_hashmap, HashStable, StableHasher, StableVec,
};
use rustc_data_structures::sync::{self, Lock, Lrc, WorkerLocal};
use rustc_data_structures::sync::{self, AtomicCell, Lock, Lrc, WorkerLocal};
use rustc_hir as hir;
use rustc_hir::def::{DefKind, Res};
use rustc_hir::def_id::{CrateNum, DefId, DefIdMap, DefIdSet, DefIndex, LOCAL_CRATE};
@ -971,8 +972,11 @@ pub struct GlobalCtxt<'tcx> {
/// Export map produced by name resolution.
export_map: FxHashMap<DefId, Vec<Export<hir::HirId>>>,
/// This should usually be accessed with the `tcx.hir()` method.
pub(crate) hir_map: hir_map::Map<'tcx>,
/// These should usually be accessed with the `tcx.hir()` method.
pub(crate) hir_map: Steal<hir_map::EarlyMap<'tcx>>,
pub(crate) late_hir_map: AtomicCell<Option<&'tcx hir_map::Map<'tcx>>>,
pub(crate) untracked_crate: &'tcx hir::Crate<'tcx>,
pub(crate) definitions: &'tcx Definitions,
/// A map from `DefPathHash` -> `DefId`. Includes `DefId`s from the local crate
/// as well as all upstream crates. Only populated in incremental mode.
@ -1116,7 +1120,7 @@ impl<'tcx> TyCtxt<'tcx> {
extern_providers: ty::query::Providers<'tcx>,
arena: &'tcx WorkerLocal<Arena<'tcx>>,
resolutions: ty::ResolverOutputs,
hir: hir_map::Map<'tcx>,
hir: hir_map::EarlyMap<'tcx>,
on_disk_query_result_cache: query::OnDiskCache<'tcx>,
crate_name: &str,
output_filenames: &OutputFilenames,
@ -1129,6 +1133,7 @@ impl<'tcx> TyCtxt<'tcx> {
let common_lifetimes = CommonLifetimes::new(&interners);
let common_consts = CommonConsts::new(&interners, &common_types);
let dep_graph = hir.dep_graph.clone();
let definitions = hir.definitions;
let cstore = resolutions.cstore;
let crates = cstore.crates_untracked();
let max_cnum = crates.iter().map(|c| c.as_usize()).max().unwrap_or(0);
@ -1139,7 +1144,7 @@ impl<'tcx> TyCtxt<'tcx> {
let def_path_tables = crates
.iter()
.map(|&cnum| (cnum, cstore.def_path_table(cnum)))
.chain(iter::once((LOCAL_CRATE, hir.definitions().def_path_table())));
.chain(iter::once((LOCAL_CRATE, definitions.def_path_table())));
// Precompute the capacity of the hashmap so we don't have to
// re-allocate when populating it.
@ -1159,11 +1164,11 @@ impl<'tcx> TyCtxt<'tcx> {
let mut trait_map: FxHashMap<_, FxHashMap<_, _>> = FxHashMap::default();
for (k, v) in resolutions.trait_map {
let hir_id = hir.node_to_hir_id(k);
let hir_id = definitions.node_to_hir_id(k);
let map = trait_map.entry(hir_id.owner).or_default();
let v = v
.into_iter()
.map(|tc| tc.map_import_ids(|id| hir.definitions().node_to_hir_id(id)))
.map(|tc| tc.map_import_ids(|id| definitions.node_to_hir_id(id)))
.collect();
map.insert(hir_id.local_id, StableVec::new(v));
}
@ -1185,28 +1190,33 @@ impl<'tcx> TyCtxt<'tcx> {
.export_map
.into_iter()
.map(|(k, v)| {
let exports: Vec<_> =
v.into_iter().map(|e| e.map_id(|id| hir.node_to_hir_id(id))).collect();
let exports: Vec<_> = v
.into_iter()
.map(|e| e.map_id(|id| definitions.node_to_hir_id(id)))
.collect();
(k, exports)
})
.collect(),
maybe_unused_trait_imports: resolutions
.maybe_unused_trait_imports
.into_iter()
.map(|id| hir.local_def_id_from_node_id(id))
.map(|id| definitions.local_def_id(id))
.collect(),
maybe_unused_extern_crates: resolutions
.maybe_unused_extern_crates
.into_iter()
.map(|(id, sp)| (hir.local_def_id_from_node_id(id), sp))
.map(|(id, sp)| (definitions.local_def_id(id), sp))
.collect(),
glob_map: resolutions
.glob_map
.into_iter()
.map(|(id, names)| (hir.local_def_id_from_node_id(id), names))
.map(|(id, names)| (definitions.local_def_id(id), names))
.collect(),
extern_prelude: resolutions.extern_prelude,
hir_map: hir,
untracked_crate: hir.krate,
hir_map: Steal::new(hir),
late_hir_map: AtomicCell::new(None),
definitions,
def_path_hash_to_def_id,
queries: query::Queries::new(providers, extern_providers, on_disk_query_result_cache),
rcache: Default::default(),
@ -1286,7 +1296,7 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline]
pub fn def_path_hash(self, def_id: DefId) -> hir_map::DefPathHash {
if def_id.is_local() {
self.hir().definitions().def_path_hash(def_id.index)
self.definitions.def_path_hash(def_id.index)
} else {
self.cstore.def_path_hash(def_id)
}
@ -1333,9 +1343,9 @@ impl<'tcx> TyCtxt<'tcx> {
#[inline(always)]
pub fn create_stable_hashing_context(self) -> StableHashingContext<'tcx> {
let krate = self.gcx.hir_map.untracked_krate();
let krate = self.gcx.untracked_crate;
StableHashingContext::new(self.sess, krate, self.hir().definitions(), &*self.cstore)
StableHashingContext::new(self.sess, krate, self.definitions, &*self.cstore)
}
// This method makes sure that we have a DepNode and a Fingerprint for

View file

@ -1,5 +1,6 @@
use crate::dep_graph::{self, DepConstructor, DepNode, DepNodeParams};
use crate::hir::exports::Export;
use crate::hir::map;
use crate::hir::{HirOwner, HirOwnerItems};
use crate::infer::canonical::{self, Canonical};
use crate::lint::LintLevelMap;