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.
This commit is contained in:
commit
cbf88730e7
76 changed files with 1128 additions and 1415 deletions
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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) => {{
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue