Cache ids between lowering runs
So that lowering is reproducible
This commit is contained in:
parent
ce80094632
commit
21205f4f9e
|
@ -318,6 +318,10 @@ impl NodeIdAssigner for Session {
|
|||
fn next_node_id(&self) -> NodeId {
|
||||
self.reserve_node_ids(1)
|
||||
}
|
||||
|
||||
fn peek_node_id(&self) -> NodeId {
|
||||
self.next_node_id.get().checked_add(1).unwrap()
|
||||
}
|
||||
}
|
||||
|
||||
fn split_msg_into_multilines(msg: &str) -> Option<String> {
|
||||
|
|
|
@ -112,8 +112,7 @@ pub fn compile_input(sess: Session,
|
|||
|
||||
let expanded_crate = assign_node_ids(&sess, expanded_crate);
|
||||
// Lower ast -> hir.
|
||||
let foo = &42;
|
||||
let lcx = LoweringContext::new(foo, &sess, &expanded_crate);
|
||||
let lcx = LoweringContext::new(&sess, &expanded_crate);
|
||||
let mut hir_forest = time(sess.time_passes(),
|
||||
"lowering ast -> hir",
|
||||
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
|
||||
|
@ -282,7 +281,7 @@ pub struct CompileState<'a, 'ast: 'a, 'tcx: 'a> {
|
|||
pub ast_map: Option<&'a hir_map::Map<'ast>>,
|
||||
pub analysis: Option<&'a ty::CrateAnalysis>,
|
||||
pub tcx: Option<&'a ty::ctxt<'tcx>>,
|
||||
pub lcx: Option<&'a LoweringContext<'a, 'tcx>>,
|
||||
pub lcx: Option<&'a LoweringContext<'a>>,
|
||||
pub trans: Option<&'a trans::CrateTranslation>,
|
||||
}
|
||||
|
||||
|
@ -340,7 +339,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
|
|||
krate: &'a ast::Crate,
|
||||
hir_crate: &'a hir::Crate,
|
||||
crate_name: &'a str,
|
||||
lcx: &'a LoweringContext<'a, 'tcx>)
|
||||
lcx: &'a LoweringContext<'a>)
|
||||
-> CompileState<'a, 'ast, 'tcx> {
|
||||
CompileState {
|
||||
crate_name: Some(crate_name),
|
||||
|
@ -359,7 +358,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
|
|||
hir_crate: &'a hir::Crate,
|
||||
analysis: &'a ty::CrateAnalysis,
|
||||
tcx: &'a ty::ctxt<'tcx>,
|
||||
lcx: &'a LoweringContext<'a, 'tcx>)
|
||||
lcx: &'a LoweringContext<'a>)
|
||||
-> CompileState<'a, 'ast, 'tcx> {
|
||||
CompileState {
|
||||
analysis: Some(analysis),
|
||||
|
|
|
@ -670,8 +670,7 @@ pub fn pretty_print_input(sess: Session,
|
|||
// There is some twisted, god-forsaken tangle of lifetimes here which makes
|
||||
// the ordering of stuff super-finicky.
|
||||
let mut hir_forest;
|
||||
let foo = &42;
|
||||
let lcx = LoweringContext::new(foo, &sess, &krate);
|
||||
let lcx = LoweringContext::new(&sess, &krate);
|
||||
let arenas = ty::CtxtArenas::new();
|
||||
let ast_map = if compute_ast_map {
|
||||
hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
|
||||
|
|
|
@ -12,6 +12,8 @@
|
|||
|
||||
use hir;
|
||||
|
||||
use std::collections::HashMap;
|
||||
|
||||
use syntax::ast::*;
|
||||
use syntax::ptr::P;
|
||||
use syntax::codemap::{respan, Spanned, Span};
|
||||
|
@ -19,15 +21,17 @@ use syntax::owned_slice::OwnedSlice;
|
|||
use syntax::parse::token::{self, str_to_ident};
|
||||
use syntax::std_inject;
|
||||
|
||||
pub struct LoweringContext<'a, 'hir> {
|
||||
// TODO
|
||||
foo: &'hir i32,
|
||||
id_assigner: &'a NodeIdAssigner,
|
||||
use std::cell::{Cell, RefCell};
|
||||
|
||||
pub struct LoweringContext<'a> {
|
||||
crate_root: Option<&'static str>,
|
||||
id_cache: RefCell<HashMap<NodeId, NodeId>>,
|
||||
id_assigner: &'a NodeIdAssigner,
|
||||
cached_id: Cell<u32>,
|
||||
}
|
||||
|
||||
impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||
pub fn new(foo: &'hir i32, id_assigner: &'a NodeIdAssigner, c: &Crate) -> LoweringContext<'a, 'hir> {
|
||||
impl<'a, 'hir> LoweringContext<'a> {
|
||||
pub fn new(id_assigner: &'a NodeIdAssigner, c: &Crate) -> LoweringContext<'a> {
|
||||
let crate_root = if std_inject::no_core(c) {
|
||||
None
|
||||
} else if std_inject::no_std(c) {
|
||||
|
@ -37,14 +41,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
|||
};
|
||||
|
||||
LoweringContext {
|
||||
foo: foo,
|
||||
id_assigner: id_assigner,
|
||||
crate_root: crate_root,
|
||||
id_cache: RefCell::new(HashMap::new()),
|
||||
id_assigner: id_assigner,
|
||||
cached_id: Cell::new(0),
|
||||
}
|
||||
}
|
||||
|
||||
fn next_id(&self) -> NodeId {
|
||||
self.id_assigner.next_node_id()
|
||||
let cached = self.cached_id.get();
|
||||
if cached == 0 {
|
||||
return self.id_assigner.next_node_id()
|
||||
}
|
||||
|
||||
self.cached_id.set(cached + 1);
|
||||
cached
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -745,6 +756,49 @@ pub fn lower_pat(_lctx: &LoweringContext, p: &Pat) -> P<hir::Pat> {
|
|||
})
|
||||
}
|
||||
|
||||
// RAII utility for setting and unsetting the cached id.
|
||||
struct CachedIdSetter<'a> {
|
||||
reset: bool,
|
||||
lctx: &'a LoweringContext<'a>,
|
||||
}
|
||||
|
||||
impl<'a> CachedIdSetter<'a> {
|
||||
fn new(lctx: &'a LoweringContext, expr_id: NodeId) -> CachedIdSetter<'a> {
|
||||
let id_cache: &mut HashMap<_, _> = &mut lctx.id_cache.borrow_mut();
|
||||
|
||||
if id_cache.contains_key(&expr_id) {
|
||||
let cached_id = lctx.cached_id.get();
|
||||
if cached_id == 0 {
|
||||
// We're entering a node where we need to track ids, but are not
|
||||
// yet tracking.
|
||||
lctx.cached_id.set(id_cache[&expr_id]);
|
||||
} else {
|
||||
// We're already tracking - check that the tracked id is the same
|
||||
// as the expected id.
|
||||
assert!(cached_id == id_cache[&expr_id], "id mismatch");
|
||||
}
|
||||
} else {
|
||||
id_cache.insert(expr_id, lctx.id_assigner.peek_node_id());
|
||||
}
|
||||
|
||||
CachedIdSetter {
|
||||
// Only reset the id if it was previously 0, i.e., was not cached.
|
||||
// If it was cached, we are in a nested node, but our id count will
|
||||
// still count towards the parent's count.
|
||||
reset: lctx.cached_id.get() == 0,
|
||||
lctx: lctx,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl<'a> Drop for CachedIdSetter<'a> {
|
||||
fn drop(&mut self) {
|
||||
if self.reset {
|
||||
self.lctx.cached_id.set(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
||||
P(hir::Expr {
|
||||
id: e.id,
|
||||
|
@ -780,9 +834,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
|||
// std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
|
||||
// InPlace::finalize(place)
|
||||
// })
|
||||
|
||||
// TODO
|
||||
println!("{}", lctx.foo);
|
||||
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||
|
||||
let placer_expr = lower_expr(lctx, placer);
|
||||
let value_expr = lower_expr(lctx, value_expr);
|
||||
|
@ -903,6 +955,7 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
|||
// might be `if let`.
|
||||
ExprIf(ref cond, ref blk, ref else_opt) => {
|
||||
let else_opt = else_opt.as_ref().map(|els| match els.node {
|
||||
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||
ExprIfLet(..) => {
|
||||
// wrap the if-let expr in a block
|
||||
let span = els.span;
|
||||
|
@ -1020,6 +1073,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
|||
// _ => [<else_opt> | ()]
|
||||
// }
|
||||
|
||||
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||
|
||||
// `<pat> => <body>`
|
||||
let pat_arm = {
|
||||
let body_expr = expr_block(lctx, lower_block(lctx, body));
|
||||
|
@ -1098,6 +1153,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
|||
// }
|
||||
// }
|
||||
|
||||
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||
|
||||
// `<pat> => <body>`
|
||||
let pat_arm = {
|
||||
let body_expr = expr_block(lctx, lower_block(lctx, body));
|
||||
|
@ -1141,6 +1198,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
|||
// result
|
||||
// }
|
||||
|
||||
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||
|
||||
// expand <head>
|
||||
let head = lower_expr(lctx, head);
|
||||
|
||||
|
|
|
@ -76,7 +76,7 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
|
|||
|
||||
impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||
pub fn new(tcx: &'l ty::ctxt<'tcx>,
|
||||
lcx: &'l LoweringContext<'l, 'tcx>,
|
||||
lcx: &'l LoweringContext<'l>,
|
||||
analysis: &'l ty::CrateAnalysis,
|
||||
output_file: Box<File>)
|
||||
-> DumpCsvVisitor<'l, 'tcx> {
|
||||
|
|
|
@ -38,7 +38,7 @@ mod dump_csv;
|
|||
|
||||
pub struct SaveContext<'l, 'tcx: 'l> {
|
||||
tcx: &'l ty::ctxt<'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l, 'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l>,
|
||||
span_utils: SpanUtils<'l>,
|
||||
}
|
||||
|
||||
|
@ -178,14 +178,14 @@ pub struct MethodCallData {
|
|||
|
||||
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||
pub fn new(tcx: &'l ty::ctxt<'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l, 'tcx>)
|
||||
lcx: &'l lowering::LoweringContext<'l>)
|
||||
-> SaveContext<'l, 'tcx> {
|
||||
let span_utils = SpanUtils::new(&tcx.sess);
|
||||
SaveContext::from_span_utils(tcx, lcx, span_utils)
|
||||
}
|
||||
|
||||
pub fn from_span_utils(tcx: &'l ty::ctxt<'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l, 'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l>,
|
||||
span_utils: SpanUtils<'l>)
|
||||
-> SaveContext<'l, 'tcx> {
|
||||
SaveContext {
|
||||
|
@ -711,7 +711,7 @@ impl<'v> Visitor<'v> for PathCollector {
|
|||
}
|
||||
|
||||
pub fn process_crate<'l, 'tcx>(tcx: &'l ty::ctxt<'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l, 'tcx>,
|
||||
lcx: &'l lowering::LoweringContext<'l>,
|
||||
krate: &ast::Crate,
|
||||
analysis: &ty::CrateAnalysis,
|
||||
odir: Option<&Path>) {
|
||||
|
|
|
@ -377,6 +377,7 @@ pub const DUMMY_NODE_ID: NodeId = !0;
|
|||
|
||||
pub trait NodeIdAssigner {
|
||||
fn next_node_id(&self) -> NodeId;
|
||||
fn peek_node_id(&self) -> NodeId;
|
||||
}
|
||||
|
||||
/// The AST represents all type param bounds as types.
|
||||
|
|
Loading…
Reference in New Issue