about summary refs log tree commit diff
path: root/src/librustc_save_analysis
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2017-01-08 11:36:52 +0000
committerbors <bors@rust-lang.org>2017-01-08 11:36:52 +0000
commitcbf88730e755d099c854f84dd0f1990490bf0088 (patch)
treed963b89f70bd039ba13fb0ef7f5393a30e315226 /src/librustc_save_analysis
parent7ac9d337dcc544b4b1959997cdd36f1ba0c8d3e1 (diff)
parentcde0a7e7e01f64caed45e97ff958821d9247959e (diff)
downloadrust-cbf88730e755d099c854f84dd0f1990490bf0088.tar.gz
rust-cbf88730e755d099c854f84dd0f1990490bf0088.zip
Auto merge of #38813 - eddyb:lazy-11, r=nikomatsakis
[11/n] Separate ty::Tables into one per each body.

_This is part of a series ([prev](https://github.com/rust-lang/rust/pull/38449) | [next]()) of patches designed to rework rustc into an out-of-order on-demand pipeline model for both better feature support (e.g. [MIR-based](https://github.com/solson/miri) early constant evaluation) and incremental execution of compiler passes (e.g. type-checking), with beneficial consequences to IDE support as well.
If any motivation is unclear, please ask for additional PR description clarifications or code comments._

<hr>

In order to track the results of type-checking and inference for incremental recompilation, they must be stored separately for each function or constant value, instead of lumped together.

These side-`Tables` also have to be tracked by various passes, as they visit through bodies (all of which have `Tables`, even if closures share the ones from their parent functions). This is usually done by switching a `tables` field in an override of `visit_nested_body` before recursing through `visit_body`, to the relevant one and then restoring it - however, in many cases the nesting is unnecessary and creating the visitor for each body in the crate and then visiting that body, would be a much cleaner solution.

To simplify handling of inlined HIR & its side-tables, their `NodeId` remapping and entries HIR map were fully stripped out, which means that `NodeId`s from inlined HIR must not be used where a local `NodeId` is expected. It might be possible to make the nodes (`Expr`, `Block`, `Pat`, etc.) that only show up within a `Body` have IDs that are scoped to that `Body`, which would also allow `Tables` to use `Vec`s.

That last part also fixes #38790 which was accidentally introduced in a previous refactor.
Diffstat (limited to 'src/librustc_save_analysis')
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs50
-rw-r--r--src/librustc_save_analysis/lib.rs36
2 files changed, 48 insertions, 38 deletions
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index 093a739c69f..424017ebd12 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -99,7 +99,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
         }
     }
 
-    fn nest<F>(&mut self, scope_id: NodeId, f: F)
+    fn nest_scope<F>(&mut self, scope_id: NodeId, f: F)
         where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>)
     {
         let parent_scope = self.cur_scope;
@@ -108,6 +108,16 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
         self.cur_scope = parent_scope;
     }
 
