Rollup merge of #35114 - michaelwoerister:inline-meta-to-hir-map, r=eddyb
Move caching of inlined HIR into CrateStore So far we've had separate HIR-inlining caches for each codegen unit and the caching for things inlined during constant evaluation had some holes. Consequently, things would be inlined multiple times if they were used from different codegen units, etc, leading to - wasted memory, - multiple `NodeId`s per `DefId` and, - for things inlined during constant evaluation, no way to map a `NodeId` back to it's original `DefId`. This PR moves all caching into the CrateStore, solving all of the above problems. It also fixes some bugs in the inlining code, like cyclic in the parent-chains in the HIR map and some `NodeId`'s being translated to more or less random values. There are assertions in place now that should prevent this kind of thing in the future. This PR based on top of #35090, which contains some necessary fixes.
This commit is contained in:
commit
518524de1a
17 changed files with 335 additions and 175 deletions
|
|
@ -867,7 +867,7 @@ pub fn walk_vis<'v, V: Visitor<'v>>(visitor: &mut V, vis: &'v Visibility) {
|
|||
}
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug)]
|
||||
#[derive(Copy, Clone, RustcEncodable, RustcDecodable, Debug, PartialEq, Eq)]
|
||||
pub struct IdRange {
|
||||
pub min: NodeId,
|
||||
pub max: NodeId,
|
||||
|
|
@ -893,6 +893,7 @@ impl IdRange {
|
|||
self.min = cmp::min(self.min, id);
|
||||
self.max = cmp::max(self.max, id + 1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ use hir::print as pprust;
|
|||
|
||||
use arena::TypedArena;
|
||||
use std::cell::RefCell;
|
||||
use std::cmp;
|
||||
use std::io;
|
||||
use std::mem;
|
||||
|
||||
|
|
@ -127,7 +128,10 @@ impl<'ast> MapEntry<'ast> {
|
|||
EntryStructCtor(id, _) => id,
|
||||
EntryLifetime(id, _) => id,
|
||||
EntryTyParam(id, _) => id,
|
||||
_ => return None
|
||||
|
||||
NotPresent |
|
||||
RootCrate |
|
||||
RootInlinedParent(_) => return None,
|
||||
})
|
||||
}
|
||||
|
||||
|
|
@ -196,6 +200,10 @@ pub struct Map<'ast> {
|
|||
map: RefCell<Vec<MapEntry<'ast>>>,
|
||||
|
||||
definitions: RefCell<Definitions>,
|
||||
|
||||
/// All NodeIds that are numerically greater or equal to this value come
|
||||
/// from inlined items.
|
||||
local_node_id_watermark: NodeId,
|
||||
}
|
||||
|
||||
impl<'ast> Map<'ast> {
|
||||
|
|
@ -550,6 +558,13 @@ impl<'ast> Map<'ast> {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn expect_inlined_item(&self, id: NodeId) -> &'ast InlinedItem {
|
||||
match self.find_entry(id) {
|
||||
Some(RootInlinedParent(inlined_item)) => inlined_item,
|
||||
_ => bug!("expected inlined item, found {}", self.node_to_string(id)),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the name associated with the given NodeId's AST.
|
||||
pub fn name(&self, id: NodeId) -> Name {
|
||||
match self.get(id) {
|
||||
|
|
@ -649,6 +664,10 @@ impl<'ast> Map<'ast> {
|
|||
pub fn node_to_user_string(&self, id: NodeId) -> String {
|
||||
node_id_to_string(self, id, false)
|
||||
}
|
||||
|
||||
pub fn is_inlined(&self, id: NodeId) -> bool {
|
||||
id >= self.local_node_id_watermark
|
||||
}
|
||||
}
|
||||
|
||||
pub struct NodesMatchingSuffix<'a, 'ast:'a> {
|
||||
|
|
@ -765,13 +784,37 @@ pub trait FoldOps {
|
|||
}
|
||||
|
||||
/// A Folder that updates IDs and Span's according to fold_ops.
|
||||
struct IdAndSpanUpdater<F> {
|
||||
fold_ops: F
|
||||
pub struct IdAndSpanUpdater<F> {
|
||||
fold_ops: F,
|
||||
min_id_assigned: NodeId,
|
||||
max_id_assigned: NodeId,
|
||||
}
|
||||
|
||||
impl<F: FoldOps> IdAndSpanUpdater<F> {
|
||||
pub fn new(fold_ops: F) -> IdAndSpanUpdater<F> {
|
||||
IdAndSpanUpdater {
|
||||
fold_ops: fold_ops,
|
||||
min_id_assigned: ::std::u32::MAX,
|
||||
max_id_assigned: ::std::u32::MIN,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn id_range(&self) -> intravisit::IdRange {
|
||||
intravisit::IdRange {
|
||||
min: self.min_id_assigned,
|
||||
max: self.max_id_assigned + 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<F: FoldOps> Folder for IdAndSpanUpdater<F> {
|
||||
fn new_id(&mut self, id: NodeId) -> NodeId {
|
||||
self.fold_ops.new_id(id)
|
||||
let id = self.fold_ops.new_id(id);
|
||||
|
||||
self.min_id_assigned = cmp::min(self.min_id_assigned, id);
|
||||
self.max_id_assigned = cmp::max(self.max_id_assigned, id);
|
||||
|
||||
id
|
||||
}
|
||||
|
||||
fn new_span(&mut self, span: Span) -> Span {
|
||||
|
|
@ -802,11 +845,14 @@ pub fn map_crate<'ast>(forest: &'ast mut Forest,
|
|||
entries, vector_length, (entries as f64 / vector_length as f64) * 100.);
|
||||
}
|
||||
|
||||
let local_node_id_watermark = map.len() as NodeId;
|
||||
|
||||
Map {
|
||||
forest: forest,
|
||||
dep_graph: forest.dep_graph.clone(),
|
||||
map: RefCell::new(map),
|
||||
definitions: RefCell::new(definitions),
|
||||
local_node_id_watermark: local_node_id_watermark
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -818,7 +864,7 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
|
|||
ii: InlinedItem,
|
||||
fold_ops: F)
|
||||
-> &'ast InlinedItem {
|
||||
let mut fld = IdAndSpanUpdater { fold_ops: fold_ops };
|
||||
let mut fld = IdAndSpanUpdater::new(fold_ops);
|
||||
let ii = match ii {
|
||||
II::Item(i) => II::Item(i.map(|i| fld.fold_item(i))),
|
||||
II::TraitItem(d, ti) => {
|
||||
|
|
@ -835,6 +881,12 @@ pub fn map_decoded_item<'ast, F: FoldOps>(map: &Map<'ast>,
|
|||
let ii = map.forest.inlined_items.alloc(ii);
|
||||
let ii_parent_id = fld.new_id(DUMMY_NODE_ID);
|
||||
|
||||
// Assert that the ii_parent_id is the last NodeId in our reserved range
|
||||
assert!(ii_parent_id == fld.max_id_assigned);
|
||||
// Assert that we did not violate the invariant that all inlined HIR items
|
||||
// have NodeIds greater than or equal to `local_node_id_watermark`
|
||||
assert!(fld.min_id_assigned >= map.local_node_id_watermark);
|
||||
|
||||
let defs = &mut *map.definitions.borrow_mut();
|
||||
let mut def_collector = DefCollector::extend(ii_parent_id,
|
||||
parent_def_path.clone(),
|
||||
|
|
|
|||
|
|
@ -120,12 +120,6 @@ pub struct ChildItem {
|
|||
pub vis: ty::Visibility,
|
||||
}
|
||||
|
||||
pub enum FoundAst<'ast> {
|
||||
Found(&'ast InlinedItem),
|
||||
FoundParent(DefId, &'ast hir::Item),
|
||||
NotFound,
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct ExternCrate {
|
||||
/// def_id of an `extern crate` in the current crate that caused
|
||||
|
|
@ -250,7 +244,10 @@ pub trait CrateStore<'tcx> {
|
|||
|
||||
// misc. metadata
|
||||
fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> FoundAst<'tcx>;
|
||||
-> Option<(&'tcx InlinedItem, ast::NodeId)>;
|
||||
fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId>;
|
||||
fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId>;
|
||||
|
||||
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<Mir<'tcx>>;
|
||||
fn is_item_mir_available(&self, def: DefId) -> bool;
|
||||
|
|
@ -447,7 +444,16 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
|
|||
|
||||
// misc. metadata
|
||||
fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> FoundAst<'tcx> { bug!("maybe_get_item_ast") }
|
||||
-> Option<(&'tcx InlinedItem, ast::NodeId)> {
|
||||
bug!("maybe_get_item_ast")
|
||||
}
|
||||
fn local_node_for_inlined_defid(&'tcx self, def_id: DefId) -> Option<ast::NodeId> {
|
||||
bug!("local_node_for_inlined_defid")
|
||||
}
|
||||
fn defid_for_inlined_node(&'tcx self, node_id: ast::NodeId) -> Option<DefId> {
|
||||
bug!("defid_for_inlined_node")
|
||||
}
|
||||
|
||||
fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
|
||||
-> Option<Mir<'tcx>> { bug!("maybe_get_item_mir") }
|
||||
fn is_item_mir_available(&self, def: DefId) -> bool {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue