about summary refs log tree commit diff
diff options
context:
space:
mode:
authorNick Cameron <ncameron@mozilla.com>2015-09-30 16:17:37 +1300
committerNick Cameron <ncameron@mozilla.com>2015-10-09 11:53:42 +1300
commit21205f4f9e61469b55a853cf6be478cd6bc7a073 (patch)
treeb94d564d03e377f438378e0b2cc2b42d7a688832
parentce80094632c727ef87b465fc87873cce1c471ad6 (diff)
downloadrust-21205f4f9e61469b55a853cf6be478cd6bc7a073.tar.gz
rust-21205f4f9e61469b55a853cf6be478cd6bc7a073.zip
Cache ids between lowering runs
So that lowering is reproducible
-rw-r--r--src/librustc/session/mod.rs4
-rw-r--r--src/librustc_driver/driver.rs9
-rw-r--r--src/librustc_driver/pretty.rs3
-rw-r--r--src/librustc_front/lowering.rs83
-rw-r--r--src/librustc_trans/save/dump_csv.rs2
-rw-r--r--src/librustc_trans/save/mod.rs8
-rw-r--r--src/libsyntax/ast.rs1
7 files changed, 86 insertions, 24 deletions
diff --git a/src/librustc/session/mod.rs b/src/librustc/session/mod.rs
index 1eb90580b48..0a1df25f115 100644
--- a/src/librustc/session/mod.rs
+++ b/src/librustc/session/mod.rs
@@ -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> {
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 6f989811ed2..3db484ef930 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -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),
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index 09a1d6f6851..73961c8d757 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -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));
diff --git a/src/librustc_front/lowering.rs b/src/librustc_front/lowering.rs
index 2b63e0615ee..27ae39acbf4 100644
--- a/src/librustc_front/lowering.rs
+++ b/src/librustc_front/lowering.rs
@@ -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;
@@ -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 = {
@@ -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);
 
diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs
index 256774756b8..09825f1f919 100644
--- a/src/librustc_trans/save/dump_csv.rs
+++ b/src/librustc_trans/save/dump_csv.rs
@@ -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> {
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index 5e26322ebda..72f665f63bf 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -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>) {
diff --git a/src/libsyntax/ast.rs b/src/libsyntax/ast.rs
index bf43b87b267..02cd648b6d8 100644
--- a/src/libsyntax/ast.rs
+++ b/src/libsyntax/ast.rs
@@ -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.