+    fn nest_tables<F>(&mut self, item_id: NodeId, f: F)
+        where F: FnOnce(&mut DumpVisitor<'l, 'tcx, 'll, D>)
+    {
+        let old_tables = self.save_ctxt.tables;
+        let item_def_id = self.tcx.map.local_def_id(item_id);
+        self.save_ctxt.tables = self.tcx.item_tables(item_def_id);
+        f(self);
+        self.save_ctxt.tables = old_tables;
+    }
+
     pub fn dump_crate_info(&mut self, name: &str, krate: &ast::Crate) {
         let source_file = self.tcx.sess.local_crate_source_file.as_ref();
         let crate_root = source_file.map(|source_file| {
@@ -337,7 +347,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
             collector.visit_pat(&arg.pat);
             let span_utils = self.span.clone();
             for &(id, ref p, ..) in &collector.collected_paths {
-                let typ = match self.tcx.tables().node_types.get(&id) {
+                let typ = match self.save_ctxt.tables.node_types.get(&id) {
                     Some(s) => s.to_string(),
                     None => continue,
                 };
@@ -378,7 +388,9 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
 
             let sig_str = ::make_signature(&sig.decl, &sig.generics);
             if body.is_some() {
-                self.process_formals(&sig.decl.inputs, &method_data.qualname);
+                self.nest_tables(id, |v| {
+                    v.process_formals(&sig.decl.inputs, &method_data.qualname)
+                });
             }
 
             // If the method is defined in an impl, then try and find the corresponding
@@ -448,7 +460,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
 
         // walk the fn body
         if let Some(body) = body {
-            self.nest(id, |v| v.visit_block(body));
+            self.nest_tables(id, |v| v.nest_scope(id, |v| v.visit_block(body)));
         }
     }
 
@@ -520,7 +532,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                 self.dumper.function(fn_data.clone().lower(self.tcx));
             }
 
-            self.process_formals(&decl.inputs, &fn_data.qualname);
+            self.nest_tables(item.id, |v| v.process_formals(&decl.inputs, &fn_data.qualname));
             self.process_generic_params(ty_params, item.span, &fn_data.qualname, item.id);
         }
 
@@ -532,7 +544,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
             self.visit_ty(&ret_ty);
         }
 
-        self.nest(item.id, |v| v.visit_block(&body));
+        self.nest_tables(item.id, |v| v.nest_scope(item.id, |v| v.visit_block(&body)));
     }
 
     fn process_static_or_const_item(&mut self,
@@ -991,7 +1003,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
         match p.node {
             PatKind::Struct(ref path, ref fields, _) => {
                 visit::walk_path(self, path);
-                let adt = match self.tcx.tables().node_id_to_type_opt(p.id) {
+                let adt = match self.save_ctxt.tables.node_id_to_type_opt(p.id) {
                     Some(ty) => ty.ty_adt_def().unwrap(),
                     None => {
                         visit::walk_pat(self, p);
@@ -1032,7 +1044,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
                 ast::Mutability::Immutable => value.to_string(),
                 _ => String::new(),
             };
-            let typ = match self.tcx.tables().node_types.get(&id) {
+            let typ = match self.save_ctxt.tables.node_types.get(&id) {
                 Some(typ) => {
                     let typ = typ.to_string();
                     if !value.is_empty() {
@@ -1286,7 +1298,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
                 self.process_trait(item, generics, trait_refs, methods),
             Mod(ref m) => {
                 self.process_mod(item);
-                self.nest(item.id, |v| visit::walk_mod(v, m));
+                self.nest_scope(item.id, |v| visit::walk_mod(v, m));
             }
             Ty(ref ty, ref ty_params) => {
                 let qualname = format!("::{}", self.tcx.node_path_str(item.id));
@@ -1349,6 +1361,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
 
                 visit::walk_path(self, path);
             }
+            ast::TyKind::Array(ref element, ref length) => {
+                self.visit_ty(element);
+                self.nest_tables(length.id, |v| v.visit_expr(length));
+            }
             _ => visit::walk_ty(self, t),
         }
     }
@@ -1367,7 +1383,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
             }
             ast::ExprKind::Struct(ref path, ref fields, ref base) => {
                 let hir_expr = self.save_ctxt.tcx.map.expect_expr(ex.id);
-                let adt = match self.tcx.tables().expr_ty_opt(&hir_expr) {
+                let adt = match self.save_ctxt.tables.expr_ty_opt(&hir_expr) {
                     Some(ty) => ty.ty_adt_def().unwrap(),
                     None => {
                         visit::walk_expr(self, ex);
@@ -1399,7 +1415,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
                         return;
                     }
                 };
-                let ty = match self.tcx.tables().expr_ty_adjusted_opt(&hir_node) {
+                let ty = match self.save_ctxt.tables.expr_ty_adjusted_opt(&hir_node) {
                     Some(ty) => &ty.sty,
                     None => {
                         visit::walk_expr(self, ex);
@@ -1427,7 +1443,6 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
             ast::ExprKind::Closure(_, ref decl, ref body, _fn_decl_span) => {
                 let mut id = String::from("$");
                 id.push_str(&ex.id.to_string());
-                self.process_formals(&decl.inputs, &id);
 
                 // walk arg and return types
                 for arg in &decl.inputs {
@@ -1439,7 +1454,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
                 }
 
                 // walk the body
-                self.nest(ex.id, |v| v.visit_expr(body));
+                self.nest_tables(ex.id, |v| {
+                    v.process_formals(&decl.inputs, &id);
+                    v.nest_scope(ex.id, |v| v.visit_expr(body))
+                });
             }
             ast::ExprKind::ForLoop(ref pattern, ref subexpression, ref block, _) |
             ast::ExprKind::WhileLet(ref pattern, ref subexpression, ref block, _) => {
@@ -1455,6 +1473,10 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
                 visit::walk_block(self, block);
                 opt_else.as_ref().map(|el| visit::walk_expr(self, el));
             }
+            ast::ExprKind::Repeat(ref element, ref count) => {
+                self.visit_expr(element);
+                self.nest_tables(count.id, |v| v.visit_expr(count));
+            }
             _ => {
                 visit::walk_expr(self, ex)
             }
@@ -1492,7 +1514,7 @@ impl<'l, 'tcx: 'l, 'll, D: Dump +'ll> Visitor<'l> for DumpVisitor<'l, 'tcx, 'll,
                     } else {
                         "<mutable>".to_string()
                     };
-                    let typ = self.tcx.tables().node_types
+                    let typ = self.save_ctxt.tables.node_types
                                   .get(&id).map(|t| t.to_string()).unwrap_or(String::new());
                     value.push_str(": ");
                     value.push_str(&typ);
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index 3f7f3bdba01..0fbe29880b9 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -84,6 +84,7 @@ pub mod recorder {
 
 pub struct SaveContext<'l, 'tcx: 'l> {
     tcx: TyCtxt<'l, 'tcx, 'tcx>,
+    tables: &'l ty::Tables<'tcx>,
     analysis: &'l ty::CrateAnalysis<'tcx>,
     span_utils: SpanUtils<'tcx>,
 }
@@ -93,24 +94,6 @@ macro_rules! option_try(
 );
 
 impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
-    pub fn new(tcx: TyCtxt<'l, 'tcx, 'tcx>,
-               analysis: &'l ty::CrateAnalysis<'tcx>)
-               -> SaveContext<'l, 'tcx> {
-        let span_utils = SpanUtils::new(&tcx.sess);
-        SaveContext::from_span_utils(tcx, analysis, span_utils)
-    }
-
-    pub fn from_span_utils(tcx: TyCtxt<'l, 'tcx, 'tcx>,
-                           analysis: &'l ty::CrateAnalysis<'tcx>,
-                           span_utils: SpanUtils<'tcx>)
-                           -> SaveContext<'l, 'tcx> {
-        SaveContext {
-            tcx: tcx,
-            analysis: analysis,
-            span_utils: span_utils,
-        }
-    }
-
     // List external crates used by the current crate.
     pub fn get_external_crates(&self) -> Vec<CrateData> {
         let mut result = Vec::new();
@@ -460,7 +443,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
 
     pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
         let hir_node = self.tcx.map.expect_expr(expr.id);
-        let ty = self.tcx.tables().expr_ty_adjusted_opt(&hir_node);
+        let ty = self.tables.expr_ty_adjusted_opt(&hir_node);
         if ty.is_none() || ty.unwrap().sty == ty::TyError {
             return None;
         }
@@ -474,7 +457,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                         return None;
                     }
                 };
-                match self.tcx.tables().expr_ty_adjusted(&hir_node).sty {
+                match self.tables.expr_ty_adjusted(&hir_node).sty {
                     ty::TyAdt(def, _) if !def.is_enum() => {
                         let f = def.struct_variant().field_named(ident.node.name);
                         let sub_span = self.span_utils.span_for_last_ident(expr.span);
@@ -493,7 +476,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 }
             }
             ast::ExprKind::Struct(ref path, ..) => {
-                match self.tcx.tables().expr_ty_adjusted(&hir_node).sty {
+                match self.tables.expr_ty_adjusted(&hir_node).sty {
                     ty::TyAdt(def, _) if !def.is_enum() => {
                         let sub_span = self.span_utils.span_for_last_ident(path.span);
                         filter!(self.span_utils, sub_span, path.span, None);
@@ -514,7 +497,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             }
             ast::ExprKind::MethodCall(..) => {
                 let method_call = ty::MethodCall::expr(expr.id);
-                let method_id = self.tcx.tables().method_map[&method_call].def_id;
+                let method_id = self.tables.method_map[&method_call].def_id;
                 let (def_id, decl_id) = match self.tcx.associated_item(method_id).container {
                     ty::ImplContainer(_) => (Some(method_id), None),
                     ty::TraitContainer(_) => (None, Some(method_id)),
@@ -551,7 +534,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
             Node::NodePat(&hir::Pat { node: hir::PatKind::Path(ref qpath), .. }) |
             Node::NodePat(&hir::Pat { node: hir::PatKind::Struct(ref qpath, ..), .. }) |
             Node::NodePat(&hir::Pat { node: hir::PatKind::TupleStruct(ref qpath, ..), .. }) => {
-                self.tcx.tables().qpath_def(qpath, id)
+                self.tables.qpath_def(qpath, id)
             }
 
             Node::NodeLocal(&hir::Pat { node: hir::PatKind::Binding(_, def_id, ..), .. }) => {
@@ -914,7 +897,12 @@ pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
     root_path.pop();
     let output = &mut output_file;
 
-    let save_ctxt = SaveContext::new(tcx, analysis);
+    let save_ctxt = SaveContext {
+        tcx: tcx,
+        tables: &ty::Tables::empty(),
+        analysis: analysis,
+        span_utils: SpanUtils::new(&tcx.sess),
+    };
 
     macro_rules! dump {
         ($new_dumper: expr) => {{