Skip to content

Commit

Permalink
Cache ids between lowering runs
Browse files Browse the repository at this point in the history
So that lowering is reproducible
  • Loading branch information
nrc committed Oct 8, 2015
1 parent ce80094 commit 21205f4
Show file tree
Hide file tree
Showing 7 changed files with 86 additions and 24 deletions.
4 changes: 4 additions & 0 deletions src/librustc/session/mod.rs
Expand Up @@ -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> {
Expand Down
9 changes: 4 additions & 5 deletions src/librustc_driver/driver.rs
Expand Up @@ -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)));
Expand Down Expand Up @@ -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>,
}

Expand Down Expand Up @@ -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),
Expand All @@ -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),
Expand Down
3 changes: 1 addition & 2 deletions src/librustc_driver/pretty.rs
Expand Up @@ -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));
Expand Down
83 changes: 71 additions & 12 deletions src/librustc_front/lowering.rs
Expand Up @@ -12,22 +12,26 @@

use hir;

use std::collections::HashMap;

use syntax::ast::*;
use syntax::ptr::P;
use syntax::codemap::{respan, Spanned, Span};
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) {
Expand All @@ -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
}
}

Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -1019,6 +1072,8 @@ pub fn lower_expr(lctx: &LoweringContext, e: &Expr) -> P<hir::Expr> {
// [_ if <else_opt_if_cond> => <else_opt_if_body>,]
// _ => [<else_opt> | ()]
// }

let _old_cached = CachedIdSetter::new(lctx, e.id);

// `<pat> => <body>`
let pat_arm = {
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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);

Expand Down
2 changes: 1 addition & 1 deletion src/librustc_trans/save/dump_csv.rs
Expand Up @@ -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> {
Expand Down
8 changes: 4 additions & 4 deletions src/librustc_trans/save/mod.rs
Expand Up @@ -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>,
}

Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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>) {
Expand Down
1 change: 1 addition & 0 deletions src/libsyntax/ast.rs
Expand Up @@ -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.
Expand Down

0 comments on commit 21205f4

Please sign in to comment.