diff options
| author | bors <bors@rust-lang.org> | 2017-01-08 11:36:52 +0000 |
|---|---|---|
| committer | bors <bors@rust-lang.org> | 2017-01-08 11:36:52 +0000 |
| commit | cbf88730e755d099c854f84dd0f1990490bf0088 (patch) | |
| tree | d963b89f70bd039ba13fb0ef7f5393a30e315226 /src/librustc_save_analysis | |
| parent | 7ac9d337dcc544b4b1959997cdd36f1ba0c8d3e1 (diff) | |
| parent | cde0a7e7e01f64caed45e97ff958821d9247959e (diff) | |
| download | rust-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.rs | 50 | ||||
| -rw-r--r-- | src/librustc_save_analysis/lib.rs | 36 |
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) => {{ |
