[] 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);
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(
-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, _)| {
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,
}
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)
// different owner.
}
}
+*/
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;
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 EarlyMap<'hir> {
+ pub 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(crate) definitions: &'hir Definitions,
+
+ /// The reverse mapping of `node_to_hir_id`.
+ 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> {
- krate: &'hir Crate<'hir>,
+ pub(super) tcx: TyCtxt<'hir>,
+
+ pub(super) krate: &'hir Crate<'hir>,
pub dep_graph: DepGraph,
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(super) 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>,
}
/// An iterator that walks up the ancestor tree of a given `HirId`.
}
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>> {
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) {
}
}
-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;
}
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`.
collector.finalize_and_compute_crate_hash(crate_disambiguator, cstore, cmdline_args)
};
- let map = Map {
+ let map = EarlyMap {
krate,
dep_graph,
crate_hash,
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", || {
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;
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 {
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);
}
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
}
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};
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};
/// 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.
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,
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);
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.
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));
}
.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(),
#[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)
}
#[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
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;