Cache ids between lowering runs
So that lowering is reproducible
This commit is contained in:
parent
ce80094632
commit
21205f4f9e
7 changed files with 86 additions and 24 deletions
|
@ -318,6 +318,10 @@ impl NodeIdAssigner for Session {
|
||||||
fn next_node_id(&self) -> NodeId {
|
fn next_node_id(&self) -> NodeId {
|
||||||
self.reserve_node_ids(1)
|
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> {
|
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);
|
let expanded_crate = assign_node_ids(&sess, expanded_crate);
|
||||||
// Lower ast -> hir.
|
// Lower ast -> hir.
|
||||||
let foo = &42;
|
let lcx = LoweringContext::new(&sess, &expanded_crate);
|
||||||
let lcx = LoweringContext::new(foo, &sess, &expanded_crate);
|
|
||||||
let mut hir_forest = time(sess.time_passes(),
|
let mut hir_forest = time(sess.time_passes(),
|
||||||
"lowering ast -> hir",
|
"lowering ast -> hir",
|
||||||
|| hir_map::Forest::new(lower_crate(&lcx, &expanded_crate)));
|
|| 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 ast_map: Option<&'a hir_map::Map<'ast>>,
|
||||||
pub analysis: Option<&'a ty::CrateAnalysis>,
|
pub analysis: Option<&'a ty::CrateAnalysis>,
|
||||||
pub tcx: Option<&'a ty::ctxt<'tcx>>,
|
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>,
|
pub trans: Option<&'a trans::CrateTranslation>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -340,7 +339,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
|
||||||
krate: &'a ast::Crate,
|
krate: &'a ast::Crate,
|
||||||
hir_crate: &'a hir::Crate,
|
hir_crate: &'a hir::Crate,
|
||||||
crate_name: &'a str,
|
crate_name: &'a str,
|
||||||
lcx: &'a LoweringContext<'a, 'tcx>)
|
lcx: &'a LoweringContext<'a>)
|
||||||
-> CompileState<'a, 'ast, 'tcx> {
|
-> CompileState<'a, 'ast, 'tcx> {
|
||||||
CompileState {
|
CompileState {
|
||||||
crate_name: Some(crate_name),
|
crate_name: Some(crate_name),
|
||||||
|
@ -359,7 +358,7 @@ impl<'a, 'ast, 'tcx> CompileState<'a, 'ast, 'tcx> {
|
||||||
hir_crate: &'a hir::Crate,
|
hir_crate: &'a hir::Crate,
|
||||||
analysis: &'a ty::CrateAnalysis,
|
analysis: &'a ty::CrateAnalysis,
|
||||||
tcx: &'a ty::ctxt<'tcx>,
|
tcx: &'a ty::ctxt<'tcx>,
|
||||||
lcx: &'a LoweringContext<'a, 'tcx>)
|
lcx: &'a LoweringContext<'a>)
|
||||||
-> CompileState<'a, 'ast, 'tcx> {
|
-> CompileState<'a, 'ast, 'tcx> {
|
||||||
CompileState {
|
CompileState {
|
||||||
analysis: Some(analysis),
|
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
|
// There is some twisted, god-forsaken tangle of lifetimes here which makes
|
||||||
// the ordering of stuff super-finicky.
|
// the ordering of stuff super-finicky.
|
||||||
let mut hir_forest;
|
let mut hir_forest;
|
||||||
let foo = &42;
|
let lcx = LoweringContext::new(&sess, &krate);
|
||||||
let lcx = LoweringContext::new(foo, &sess, &krate);
|
|
||||||
let arenas = ty::CtxtArenas::new();
|
let arenas = ty::CtxtArenas::new();
|
||||||
let ast_map = if compute_ast_map {
|
let ast_map = if compute_ast_map {
|
||||||
hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
|
hir_forest = hir_map::Forest::new(lower_crate(&lcx, &krate));
|
||||||
|
|
|
@ -12,6 +12,8 @@
|
||||||
|
|
||||||
use hir;
|
use hir;
|
||||||
|
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use syntax::ast::*;
|
use syntax::ast::*;
|
||||||
use syntax::ptr::P;
|
use syntax::ptr::P;
|
||||||
use syntax::codemap::{respan, Spanned, Span};
|
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::parse::token::{self, str_to_ident};
|
||||||
use syntax::std_inject;
|
use syntax::std_inject;
|
||||||
|
|
||||||
pub struct LoweringContext<'a, 'hir> {
|
use std::cell::{Cell, RefCell};
|
||||||
// TODO
|
|
||||||
foo: &'hir i32,
|
pub struct LoweringContext<'a> {
|
||||||
id_assigner: &'a NodeIdAssigner,
|
|
||||||
crate_root: Option<&'static str>,
|
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> {
|
impl<'a, 'hir> LoweringContext<'a> {
|
||||||
pub fn new(foo: &'hir i32, id_assigner: &'a NodeIdAssigner, c: &Crate) -> LoweringContext<'a, 'hir> {
|
pub fn new(id_assigner: &'a NodeIdAssigner, c: &Crate) -> LoweringContext<'a> {
|
||||||
let crate_root = if std_inject::no_core(c) {
|
let crate_root = if std_inject::no_core(c) {
|
||||||
None
|
None
|
||||||
} else if std_inject::no_std(c) {
|
} else if std_inject::no_std(c) {
|
||||||
|
@ -37,14 +41,21 @@ impl<'a, 'hir> LoweringContext<'a, 'hir> {
|
||||||
};
|
};
|
||||||
|
|
||||||
LoweringContext {
|
LoweringContext {
|
||||||
foo: foo,
|
|
||||||
id_assigner: id_assigner,
|
|
||||||
crate_root: crate_root,
|
crate_root: crate_root,
|
||||||
|
id_cache: RefCell::new(HashMap::new()),
|
||||||
|
id_assigner: id_assigner,
|
||||||
|
cached_id: Cell::new(0),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn next_id(&self) -> NodeId {
|
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> {
|
pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
||||||
P(hir::Expr {
|
P(hir::Expr {
|
||||||
id: e.id,
|
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 ));
|
// std::intrinsics::move_val_init(raw_place, pop_unsafe!( EXPR ));
|
||||||
// InPlace::finalize(place)
|
// InPlace::finalize(place)
|
||||||
// })
|
// })
|
||||||
|
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||||
// TODO
|
|
||||||
println!("{}", lctx.foo);
|
|
||||||
|
|
||||||
let placer_expr = lower_expr(lctx, placer);
|
let placer_expr = lower_expr(lctx, placer);
|
||||||
let value_expr = lower_expr(lctx, value_expr);
|
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`.
|
// might be `if let`.
|
||||||
ExprIf(ref cond, ref blk, ref else_opt) => {
|
ExprIf(ref cond, ref blk, ref else_opt) => {
|
||||||
let else_opt = else_opt.as_ref().map(|els| match els.node {
|
let else_opt = else_opt.as_ref().map(|els| match els.node {
|
||||||
|
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||||
ExprIfLet(..) => {
|
ExprIfLet(..) => {
|
||||||
// wrap the if-let expr in a block
|
// wrap the if-let expr in a block
|
||||||
let span = els.span;
|
let span = els.span;
|
||||||
|
@ -1020,6 +1073,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
|
||||||
// _ => [<else_opt> | ()]
|
// _ => [<else_opt> | ()]
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||||
|
|
||||||
// `<pat> => <body>`
|
// `<pat> => <body>`
|
||||||
let pat_arm = {
|
let pat_arm = {
|
||||||
let body_expr = expr_block(lctx, lower_block(lctx, body));
|
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>`
|
// `<pat> => <body>`
|
||||||
let pat_arm = {
|
let pat_arm = {
|
||||||
let body_expr = expr_block(lctx, lower_block(lctx, body));
|
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
|
// result
|
||||||
// }
|
// }
|
||||||
|
|
||||||
|
let _old_cached = CachedIdSetter::new(lctx, e.id);
|
||||||
|
|
||||||
// expand <head>
|
// expand <head>
|
||||||
let head = lower_expr(lctx, head);
|
let head = lower_expr(lctx, head);
|
||||||
|
|
||||||
|
|
|
@ -76,7 +76,7 @@ pub struct DumpCsvVisitor<'l, 'tcx: 'l> {
|
||||||
|
|
||||||
impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
|
||||||
pub fn new(tcx: &'l ty::ctxt<'tcx>,
|
pub fn new(tcx: &'l ty::ctxt<'tcx>,
|
||||||
lcx: &'l LoweringContext<'l, 'tcx>,
|
lcx: &'l LoweringContext<'l>,
|
||||||
analysis: &'l ty::CrateAnalysis,
|
analysis: &'l ty::CrateAnalysis,
|
||||||
output_file: Box<File>)
|
output_file: Box<File>)
|
||||||
-> DumpCsvVisitor<'l, 'tcx> {
|
-> DumpCsvVisitor<'l, 'tcx> {
|
||||||
|
|
|
@ -38,7 +38,7 @@ mod dump_csv;
|
||||||
|
|
||||||
pub struct SaveContext<'l, 'tcx: 'l> {
|
pub struct SaveContext<'l, 'tcx: 'l> {
|
||||||
tcx: &'l ty::ctxt<'tcx>,
|
tcx: &'l ty::ctxt<'tcx>,
|
||||||
lcx: &'l lowering::LoweringContext<'l, 'tcx>,
|
lcx: &'l lowering::LoweringContext<'l>,
|
||||||
span_utils: SpanUtils<'l>,
|
span_utils: SpanUtils<'l>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -178,14 +178,14 @@ pub struct MethodCallData {
|
||||||
|
|
||||||
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
|
||||||
pub fn new(tcx: &'l ty::ctxt<'tcx>,
|
pub fn new(tcx: &'l ty::ctxt<'tcx>,
|
||||||
lcx: &'l lowering::LoweringContext<'l, 'tcx>)
|
lcx: &'l lowering::LoweringContext<'l>)
|
||||||
-> SaveContext<'l, 'tcx> {
|
-> SaveContext<'l, 'tcx> {
|
||||||
let span_utils = SpanUtils::new(&tcx.sess);
|
let span_utils = SpanUtils::new(&tcx.sess);
|
||||||
SaveContext::from_span_utils(tcx, lcx, span_utils)
|
SaveContext::from_span_utils(tcx, lcx, span_utils)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn from_span_utils(tcx: &'l ty::ctxt<'tcx>,
|
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>)
|
span_utils: SpanUtils<'l>)
|
||||||
-> SaveContext<'l, 'tcx> {
|
-> SaveContext<'l, 'tcx> {
|
||||||
SaveContext {
|
SaveContext {
|
||||||
|
@ -711,7 +711,7 @@ impl<'v> Visitor<'v> for PathCollector {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn process_crate<'l, 'tcx>(tcx: &'l ty::ctxt<'tcx>,
|
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,
|
krate: &ast::Crate,
|
||||||
analysis: &ty::CrateAnalysis,
|
analysis: &ty::CrateAnalysis,
|
||||||
odir: Option<&Path>) {
|
odir: Option<&Path>) {
|
||||||
|
|
|
@ -377,6 +377,7 @@ pub const DUMMY_NODE_ID: NodeId = !0;
|
||||||
|
|
||||||
pub trait NodeIdAssigner {
|
pub trait NodeIdAssigner {
|
||||||
fn next_node_id(&self) -> NodeId;
|
fn next_node_id(&self) -> NodeId;
|
||||||
|
fn peek_node_id(&self) -> NodeId;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// The AST represents all type param bounds as types.
|
/// The AST represents all type param bounds as types.
|
||||||
|
|
Loading…
Reference in a new issue