From 28ddd7a4ef30a89091dbf48cae18f571326510fb Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Aug 2017 19:27:30 +0300 Subject: [PATCH 1/3] rustc: use hir::ItemLocalId instead of ast::NodeId in CFG. --- src/librustc/cfg/construct.rs | 89 +++++++++-------- src/librustc/cfg/graphviz.rs | 63 ++++++------ src/librustc/cfg/mod.rs | 13 +-- src/librustc/hir/map/mod.rs | 15 ++- src/librustc/middle/dataflow.rs | 96 ++++++++++--------- src/librustc_borrowck/borrowck/check_loans.rs | 60 +++++++----- .../borrowck/gather_loans/gather_moves.rs | 15 +-- .../borrowck/gather_loans/mod.rs | 12 ++- src/librustc_borrowck/borrowck/mod.rs | 17 ++-- src/librustc_borrowck/borrowck/move_data.rs | 55 +++++------ src/librustc_borrowck/graphviz.rs | 2 +- src/librustc_driver/pretty.rs | 2 +- src/librustc_lint/builtin.rs | 26 ++--- 13 files changed, 249 insertions(+), 216 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index e7e2c84fc4efa..1448fb7c528c6 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -12,7 +12,6 @@ use rustc_data_structures::graph; use cfg::*; use middle::region::CodeExtent; use ty::{self, TyCtxt}; -use syntax::ast; use syntax::ptr::P; use hir::{self, PatKind}; @@ -30,13 +29,13 @@ struct CFGBuilder<'a, 'tcx: 'a> { #[derive(Copy, Clone)] struct BlockScope { - block_expr_id: ast::NodeId, // id of breakable block expr node + block_expr_id: hir::ItemLocalId, // id of breakable block expr node break_index: CFGIndex, // where to go on `break` } #[derive(Copy, Clone)] struct LoopScope { - loop_id: ast::NodeId, // id of loop/while node + loop_id: hir::ItemLocalId, // id of loop/while node continue_index: CFGIndex, // where to go on a `loop` break_index: CFGIndex, // where to go on a `break` } @@ -70,6 +69,7 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, cfg_builder.add_contained_edge(body_exit, fn_exit); let CFGBuilder { graph, .. } = cfg_builder; CFG { + owner_def_id, graph, entry, exit: fn_exit, @@ -79,10 +79,10 @@ pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn block(&mut self, blk: &hir::Block, pred: CFGIndex) -> CFGIndex { if blk.targeted_by_break { - let expr_exit = self.add_ast_node(blk.id, &[]); + let expr_exit = self.add_ast_node(blk.hir_id.local_id, &[]); self.breakable_block_scopes.push(BlockScope { - block_expr_id: blk.id, + block_expr_id: blk.hir_id.local_id, break_index: expr_exit, }); @@ -104,21 +104,22 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let expr_exit = self.opt_expr(&blk.expr, stmts_exit); - self.add_ast_node(blk.id, &[expr_exit]) + self.add_ast_node(blk.hir_id.local_id, &[expr_exit]) } } fn stmt(&mut self, stmt: &hir::Stmt, pred: CFGIndex) -> CFGIndex { + let hir_id = self.tcx.hir.node_to_hir_id(stmt.node.id()); match stmt.node { - hir::StmtDecl(ref decl, id) => { + hir::StmtDecl(ref decl, _) => { let exit = self.decl(&decl, pred); - self.add_ast_node(id, &[exit]) + self.add_ast_node(hir_id.local_id, &[exit]) } - hir::StmtExpr(ref expr, id) | - hir::StmtSemi(ref expr, id) => { + hir::StmtExpr(ref expr, _) | + hir::StmtSemi(ref expr, _) => { let exit = self.expr(&expr, pred); - self.add_ast_node(id, &[exit]) + self.add_ast_node(hir_id.local_id, &[exit]) } } } @@ -140,31 +141,31 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { PatKind::Path(_) | PatKind::Lit(..) | PatKind::Range(..) | - PatKind::Wild => self.add_ast_node(pat.id, &[pred]), + PatKind::Wild => self.add_ast_node(pat.hir_id.local_id, &[pred]), PatKind::Box(ref subpat) | PatKind::Ref(ref subpat, _) | PatKind::Binding(.., Some(ref subpat)) => { let subpat_exit = self.pat(&subpat, pred); - self.add_ast_node(pat.id, &[subpat_exit]) + self.add_ast_node(pat.hir_id.local_id, &[subpat_exit]) } PatKind::TupleStruct(_, ref subpats, _) | PatKind::Tuple(ref subpats, _) => { let pats_exit = self.pats_all(subpats.iter(), pred); - self.add_ast_node(pat.id, &[pats_exit]) + self.add_ast_node(pat.hir_id.local_id, &[pats_exit]) } PatKind::Struct(_, ref subpats, _) => { let pats_exit = self.pats_all(subpats.iter().map(|f| &f.node.pat), pred); - self.add_ast_node(pat.id, &[pats_exit]) + self.add_ast_node(pat.hir_id.local_id, &[pats_exit]) } PatKind::Slice(ref pre, ref vec, ref post) => { let pre_exit = self.pats_all(pre.iter(), pred); let vec_exit = self.pats_all(vec.iter(), pre_exit); let post_exit = self.pats_all(post.iter(), vec_exit); - self.add_ast_node(pat.id, &[post_exit]) + self.add_ast_node(pat.hir_id.local_id, &[post_exit]) } } } @@ -180,7 +181,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { match expr.node { hir::ExprBlock(ref blk) => { let blk_exit = self.block(&blk, pred); - self.add_ast_node(expr.id, &[blk_exit]) + self.add_ast_node(expr.hir_id.local_id, &[blk_exit]) } hir::ExprIf(ref cond, ref then, None) => { @@ -200,7 +201,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // let cond_exit = self.expr(&cond, pred); // 1 let then_exit = self.expr(&then, cond_exit); // 2 - self.add_ast_node(expr.id, &[cond_exit, then_exit]) // 3,4 + self.add_ast_node(expr.hir_id.local_id, &[cond_exit, then_exit]) // 3,4 } hir::ExprIf(ref cond, ref then, Some(ref otherwise)) => { @@ -221,7 +222,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let cond_exit = self.expr(&cond, pred); // 1 let then_exit = self.expr(&then, cond_exit); // 2 let else_exit = self.expr(&otherwise, cond_exit); // 3 - self.add_ast_node(expr.id, &[then_exit, else_exit]) // 4, 5 + self.add_ast_node(expr.hir_id.local_id, &[then_exit, else_exit]) // 4, 5 } hir::ExprWhile(ref cond, ref body, _) => { @@ -245,12 +246,12 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { let loopback = self.add_dummy_node(&[pred]); // 1 // Create expr_exit without pred (cond_exit) - let expr_exit = self.add_ast_node(expr.id, &[]); // 3 + let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 3 // The LoopScope needs to be on the loop_scopes stack while evaluating the // condition and the body of the loop (both can break out of the loop) self.loop_scopes.push(LoopScope { - loop_id: expr.id, + loop_id: expr.hir_id.local_id, continue_index: loopback, break_index: expr_exit }); @@ -282,9 +283,9 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // may cause additional edges. let loopback = self.add_dummy_node(&[pred]); // 1 - let expr_exit = self.add_ast_node(expr.id, &[]); // 2 + let expr_exit = self.add_ast_node(expr.hir_id.local_id, &[]); // 2 self.loop_scopes.push(LoopScope { - loop_id: expr.id, + loop_id: expr.hir_id.local_id, continue_index: loopback, break_index: expr_exit, }); @@ -295,7 +296,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ExprMatch(ref discr, ref arms, _) => { - self.match_(expr.id, &discr, &arms, pred) + self.match_(expr.hir_id.local_id, &discr, &arms, pred) } hir::ExprBinary(op, ref l, ref r) if op.node.is_lazy() => { @@ -315,30 +316,30 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { // let l_exit = self.expr(&l, pred); // 1 let r_exit = self.expr(&r, l_exit); // 2 - self.add_ast_node(expr.id, &[l_exit, r_exit]) // 3,4 + self.add_ast_node(expr.hir_id.local_id, &[l_exit, r_exit]) // 3,4 } hir::ExprRet(ref v) => { let v_exit = self.opt_expr(v, pred); - let b = self.add_ast_node(expr.id, &[v_exit]); + let b = self.add_ast_node(expr.hir_id.local_id, &[v_exit]); self.add_returning_edge(expr, b); self.add_unreachable_node() } hir::ExprBreak(destination, ref opt_expr) => { let v = self.opt_expr(opt_expr, pred); - let (scope_id, break_dest) = + let (target_scope, break_dest) = self.find_scope_edge(expr, destination, ScopeCfKind::Break); - let b = self.add_ast_node(expr.id, &[v]); - self.add_exiting_edge(expr, b, scope_id, break_dest); + let b = self.add_ast_node(expr.hir_id.local_id, &[v]); + self.add_exiting_edge(expr, b, target_scope, break_dest); self.add_unreachable_node() } hir::ExprAgain(destination) => { - let (scope_id, cont_dest) = + let (target_scope, cont_dest) = self.find_scope_edge(expr, destination, ScopeCfKind::Continue); - let a = self.add_ast_node(expr.id, &[pred]); - self.add_exiting_edge(expr, a, scope_id, cont_dest); + let a = self.add_ast_node(expr.hir_id.local_id, &[pred]); + self.add_exiting_edge(expr, a, target_scope, cont_dest); self.add_unreachable_node() } @@ -397,7 +398,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ExprInlineAsm(_, ref outputs, ref inputs) => { let post_outputs = self.exprs(outputs.iter().map(|e| &*e), pred); let post_inputs = self.exprs(inputs.iter().map(|e| &*e), post_outputs); - self.add_ast_node(expr.id, &[post_inputs]) + self.add_ast_node(expr.hir_id.local_id, &[post_inputs]) } hir::ExprClosure(..) | @@ -444,10 +445,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { //! Handles case of an expression that evaluates `subexprs` in order let subexprs_exit = self.exprs(subexprs, pred); - self.add_ast_node(expr.id, &[subexprs_exit]) + self.add_ast_node(expr.hir_id.local_id, &[subexprs_exit]) } - fn match_(&mut self, id: ast::NodeId, discr: &hir::Expr, + fn match_(&mut self, id: hir::ItemLocalId, discr: &hir::Expr, arms: &[hir::Arm], pred: CFGIndex) -> CFGIndex { // The CFG for match expression is quite complex, so no ASCII // art for it (yet). @@ -552,8 +553,7 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { self.add_node(CFGNodeData::Dummy, preds) } - fn add_ast_node(&mut self, id: ast::NodeId, preds: &[CFGIndex]) -> CFGIndex { - assert!(id != ast::DUMMY_NODE_ID); + fn add_ast_node(&mut self, id: hir::ItemLocalId, preds: &[CFGIndex]) -> CFGIndex { self.add_node(CFGNodeData::AST(id), preds) } @@ -579,14 +579,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn add_exiting_edge(&mut self, from_expr: &hir::Expr, from_index: CFGIndex, - scope_id: ast::NodeId, + target_scope: CodeExtent, to_index: CFGIndex) { let mut data = CFGEdgeData { exiting_scopes: vec![] }; let mut scope = CodeExtent::Misc(from_expr.id); - let target_scope = CodeExtent::Misc(scope_id); let region_maps = self.tcx.region_maps(self.owner_def_id); while scope != target_scope { - data.exiting_scopes.push(scope.node_id()); + data.exiting_scopes.push(self.tcx.hir.node_to_hir_id(scope.node_id()).local_id); scope = region_maps.encl_scope(scope); } self.graph.add_edge(from_index, to_index, data); @@ -607,13 +606,13 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { fn find_scope_edge(&self, expr: &hir::Expr, destination: hir::Destination, - scope_cf_kind: ScopeCfKind) -> (ast::NodeId, CFGIndex) { + scope_cf_kind: ScopeCfKind) -> (CodeExtent, CFGIndex) { match destination.target_id { hir::ScopeTarget::Block(block_expr_id) => { for b in &self.breakable_block_scopes { - if b.block_expr_id == block_expr_id { - return (block_expr_id, match scope_cf_kind { + if b.block_expr_id == self.tcx.hir.node_to_hir_id(block_expr_id).local_id { + return (CodeExtent::Misc(block_expr_id), match scope_cf_kind { ScopeCfKind::Break => b.break_index, ScopeCfKind::Continue => bug!("can't continue to block"), }); @@ -623,8 +622,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { } hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => { for l in &self.loop_scopes { - if l.loop_id == loop_id { - return (loop_id, match scope_cf_kind { + if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { + return (CodeExtent::Misc(loop_id), match scope_cf_kind { ScopeCfKind::Break => l.break_index, ScopeCfKind::Continue => l.continue_index, }); diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc/cfg/graphviz.rs index 944b77dbf01fd..fa034744b62e2 100644 --- a/src/librustc/cfg/graphviz.rs +++ b/src/librustc/cfg/graphviz.rs @@ -15,40 +15,47 @@ use graphviz as dot; use graphviz::IntoCow; -use syntax::ast; - -use hir::map as hir_map; use cfg; +use hir; +use ty::TyCtxt; pub type Node<'a> = (cfg::CFGIndex, &'a cfg::CFGNode); pub type Edge<'a> = &'a cfg::CFGEdge; -pub struct LabelledCFG<'a, 'hir: 'a> { - pub hir_map: &'a hir_map::Map<'hir>, +pub struct LabelledCFG<'a, 'tcx: 'a> { + pub tcx: TyCtxt<'a, 'tcx, 'tcx>, pub cfg: &'a cfg::CFG, pub name: String, /// `labelled_edges` controls whether we emit labels on the edges pub labelled_edges: bool, } -fn replace_newline_with_backslash_l(s: String) -> String { - // Replacing newlines with \\l causes each line to be left-aligned, - // improving presentation of (long) pretty-printed expressions. - if s.contains("\n") { - let mut s = s.replace("\n", "\\l"); - // Apparently left-alignment applies to the line that precedes - // \l, not the line that follows; so, add \l at end of string - // if not already present, ensuring last line gets left-aligned - // as well. - let mut last_two: Vec<_> = - s.chars().rev().take(2).collect(); - last_two.reverse(); - if last_two != ['\\', 'l'] { - s.push_str("\\l"); +impl<'a, 'tcx> LabelledCFG<'a, 'tcx> { + fn local_id_to_string(&self, local_id: hir::ItemLocalId) -> String { + let node_id = self.tcx.hir.hir_to_node_id(hir::HirId { + owner: self.tcx.closure_base_def_id(self.cfg.owner_def_id).index, + local_id + }); + let s = self.tcx.hir.node_to_string(node_id); + + // Replacing newlines with \\l causes each line to be left-aligned, + // improving presentation of (long) pretty-printed expressions. + if s.contains("\n") { + let mut s = s.replace("\n", "\\l"); + // Apparently left-alignment applies to the line that precedes + // \l, not the line that follows; so, add \l at end of string + // if not already present, ensuring last line gets left-aligned + // as well. + let mut last_two: Vec<_> = + s.chars().rev().take(2).collect(); + last_two.reverse(); + if last_two != ['\\', 'l'] { + s.push_str("\\l"); + } + s + } else { + s } - s - } else { - s } } @@ -66,12 +73,10 @@ impl<'a, 'hir> dot::Labeller<'a> for LabelledCFG<'a, 'hir> { dot::LabelText::LabelStr("entry".into_cow()) } else if i == self.cfg.exit { dot::LabelText::LabelStr("exit".into_cow()) - } else if n.data.id() == ast::DUMMY_NODE_ID { + } else if n.data.id() == hir::DUMMY_ITEM_LOCAL_ID { dot::LabelText::LabelStr("(dummy_node)".into_cow()) } else { - let s = self.hir_map.node_to_string(n.data.id()); - // left-aligns the lines - let s = replace_newline_with_backslash_l(s); + let s = self.local_id_to_string(n.data.id()); dot::LabelText::EscStr(s.into_cow()) } } @@ -82,15 +87,13 @@ impl<'a, 'hir> dot::Labeller<'a> for LabelledCFG<'a, 'hir> { return dot::LabelText::EscStr(label.into_cow()); } let mut put_one = false; - for (i, &node_id) in e.data.exiting_scopes.iter().enumerate() { + for (i, &id) in e.data.exiting_scopes.iter().enumerate() { if put_one { label.push_str(",\\l"); } else { put_one = true; } - let s = self.hir_map.node_to_string(node_id); - // left-aligns the lines - let s = replace_newline_with_backslash_l(s); + let s = self.local_id_to_string(id); label.push_str(&format!("exiting scope_{} {}", i, &s[..])); diff --git a/src/librustc/cfg/mod.rs b/src/librustc/cfg/mod.rs index 1473dbb1676f3..b379d3956e944 100644 --- a/src/librustc/cfg/mod.rs +++ b/src/librustc/cfg/mod.rs @@ -13,13 +13,14 @@ use rustc_data_structures::graph; use ty::TyCtxt; -use syntax::ast; use hir; +use hir::def_id::DefId; mod construct; pub mod graphviz; pub struct CFG { + pub owner_def_id: DefId, pub graph: CFGGraph, pub entry: CFGIndex, pub exit: CFGIndex, @@ -27,7 +28,7 @@ pub struct CFG { #[derive(Copy, Clone, Debug, PartialEq)] pub enum CFGNodeData { - AST(ast::NodeId), + AST(hir::ItemLocalId), Entry, Exit, Dummy, @@ -35,18 +36,18 @@ pub enum CFGNodeData { } impl CFGNodeData { - pub fn id(&self) -> ast::NodeId { + pub fn id(&self) -> hir::ItemLocalId { if let CFGNodeData::AST(id) = *self { id } else { - ast::DUMMY_NODE_ID + hir::DUMMY_ITEM_LOCAL_ID } } } #[derive(Debug)] pub struct CFGEdgeData { - pub exiting_scopes: Vec + pub exiting_scopes: Vec } pub type CFGIndex = graph::NodeIndex; @@ -63,7 +64,7 @@ impl CFG { construct::construct(tcx, body) } - pub fn node_is_reachable(&self, id: ast::NodeId) -> bool { + pub fn node_is_reachable(&self, id: hir::ItemLocalId) -> bool { self.graph.depth_traverse(self.entry, graph::OUTGOING) .any(|idx| self.graph.node_data(idx).id() == id) } diff --git a/src/librustc/hir/map/mod.rs b/src/librustc/hir/map/mod.rs index 31b0b5c820e3d..e54df2d50d8eb 100644 --- a/src/librustc/hir/map/mod.rs +++ b/src/librustc/hir/map/mod.rs @@ -26,7 +26,7 @@ use syntax_pos::Span; use hir::*; use hir::print::Nested; -use util::nodemap::DefIdMap; +use util::nodemap::{DefIdMap, FxHashMap}; use arena::TypedArena; use std::cell::RefCell; @@ -251,6 +251,9 @@ pub struct Map<'hir> { /// Bodies inlined from other crates are cached here. inlined_bodies: RefCell>, + + /// The reverse mapping of `node_to_hir_id`. + hir_to_node_id: FxHashMap, } impl<'hir> Map<'hir> { @@ -339,6 +342,11 @@ impl<'hir> Map<'hir> { self.definitions.as_local_node_id(def_id) } + #[inline] + pub fn hir_to_node_id(&self, hir_id: HirId) -> NodeId { + self.hir_to_node_id[&hir_id] + } + #[inline] pub fn node_to_hir_id(&self, node_id: NodeId) -> HirId { self.definitions.node_to_hir_id(node_id) @@ -1021,10 +1029,15 @@ pub fn map_crate<'hir>(forest: &'hir mut Forest, entries, vector_length, (entries as f64 / vector_length as f64) * 100.); } + // Build the reverse mapping of `node_to_hir_id`. + let hir_to_node_id = definitions.node_to_hir_id.iter_enumerated() + .map(|(node_id, &hir_id)| (hir_id, node_id)).collect(); + let map = Map { forest, dep_graph: forest.dep_graph.clone(), map, + hir_to_node_id, definitions, inlined_bodies: RefCell::new(DefIdMap()), }; diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs index d394c0f0c8734..e88678dea1d74 100644 --- a/src/librustc/middle/dataflow.rs +++ b/src/librustc/middle/dataflow.rs @@ -20,12 +20,11 @@ use ty::TyCtxt; use std::io; use std::mem; use std::usize; -use syntax::ast; use syntax::print::pprust::PrintState; use rustc_data_structures::graph::OUTGOING; -use util::nodemap::NodeMap; +use util::nodemap::FxHashMap; use hir; use hir::intravisit::{self, IdRange}; use hir::print as pprust; @@ -56,7 +55,7 @@ pub struct DataFlowContext<'a, 'tcx: 'a, O> { // mapping from node to cfg node index // FIXME (#6298): Shouldn't this go with CFG? - nodeid_to_index: NodeMap>, + local_id_to_index: FxHashMap>, // Bit sets per cfg node. The following three fields (`gens`, `kills`, // and `on_entry`) all have the same structure. For each id in @@ -97,15 +96,16 @@ struct PropagationContext<'a, 'b: 'a, 'tcx: 'b, O: 'a> { changed: bool } -fn get_cfg_indices<'a>(id: ast::NodeId, index: &'a NodeMap>) -> &'a [CFGIndex] { - let opt_indices = index.get(&id); - opt_indices.map(|v| &v[..]).unwrap_or(&[]) +fn get_cfg_indices<'a>(id: hir::ItemLocalId, + index: &'a FxHashMap>) + -> &'a [CFGIndex] { + index.get(&id).map_or(&[], |v| &v[..]) } impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { - fn has_bitset_for_nodeid(&self, n: ast::NodeId) -> bool { - assert!(n != ast::DUMMY_NODE_ID); - self.nodeid_to_index.contains_key(&n) + fn has_bitset_for_local_id(&self, n: hir::ItemLocalId) -> bool { + assert!(n != hir::DUMMY_ITEM_LOCAL_ID); + self.local_id_to_index.contains_key(&n) } } @@ -117,19 +117,20 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O ps: &mut pprust::State, node: pprust::AnnNode) -> io::Result<()> { let id = match node { - pprust::NodeName(_) => ast::CRATE_NODE_ID, - pprust::NodeExpr(expr) => expr.id, - pprust::NodeBlock(blk) => blk.id, - pprust::NodeItem(_) | pprust::NodeSubItem(_) => ast::CRATE_NODE_ID, - pprust::NodePat(pat) => pat.id + pprust::NodeName(_) => return Ok(()), + pprust::NodeExpr(expr) => expr.hir_id.local_id, + pprust::NodeBlock(blk) => blk.hir_id.local_id, + pprust::NodeItem(_) | + pprust::NodeSubItem(_) => return Ok(()), + pprust::NodePat(pat) => pat.hir_id.local_id }; - if !self.has_bitset_for_nodeid(id) { + if !self.has_bitset_for_local_id(id) { return Ok(()); } assert!(self.bits_per_id > 0); - let indices = get_cfg_indices(id, &self.nodeid_to_index); + let indices = get_cfg_indices(id, &self.local_id_to_index); for &cfgidx in indices { let (start, end) = self.compute_id_range(cfgidx); let on_entry = &self.on_entry[start.. end]; @@ -157,7 +158,7 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O }; ps.synth_comment( - format!("id {}: {}{}{}{}", id, entry_str, + format!("id {}: {}{}{}{}", id.as_usize(), entry_str, gens_str, action_kills_str, scope_kills_str))?; ps.s.space()?; } @@ -165,9 +166,10 @@ impl<'a, 'tcx, O:DataFlowOperator> pprust::PpAnn for DataFlowContext<'a, 'tcx, O } } -fn build_nodeid_to_index(body: Option<&hir::Body>, - cfg: &cfg::CFG) -> NodeMap> { - let mut index = NodeMap(); +fn build_local_id_to_index(body: Option<&hir::Body>, + cfg: &cfg::CFG) + -> FxHashMap> { + let mut index = FxHashMap(); // FIXME (#6298): Would it be better to fold formals from decl // into cfg itself? i.e. introduce a fn-based flow-graph in @@ -188,14 +190,14 @@ fn build_nodeid_to_index(body: Option<&hir::Body>, /// Add mappings from the ast nodes for the formal bindings to /// the entry-node in the graph. - fn add_entries_from_fn_body(index: &mut NodeMap>, + fn add_entries_from_fn_body(index: &mut FxHashMap>, body: &hir::Body, entry: CFGIndex) { use hir::intravisit::Visitor; struct Formals<'a> { entry: CFGIndex, - index: &'a mut NodeMap>, + index: &'a mut FxHashMap>, } let mut formals = Formals { entry: entry, index: index }; for arg in &body.arguments { @@ -207,7 +209,7 @@ fn build_nodeid_to_index(body: Option<&hir::Body>, } fn visit_pat(&mut self, p: &hir::Pat) { - self.index.entry(p.id).or_insert(vec![]).push(self.entry); + self.index.entry(p.hir_id.local_id).or_insert(vec![]).push(self.entry); intravisit::walk_pat(self, p) } } @@ -259,13 +261,13 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let kills2 = zeroes; let on_entry = vec![entry; num_nodes * words_per_id]; - let nodeid_to_index = build_nodeid_to_index(body, cfg); + let local_id_to_index = build_local_id_to_index(body, cfg); DataFlowContext { tcx, analysis_name, words_per_id, - nodeid_to_index, + local_id_to_index, bits_per_id, oper, gens, @@ -275,14 +277,14 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } } - pub fn add_gen(&mut self, id: ast::NodeId, bit: usize) { + pub fn add_gen(&mut self, id: hir::ItemLocalId, bit: usize) { //! Indicates that `id` generates `bit` - debug!("{} add_gen(id={}, bit={})", + debug!("{} add_gen(id={:?}, bit={})", self.analysis_name, id, bit); - assert!(self.nodeid_to_index.contains_key(&id)); + assert!(self.local_id_to_index.contains_key(&id)); assert!(self.bits_per_id > 0); - let indices = get_cfg_indices(id, &self.nodeid_to_index); + let indices = get_cfg_indices(id, &self.local_id_to_index); for &cfgidx in indices { let (start, end) = self.compute_id_range(cfgidx); let gens = &mut self.gens[start.. end]; @@ -290,14 +292,14 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } } - pub fn add_kill(&mut self, kind: KillFrom, id: ast::NodeId, bit: usize) { + pub fn add_kill(&mut self, kind: KillFrom, id: hir::ItemLocalId, bit: usize) { //! Indicates that `id` kills `bit` - debug!("{} add_kill(id={}, bit={})", + debug!("{} add_kill(id={:?}, bit={})", self.analysis_name, id, bit); - assert!(self.nodeid_to_index.contains_key(&id)); + assert!(self.local_id_to_index.contains_key(&id)); assert!(self.bits_per_id > 0); - let indices = get_cfg_indices(id, &self.nodeid_to_index); + let indices = get_cfg_indices(id, &self.local_id_to_index); for &cfgidx in indices { let (start, end) = self.compute_id_range(cfgidx); let kills = match kind { @@ -341,15 +343,15 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } - pub fn each_bit_on_entry(&self, id: ast::NodeId, mut f: F) -> bool where + pub fn each_bit_on_entry(&self, id: hir::ItemLocalId, mut f: F) -> bool where F: FnMut(usize) -> bool, { //! Iterates through each bit that is set on entry to `id`. //! Only useful after `propagate()` has been called. - if !self.has_bitset_for_nodeid(id) { + if !self.has_bitset_for_local_id(id) { return true; } - let indices = get_cfg_indices(id, &self.nodeid_to_index); + let indices = get_cfg_indices(id, &self.local_id_to_index); for &cfgidx in indices { if !self.each_bit_for_node(EntryOrExit::Entry, cfgidx, |i| f(i)) { return false; @@ -387,11 +389,11 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { self.each_bit(slice, f) } - pub fn each_gen_bit(&self, id: ast::NodeId, mut f: F) -> bool where + pub fn each_gen_bit(&self, id: hir::ItemLocalId, mut f: F) -> bool where F: FnMut(usize) -> bool, { //! Iterates through each bit in the gen set for `id`. - if !self.has_bitset_for_nodeid(id) { + if !self.has_bitset_for_local_id(id) { return true; } @@ -401,11 +403,11 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { return true; } - let indices = get_cfg_indices(id, &self.nodeid_to_index); + let indices = get_cfg_indices(id, &self.local_id_to_index); for &cfgidx in indices { let (start, end) = self.compute_id_range(cfgidx); let gens = &self.gens[start.. end]; - debug!("{} each_gen_bit(id={}, gens={})", + debug!("{} each_gen_bit(id={:?}, gens={})", self.analysis_name, id, bits_to_string(gens)); if !self.each_bit(gens, |i| f(i)) { return false; @@ -472,17 +474,17 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { let mut orig_kills = self.scope_kills[start.. end].to_vec(); let mut changed = false; - for &node_id in &edge.data.exiting_scopes { - let opt_cfg_idx = self.nodeid_to_index.get(&node_id); + for &id in &edge.data.exiting_scopes { + let opt_cfg_idx = self.local_id_to_index.get(&id); match opt_cfg_idx { Some(indices) => { for &cfg_idx in indices { let (start, end) = self.compute_id_range(cfg_idx); let kills = &self.scope_kills[start.. end]; if bitwise(&mut orig_kills, kills, &Union) { - debug!("scope exits: scope id={} \ + debug!("scope exits: scope id={:?} \ (node={:?} of {:?}) added killset: {}", - node_id, cfg_idx, indices, + id, cfg_idx, indices, bits_to_string(kills)); changed = true; } @@ -490,8 +492,8 @@ impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> { } None => { debug!("{} add_kills_from_flow_exits flow_exit={:?} \ - no cfg_idx for exiting_scope={}", - self.analysis_name, flow_exit, node_id); + no cfg_idx for exiting_scope={:?}", + self.analysis_name, flow_exit, id); } } } @@ -559,7 +561,7 @@ impl<'a, 'b, 'tcx, O:DataFlowOperator> PropagationContext<'a, 'b, 'tcx, O> { // Iterate over nodes in reverse postorder for &node_index in nodes_po.iter().rev() { let node = cfg.graph.node(node_index); - debug!("DataFlowContext::walk_cfg idx={:?} id={} begin in_out={}", + debug!("DataFlowContext::walk_cfg idx={:?} id={:?} begin in_out={}", node_index, node.data.id(), bits_to_string(in_out)); let (start, end) = self.dfcx.compute_id_range(node_index); diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index 4058f3198afb4..e83c79fb4a414 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -103,7 +103,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { debug!("consume(consume_id={}, cmt={:?}, mode={:?})", consume_id, cmt, mode); - self.consume_common(consume_id, consume_span, cmt, mode); + let hir_id = self.tcx().hir.node_to_hir_id(consume_id); + self.consume_common(hir_id.local_id, consume_span, cmt, mode); } fn matched_pat(&mut self, @@ -120,7 +121,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { cmt, mode); - self.consume_common(consume_pat.id, consume_pat.span, cmt, mode); + self.consume_common(consume_pat.hir_id.local_id, consume_pat.span, cmt, mode); } fn borrow(&mut self, @@ -136,15 +137,16 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { borrow_id, cmt, loan_region, bk, loan_cause); + let hir_id = self.tcx().hir.node_to_hir_id(borrow_id); if let Some(lp) = opt_loan_path(&cmt) { let moved_value_use_kind = match loan_cause { euv::ClosureCapture(_) => MovedInCapture, _ => MovedInUse, }; - self.check_if_path_is_moved(borrow_id, borrow_span, moved_value_use_kind, &lp); + self.check_if_path_is_moved(hir_id.local_id, borrow_span, moved_value_use_kind, &lp); } - self.check_for_conflicting_loans(borrow_id); + self.check_for_conflicting_loans(hir_id.local_id); } fn mutate(&mut self, @@ -163,7 +165,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { // have to be *FULLY* initialized, but we still // must be careful lest it contains derefs of // pointers. - self.check_if_assigned_path_is_moved(assignee_cmt.id, + let hir_id = self.tcx().hir.node_to_hir_id(assignee_cmt.id); + self.check_if_assigned_path_is_moved(hir_id.local_id, assignment_span, MovedInUse, &lp); @@ -172,14 +175,16 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for CheckLoanCtxt<'a, 'tcx> { // In a case like `path += 1`, then path must be // fully initialized, since we will read it before // we write it. - self.check_if_path_is_moved(assignee_cmt.id, + let hir_id = self.tcx().hir.node_to_hir_id(assignee_cmt.id); + self.check_if_path_is_moved(hir_id.local_id, assignment_span, MovedInUse, &lp); } } } - self.check_assignment(assignment_id, assignment_span, assignee_cmt); + self.check_assignment(self.tcx().hir.node_to_hir_id(assignment_id).local_id, + assignment_span, assignee_cmt); } fn decl_without_init(&mut self, _id: ast::NodeId, _span: Span) { } @@ -220,7 +225,7 @@ fn compatible_borrow_kinds(borrow_kind1: ty::BorrowKind, impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.bccx.tcx } - pub fn each_issued_loan(&self, node: ast::NodeId, mut op: F) -> bool where + pub fn each_issued_loan(&self, node: hir::ItemLocalId, mut op: F) -> bool where F: FnMut(&Loan<'tcx>) -> bool, { //! Iterates over each loan that has been issued @@ -241,7 +246,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { //! Like `each_issued_loan()`, but only considers loans that are //! currently in scope. - self.each_issued_loan(scope.node_id(), |loan| { + self.each_issued_loan(self.tcx().hir.node_to_hir_id(scope.node_id()).local_id, |loan| { if self.bccx.region_maps.is_subscope_of(scope, loan.kill_scope) { op(loan) } else { @@ -325,7 +330,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { return true; } - pub fn loans_generated_by(&self, node: ast::NodeId) -> Vec { + pub fn loans_generated_by(&self, node: hir::ItemLocalId) -> Vec { //! Returns a vector of the loans that are generated as //! we enter `node`. @@ -337,7 +342,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { return result; } - pub fn check_for_conflicting_loans(&self, node: ast::NodeId) { + pub fn check_for_conflicting_loans(&self, node: hir::ItemLocalId) { //! Checks to see whether any of the loans that are issued //! on entrance to `node` conflict with loans that have already been //! issued when we enter `node` (for example, we do not @@ -590,7 +595,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } fn consume_common(&self, - id: ast::NodeId, + id: hir::ItemLocalId, span: Span, cmt: mc::cmt<'tcx>, mode: euv::ConsumeMode) { @@ -628,7 +633,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } fn check_for_copy_of_frozen_path(&self, - id: ast::NodeId, + id: hir::ItemLocalId, span: Span, copy_path: &LoanPath<'tcx>) { match self.analyze_restrictions_on_use(id, copy_path, ty::ImmBorrow) { @@ -649,7 +654,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } fn check_for_move_of_borrowed_path(&self, - id: ast::NodeId, + id: hir::ItemLocalId, span: Span, move_path: &LoanPath<'tcx>, move_kind: move_data::MoveKind) { @@ -699,18 +704,21 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } pub fn analyze_restrictions_on_use(&self, - expr_id: ast::NodeId, + expr_id: hir::ItemLocalId, use_path: &LoanPath<'tcx>, borrow_kind: ty::BorrowKind) -> UseError<'tcx> { - debug!("analyze_restrictions_on_use(expr_id={}, use_path={:?})", - self.tcx().hir.node_to_string(expr_id), - use_path); + debug!("analyze_restrictions_on_use(expr_id={:?}, use_path={:?})", + expr_id, use_path); let mut ret = UseOk; + let node_id = self.tcx().hir.hir_to_node_id(hir::HirId { + owner: self.tcx().closure_base_def_id(self.bccx.owner_def_id).index, + local_id: expr_id + }); self.each_in_scope_loan_affecting_path( - region::CodeExtent::Misc(expr_id), use_path, |loan| { + region::CodeExtent::Misc(node_id), use_path, |loan| { if !compatible_borrow_kinds(loan.kind, borrow_kind) { ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span); false @@ -725,11 +733,11 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { /// Reports an error if `expr` (which should be a path) /// is using a moved/uninitialized value fn check_if_path_is_moved(&self, - id: ast::NodeId, + id: hir::ItemLocalId, span: Span, use_kind: MovedValueUseKind, lp: &Rc>) { - debug!("check_if_path_is_moved(id={}, use_kind={:?}, lp={:?})", + debug!("check_if_path_is_moved(id={:?}, use_kind={:?}, lp={:?})", id, use_kind, lp); // FIXME (22079): if you find yourself tempted to cut and paste @@ -772,7 +780,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { /// (*p).x = 22; // not ok, p is uninitialized, can't deref /// ``` fn check_if_assigned_path_is_moved(&self, - id: ast::NodeId, + id: hir::ItemLocalId, span: Span, use_kind: MovedValueUseKind, lp: &Rc>) @@ -822,14 +830,18 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { } fn check_assignment(&self, - assignment_id: ast::NodeId, + assignment_id: hir::ItemLocalId, assignment_span: Span, assignee_cmt: mc::cmt<'tcx>) { debug!("check_assignment(assignee_cmt={:?})", assignee_cmt); // Check that we don't invalidate any outstanding loans if let Some(loan_path) = opt_loan_path(&assignee_cmt) { - let scope = region::CodeExtent::Misc(assignment_id); + let node_id = self.tcx().hir.hir_to_node_id(hir::HirId { + owner: self.tcx().closure_base_def_id(self.bccx.owner_def_id).index, + local_id: assignment_id + }); + let scope = region::CodeExtent::Misc(node_id); self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| { self.report_illegal_mutation(assignment_span, &loan_path, loan); false diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs index 7878762788905..465457f5ab39a 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs @@ -27,7 +27,7 @@ use rustc::hir::*; use rustc::hir::map::Node::*; struct GatherMoveInfo<'tcx> { - id: ast::NodeId, + id: hir::ItemLocalId, kind: MoveKind, cmt: mc::cmt<'tcx>, span_path_opt: Option> @@ -79,13 +79,14 @@ pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, var_id: ast::NodeId, var_ty: Ty<'tcx>) { let loan_path = Rc::new(LoanPath::new(LpVar(var_id), var_ty)); - move_data.add_move(bccx.tcx, loan_path, var_id, Declared); + let hir_id = bccx.tcx.hir.node_to_hir_id(var_id); + move_data.add_move(bccx.tcx, loan_path, hir_id.local_id, Declared); } pub fn gather_move_from_expr<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, move_error_collector: &mut MoveErrorCollector<'tcx>, - move_expr_id: ast::NodeId, + move_expr_id: hir::ItemLocalId, cmt: mc::cmt<'tcx>, move_reason: euv::MoveReason) { let kind = match move_reason { @@ -118,7 +119,7 @@ pub fn gather_move_from_pat<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, _ => None, }; let move_info = GatherMoveInfo { - id: move_pat.id, + id: move_pat.hir_id.local_id, kind: MovePat, cmt, span_path_opt: pat_span_path_opt, @@ -135,7 +136,7 @@ fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, move_error_collector: &mut MoveErrorCollector<'tcx>, move_info: GatherMoveInfo<'tcx>) { - debug!("gather_move(move_id={}, cmt={:?})", + debug!("gather_move(move_id={:?}, cmt={:?})", move_info.id, move_info.cmt); let potentially_illegal_move = @@ -161,10 +162,10 @@ fn gather_move<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, pub fn gather_assignment<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, move_data: &MoveData<'tcx>, - assignment_id: ast::NodeId, + assignment_id: hir::ItemLocalId, assignment_span: Span, assignee_loan_path: Rc>, - assignee_id: ast::NodeId, + assignee_id: hir::ItemLocalId, mode: euv::MutateMode) { move_data.add_assignment(bccx.tcx, assignee_loan_path, diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index 68bffb90f4da8..e14edc43904ea 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -44,7 +44,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, bccx, all_loans: Vec::new(), item_ub: region::CodeExtent::Misc(body.node_id), - move_data: MoveData::new(), + move_data: MoveData::default(), move_error_collector: move_error::MoveErrorCollector::new(), }; @@ -79,7 +79,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { euv::Move(move_reason) => { gather_moves::gather_move_from_expr( self.bccx, &self.move_data, &mut self.move_error_collector, - consume_id, cmt, move_reason); + self.bccx.tcx.hir.node_to_hir_id(consume_id).local_id, cmt, move_reason); } euv::Copy => { } } @@ -272,8 +272,12 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { self.mark_loan_path_as_mutated(&lp); } gather_moves::gather_assignment(self.bccx, &self.move_data, - assignment_id, assignment_span, - lp, cmt.id, mode); + self.bccx.tcx.hir.node_to_hir_id(assignment_id) + .local_id, + assignment_span, + lp, + self.bccx.tcx.hir.node_to_hir_id(cmt.id).local_id, + mode); } None => { // This can occur with e.g. `*foo() = 5`. In such diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index eca713a98df57..0b62da306db47 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -167,9 +167,11 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc id_range, all_loans.len()); for (loan_idx, loan) in all_loans.iter().enumerate() { - loan_dfcx.add_gen(loan.gen_scope.node_id(), loan_idx); + loan_dfcx.add_gen(this.tcx.hir.node_to_hir_id(loan.gen_scope.node_id()).local_id, + loan_idx); loan_dfcx.add_kill(KillFrom::ScopeEnd, - loan.kill_scope.node_id(), loan_idx); + this.tcx.hir.node_to_hir_id(loan.kill_scope.node_id()).local_id, + loan_idx); } loan_dfcx.add_kills_from_flow_exits(cfg); loan_dfcx.propagate(cfg, this.body); @@ -640,19 +642,22 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { // Get type of value and span where it was previously // moved. + let node_id = self.tcx.hir.hir_to_node_id(hir::HirId { + owner: self.tcx.closure_base_def_id(self.owner_def_id).index, + local_id: the_move.id + }); let (move_span, move_note) = match the_move.kind { move_data::Declared => { unreachable!(); } move_data::MoveExpr | - move_data::MovePat => - (self.tcx.hir.span(the_move.id), ""), + move_data::MovePat => (self.tcx.hir.span(node_id), ""), move_data::Captured => - (match self.tcx.hir.expect_expr(the_move.id).node { + (match self.tcx.hir.expect_expr(node_id).node { hir::ExprClosure(.., fn_decl_span, _) => fn_decl_span, - ref r => bug!("Captured({}) maps to non-closure: {:?}", + ref r => bug!("Captured({:?}) maps to non-closure: {:?}", the_move.id, r), }, " (into closure)"), }; diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 217bd6e6ca1ca..79a4a4f9f4d5b 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -23,16 +23,16 @@ use rustc::middle::expr_use_visitor as euv; use rustc::middle::expr_use_visitor::MutateMode; use rustc::middle::mem_categorization as mc; use rustc::ty::{self, TyCtxt}; -use rustc::util::nodemap::{FxHashMap, NodeSet}; +use rustc::util::nodemap::{FxHashMap, FxHashSet}; use std::cell::RefCell; use std::rc::Rc; use std::usize; -use syntax::ast; use syntax_pos::Span; use rustc::hir; use rustc::hir::intravisit::IdRange; +#[derive(Default)] pub struct MoveData<'tcx> { /// Move paths. See section "Move paths" in `README.md`. pub paths: RefCell>>, @@ -54,7 +54,7 @@ pub struct MoveData<'tcx> { pub path_assignments: RefCell>, /// Assignments to a variable or path, like `x = foo`, but not `x += foo`. - pub assignee_ids: RefCell, + pub assignee_ids: RefCell>, } pub struct FlowedMoveData<'a, 'tcx: 'a> { @@ -133,7 +133,7 @@ pub struct Move { pub path: MovePathIndex, /// id of node that is doing the move. - pub id: ast::NodeId, + pub id: hir::ItemLocalId, /// Kind of move, for error messages. pub kind: MoveKind, @@ -148,13 +148,13 @@ pub struct Assignment { pub path: MovePathIndex, /// id where assignment occurs - pub id: ast::NodeId, + pub id: hir::ItemLocalId, /// span of node where assignment occurs pub span: Span, /// id for l-value expression on lhs of assignment - pub assignee_id: ast::NodeId, + pub assignee_id: hir::ItemLocalId, } #[derive(Clone, Copy)] @@ -189,17 +189,6 @@ fn loan_path_is_precise(loan_path: &LoanPath) -> bool { } impl<'a, 'tcx> MoveData<'tcx> { - pub fn new() -> MoveData<'tcx> { - MoveData { - paths: RefCell::new(Vec::new()), - path_map: RefCell::new(FxHashMap()), - moves: RefCell::new(Vec::new()), - path_assignments: RefCell::new(Vec::new()), - var_assignments: RefCell::new(Vec::new()), - assignee_ids: RefCell::new(NodeSet()), - } - } - /// return true if there are no trackable assignments or moves /// in this move data - that means that there is nothing that /// could cause a borrow error. @@ -345,7 +334,7 @@ impl<'a, 'tcx> MoveData<'tcx> { /// Adds a new move entry for a move of `lp` that occurs at location `id` with kind `kind`. pub fn add_move(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, orig_lp: Rc>, - id: ast::NodeId, + id: hir::ItemLocalId, kind: MoveKind) { // Moving one union field automatically moves all its fields. Also move siblings of // all parent union fields, moves do not propagate upwards automatically. @@ -373,9 +362,9 @@ impl<'a, 'tcx> MoveData<'tcx> { fn add_move_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, lp: Rc>, - id: ast::NodeId, + id: hir::ItemLocalId, kind: MoveKind) { - debug!("add_move(lp={:?}, id={}, kind={:?})", + debug!("add_move(lp={:?}, id={:?}, kind={:?})", lp, id, kind); @@ -398,9 +387,9 @@ impl<'a, 'tcx> MoveData<'tcx> { /// `span`. pub fn add_assignment(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, lp: Rc>, - assign_id: ast::NodeId, + assign_id: hir::ItemLocalId, span: Span, - assignee_id: ast::NodeId, + assignee_id: hir::ItemLocalId, mode: euv::MutateMode) { // Assigning to one union field automatically assigns to all its fields. if let LpExtend(ref base_lp, mutbl, LpInterior(opt_variant_id, interior)) = lp.kind { @@ -429,11 +418,11 @@ impl<'a, 'tcx> MoveData<'tcx> { fn add_assignment_helper(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, lp: Rc>, - assign_id: ast::NodeId, + assign_id: hir::ItemLocalId, span: Span, - assignee_id: ast::NodeId, + assignee_id: hir::ItemLocalId, mode: euv::MutateMode) { - debug!("add_assignment(lp={:?}, assign_id={}, assignee_id={}", + debug!("add_assignment(lp={:?}, assign_id={:?}, assignee_id={:?}", lp, assign_id, assignee_id); let path_index = self.move_path(tcx, lp.clone()); @@ -496,7 +485,8 @@ impl<'a, 'tcx> MoveData<'tcx> { LpVar(..) | LpUpvar(..) | LpDowncast(..) => { let kill_scope = path.loan_path.kill_scope(bccx); let path = *self.path_map.borrow().get(&path.loan_path).unwrap(); - self.kill_moves(path, kill_scope.node_id(), + self.kill_moves(path, + bccx.tcx.hir.node_to_hir_id(kill_scope.node_id()).local_id, KillFrom::ScopeEnd, dfcx_moves); } LpExtend(..) => {} @@ -511,7 +501,8 @@ impl<'a, 'tcx> MoveData<'tcx> { LpVar(..) | LpUpvar(..) | LpDowncast(..) => { let kill_scope = lp.kill_scope(bccx); dfcx_assign.add_kill(KillFrom::ScopeEnd, - kill_scope.node_id(), + bccx.tcx.hir.node_to_hir_id(kill_scope.node_id()) + .local_id, assignment_index); } LpExtend(..) => { @@ -579,7 +570,7 @@ impl<'a, 'tcx> MoveData<'tcx> { fn kill_moves(&self, path: MovePathIndex, - kill_id: ast::NodeId, + kill_id: hir::ItemLocalId, kill_kind: KillFrom, dfcx_moves: &mut MoveDataFlow) { // We can only perform kills for paths that refer to a unique location, @@ -589,7 +580,7 @@ impl<'a, 'tcx> MoveData<'tcx> { let loan_path = self.path_loan_path(path); if loan_path_is_precise(&loan_path) { self.each_applicable_move(path, |move_index| { - debug!("kill_moves add_kill {:?} kill_id={} move_index={}", + debug!("kill_moves add_kill {:?} kill_id={:?} move_index={}", kill_kind, kill_id, move_index.get()); dfcx_moves.add_kill(kill_kind, kill_id, move_index.get()); true @@ -642,7 +633,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { } pub fn kind_of_move_of_path(&self, - id: ast::NodeId, + id: hir::ItemLocalId, loan_path: &Rc>) -> Option { //! Returns the kind of a move of `loan_path` by `id`, if one exists. @@ -667,7 +658,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { /// have occurred on entry to `id` without an intervening assignment. In other words, any moves /// that would invalidate a reference to `loan_path` at location `id`. pub fn each_move_of(&self, - id: ast::NodeId, + id: hir::ItemLocalId, loan_path: &Rc>, mut f: F) -> bool where @@ -724,7 +715,7 @@ impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> { /// Iterates through every assignment to `loan_path` that may have occurred on entry to `id`. /// `loan_path` must be a single variable. pub fn each_assignment_of(&self, - id: ast::NodeId, + id: hir::ItemLocalId, loan_path: &Rc>, mut f: F) -> bool where diff --git a/src/librustc_borrowck/graphviz.rs b/src/librustc_borrowck/graphviz.rs index e3a2bfa392738..22867ba5b55a4 100644 --- a/src/librustc_borrowck/graphviz.rs +++ b/src/librustc_borrowck/graphviz.rs @@ -52,7 +52,7 @@ pub struct DataflowLabeller<'a, 'tcx: 'a> { impl<'a, 'tcx> DataflowLabeller<'a, 'tcx> { fn dataflow_for(&self, e: EntryOrExit, n: &Node<'a>) -> String { let id = n.1.data.id(); - debug!("dataflow_for({:?}, id={}) {:?}", e, id, self.variants); + debug!("dataflow_for({:?}, id={:?}) {:?}", e, id, self.variants); let mut sets = "".to_string(); let mut seen_one = false; for &variant in &self.variants { diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs index 20f2a146b0b15..6a58b7fb75360 100644 --- a/src/librustc_driver/pretty.rs +++ b/src/librustc_driver/pretty.rs @@ -765,7 +765,7 @@ fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec, let cfg = cfg::CFG::new(tcx, &body); let labelled_edges = mode != PpFlowGraphMode::UnlabelledEdges; let lcfg = LabelledCFG { - hir_map: &tcx.hir, + tcx, cfg: &cfg, name: format!("node_{}", code.id()), labelled_edges, diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 3bfe2897de175..0fe30dcabb00d 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -850,23 +850,25 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { } visited.insert(cfg_id); - let node_id = cfg.graph.node_data(idx).id(); - // is this a recursive call? - let self_recursive = if node_id != ast::DUMMY_NODE_ID { - match method { + let local_id = cfg.graph.node_data(idx).id(); + if local_id != hir::DUMMY_ITEM_LOCAL_ID { + let node_id = cx.tcx.hir.hir_to_node_id(hir::HirId { + owner: cx.tcx.closure_base_def_id(cfg.owner_def_id).index, + local_id + }); + let self_recursive = match method { Some(ref method) => expr_refers_to_this_method(cx, method, node_id), None => expr_refers_to_this_fn(cx, id, node_id), + }; + if self_recursive { + self_call_spans.push(cx.tcx.hir.span(node_id)); + // this is a self call, so we shouldn't explore past + // this node in the CFG. + continue; } - } else { - false - }; - if self_recursive { - self_call_spans.push(cx.tcx.hir.span(node_id)); - // this is a self call, so we shouldn't explore past - // this node in the CFG. - continue; } + // add the successors of this node to explore the graph further. for (_, edge) in cfg.graph.outgoing_edges(idx) { let target_idx = edge.target(); From ea6aca7726bd035ae79fc4643f863178c8f26e90 Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Wed, 30 Aug 2017 02:39:06 +0300 Subject: [PATCH 2/3] rustc: take TyCtxt and RegionMaps in CodeMap::span. --- src/librustc/infer/error_reporting/mod.rs | 31 +++-- src/librustc/infer/error_reporting/note.rs | 112 ++++++++++-------- src/librustc/infer/mod.rs | 2 +- src/librustc/middle/region.rs | 48 ++++---- src/librustc/ty/error.rs | 37 +----- src/librustc/ty/structural_impls.rs | 16 +-- src/librustc_borrowck/borrowck/mod.rs | 13 +- src/librustc_mir/build/block.rs | 8 +- src/librustc_mir/build/scope.rs | 3 +- src/librustc_mir/hair/cx/block.rs | 2 - src/librustc_mir/hair/mod.rs | 1 - .../check/generator_interior.rs | 16 +-- .../mismatched_types/closure-mismatch.stderr | 1 - 13 files changed, 120 insertions(+), 170 deletions(-) diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index 4c55c1474a326..d86626c210e14 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -64,7 +64,7 @@ use std::fmt; use hir; use hir::map as hir_map; use hir::def_id::DefId; -use middle::region; +use middle::region::{self, RegionMaps}; use traits::{ObligationCause, ObligationCauseCode}; use ty::{self, Region, TyCtxt, TypeFoldable}; use ty::error::TypeError; @@ -83,6 +83,7 @@ mod anon_anon_conflict; impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { pub fn note_and_explain_region(self, + region_maps: &RegionMaps, err: &mut DiagnosticBuilder, prefix: &str, region: ty::Region<'tcx>, @@ -130,13 +131,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { format!("{}unknown scope: {:?}{}. Please report a bug.", prefix, scope, suffix) }; - let span = match scope.span(&self.hir) { - Some(s) => s, - None => { - err.note(&unknown_scope()); - return; - } - }; + let span = scope.span(self, region_maps); let tag = match self.hir.find(scope.node_id()) { Some(hir_map::NodeBlock(_)) => "block", Some(hir_map::NodeExpr(expr)) => match expr.node { @@ -260,8 +255,9 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { - - pub fn report_region_errors(&self, errors: &Vec>) { + pub fn report_region_errors(&self, + region_maps: &RegionMaps, + errors: &Vec>) { debug!("report_region_errors(): {} errors to start", errors.len()); // try to pre-process the errors, which will group some of them @@ -285,16 +281,16 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // the error. If all of these fails, we fall back to a rather // general bit of code that displays the error information ConcreteFailure(origin, sub, sup) => { - - self.report_concrete_failure(origin, sub, sup).emit(); + self.report_concrete_failure(region_maps, origin, sub, sup).emit(); } GenericBoundFailure(kind, param_ty, sub) => { - self.report_generic_bound_failure(kind, param_ty, sub); + self.report_generic_bound_failure(region_maps, kind, param_ty, sub); } SubSupConflict(var_origin, sub_origin, sub_r, sup_origin, sup_r) => { - self.report_sub_sup_conflict(var_origin, + self.report_sub_sup_conflict(region_maps, + var_origin, sub_origin, sub_r, sup_origin, @@ -773,6 +769,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } fn report_generic_bound_failure(&self, + region_maps: &RegionMaps, origin: SubregionOrigin<'tcx>, bound_kind: GenericKind<'tcx>, sub: Region<'tcx>) @@ -840,6 +837,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { err.help(&format!("consider adding an explicit lifetime bound for `{}`", bound_kind)); self.tcx.note_and_explain_region( + region_maps, &mut err, &format!("{} must be valid for ", labeled_user_string), sub, @@ -853,6 +851,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } fn report_sub_sup_conflict(&self, + region_maps: &RegionMaps, var_origin: RegionVariableOrigin, sub_origin: SubregionOrigin<'tcx>, sub_region: Region<'tcx>, @@ -860,14 +859,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { sup_region: Region<'tcx>) { let mut err = self.report_inference_failure(var_origin); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "first, the lifetime cannot outlive ", sup_region, "..."); self.note_region_origin(&mut err, &sup_origin); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "but, the lifetime must be valid for ", sub_region, "..."); diff --git a/src/librustc/infer/error_reporting/note.rs b/src/librustc/infer/error_reporting/note.rs index 87047d0df144c..3e78cce80f594 100644 --- a/src/librustc/infer/error_reporting/note.rs +++ b/src/librustc/infer/error_reporting/note.rs @@ -9,6 +9,7 @@ // except according to those terms. use infer::{self, InferCtxt, SubregionOrigin}; +use middle::region::RegionMaps; use ty::{self, Region}; use ty::error::TypeError; use errors::DiagnosticBuilder; @@ -144,6 +145,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { } pub(super) fn report_concrete_failure(&self, + region_maps: &RegionMaps, origin: SubregionOrigin<'tcx>, sub: Region<'tcx>, sup: Region<'tcx>) @@ -151,7 +153,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { match origin { infer::Subtype(trace) => { let terr = TypeError::RegionsDoesNotOutlive(sup, sub); - self.report_and_explain_type_error(trace, &terr) + let mut err = self.report_and_explain_type_error(trace, &terr); + self.tcx.note_and_explain_region(region_maps, &mut err, "", sup, "..."); + self.tcx.note_and_explain_region(region_maps, &mut err, + "...does not necessarily outlive ", sub, ""); + err } infer::Reborrow(span) => { let mut err = struct_span_err!(self.tcx.sess, @@ -159,11 +165,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0312, "lifetime of reference outlives lifetime of \ borrowed content..."); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "...the reference is valid for ", sub, "..."); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "...but the borrowed content is only valid for ", sup, ""); @@ -177,27 +183,27 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { of captured variable `{}`...", self.tcx .local_var_name_str_def_index(upvar_id.var_id)); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "...the borrowed pointer is valid for ", sub, "..."); - self.tcx - .note_and_explain_region( - &mut err, - &format!("...but `{}` is only valid for ", - self.tcx.local_var_name_str_def_index(upvar_id.var_id)), - sup, - ""); + self.tcx.note_and_explain_region( + region_maps, + &mut err, + &format!("...but `{}` is only valid for ", + self.tcx.local_var_name_str_def_index(upvar_id.var_id)), + sup, + ""); err } infer::InfStackClosure(span) => { let mut err = struct_span_err!(self.tcx.sess, span, E0314, "closure outlives stack frame"); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "...the closure must be valid for ", sub, "..."); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "...but the closure's stack frame is only valid \ for ", sup, @@ -209,8 +215,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span, E0315, "cannot invoke closure outside of its lifetime"); - self.tcx - .note_and_explain_region(&mut err, "the closure is only valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the closure is only valid for ", sup, ""); err } infer::DerefPointer(span) => { @@ -218,8 +224,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span, E0473, "dereference of reference outside its lifetime"); - self.tcx - .note_and_explain_region(&mut err, "the reference is only valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the reference is only valid for ", sup, ""); err } infer::FreeVariable(span, id) => { @@ -229,9 +235,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "captured variable `{}` does not outlive the \ enclosing closure", self.tcx.local_var_name_str(id)); - self.tcx - .note_and_explain_region(&mut err, "captured variable is valid for ", sup, ""); - self.tcx.note_and_explain_region(&mut err, "closure is valid for ", sub, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "captured variable is valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "closure is valid for ", sub, ""); err } infer::IndexSlice(span) => { @@ -239,7 +246,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span, E0475, "index of slice outside its lifetime"); - self.tcx.note_and_explain_region(&mut err, "the slice is only valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the slice is only valid for ", sup, ""); err } infer::RelateObjectBound(span) => { @@ -248,8 +256,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0476, "lifetime of the source pointer does not outlive \ lifetime bound of the object type"); - self.tcx.note_and_explain_region(&mut err, "object type is valid for ", sub, ""); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, + "object type is valid for ", sub, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, "source pointer is only valid for ", sup, ""); @@ -264,10 +273,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { self.ty_to_string(ty)); match *sub { ty::ReStatic => { - self.tcx.note_and_explain_region(&mut err, "type must satisfy ", sub, "") + self.tcx.note_and_explain_region(region_maps, &mut err, + "type must satisfy ", sub, "") } _ => { - self.tcx.note_and_explain_region(&mut err, "type must outlive ", sub, "") + self.tcx.note_and_explain_region(region_maps, &mut err, + "type must outlive ", sub, "") } } err @@ -275,11 +286,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { infer::RelateRegionParamBound(span) => { let mut err = struct_span_err!(self.tcx.sess, span, E0478, "lifetime bound not satisfied"); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "lifetime parameter instantiated with ", sup, ""); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "but lifetime parameter must outlive ", sub, ""); @@ -292,7 +303,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "the type `{}` (provided as the value of a type \ parameter) is not valid at this point", self.ty_to_string(ty)); - self.tcx.note_and_explain_region(&mut err, "type must outlive ", sub, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "type must outlive ", sub, ""); err } infer::CallRcvr(span) => { @@ -301,8 +313,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0480, "lifetime of method receiver does not outlive the \ method call"); - self.tcx - .note_and_explain_region(&mut err, "the receiver is only valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the receiver is only valid for ", sup, ""); err } infer::CallArg(span) => { @@ -311,7 +323,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0481, "lifetime of function argument does not outlive \ the function call"); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "the function argument is only valid for ", sup, ""); @@ -323,7 +335,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0482, "lifetime of return value does not outlive the \ function call"); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "the return value is only valid for ", sup, ""); @@ -335,8 +347,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0483, "lifetime of operand does not outlive the \ operation"); - self.tcx - .note_and_explain_region(&mut err, "the operand is only valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the operand is only valid for ", sup, ""); err } infer::AddrOf(span) => { @@ -344,8 +356,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span, E0484, "reference is not valid at the time of borrow"); - self.tcx - .note_and_explain_region(&mut err, "the borrow is only valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the borrow is only valid for ", sup, ""); err } infer::AutoBorrow(span) => { @@ -354,7 +366,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0485, "automatically reference is not valid at the time \ of borrow"); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, "the automatic borrow is only valid for ", sup, ""); @@ -367,7 +379,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "type of expression contains references that are \ not valid during the expression: `{}`", self.ty_to_string(t)); - self.tcx.note_and_explain_region(&mut err, "type is only valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "type is only valid for ", sup, ""); err } infer::SafeDestructor(span) => { @@ -377,8 +390,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "unsafe use of destructor: destructor might be \ called while references are dead"); // FIXME (22171): terms "super/subregion" are suboptimal - self.tcx.note_and_explain_region(&mut err, "superregion: ", sup, ""); - self.tcx.note_and_explain_region(&mut err, "subregion: ", sub, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, "superregion: ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, "subregion: ", sub, ""); err } infer::BindingTypeIsNotValidAtDecl(span) => { @@ -387,8 +400,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0488, "lifetime of variable does not enclose its \ declaration"); - self.tcx - .note_and_explain_region(&mut err, "the variable is only valid for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the variable is only valid for ", sup, ""); err } infer::ParameterInScope(_, span) => { @@ -396,8 +409,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { span, E0489, "type/lifetime parameter not in scope here"); - self.tcx - .note_and_explain_region(&mut err, "the parameter is only valid for ", sub, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the parameter is only valid for ", sub, ""); err } infer::DataBorrowed(ty, span) => { @@ -406,8 +419,10 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { E0490, "a value of type `{}` is borrowed for too long", self.ty_to_string(ty)); - self.tcx.note_and_explain_region(&mut err, "the type is valid for ", sub, ""); - self.tcx.note_and_explain_region(&mut err, "but the borrow lasts for ", sup, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "the type is valid for ", sub, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, + "but the borrow lasts for ", sup, ""); err } infer::ReferenceOutlivesReferent(ty, span) => { @@ -417,8 +432,9 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { "in type `{}`, reference has a longer lifetime \ than the data it references", self.ty_to_string(ty)); - self.tcx.note_and_explain_region(&mut err, "the pointer is valid for ", sub, ""); - self.tcx.note_and_explain_region(&mut err, + self.tcx.note_and_explain_region(region_maps, &mut err, + "the pointer is valid for ", sub, ""); + self.tcx.note_and_explain_region(region_maps, &mut err, "but the referenced data is only valid for ", sup, ""); diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs index 27c6a4c5cf291..21af92a25e684 100644 --- a/src/librustc/infer/mod.rs +++ b/src/librustc/infer/mod.rs @@ -1084,7 +1084,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> { // this infcx was in use. This is totally hokey but // otherwise we have a hard time separating legit region // errors from silly ones. - self.report_region_errors(&errors); // see error_reporting module + self.report_region_errors(region_map, &errors); // see error_reporting module } } diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 8b01d5045c6b0..10a21a582f554 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -16,7 +16,6 @@ //! Most of the documentation on regions can be found in //! `middle/infer/region_inference/README.md` -use hir::map as hir_map; use util::nodemap::{FxHashMap, NodeMap, NodeSet}; use ty; @@ -161,34 +160,31 @@ impl CodeExtent { /// Returns the span of this CodeExtent. Note that in general the /// returned span may not correspond to the span of any node id in /// the AST. - pub fn span(&self, hir_map: &hir_map::Map) -> Option { - match hir_map.find(self.node_id()) { - Some(hir_map::NodeBlock(ref blk)) => { - match *self { - CodeExtent::CallSiteScope(_) | - CodeExtent::ParameterScope(_) | - CodeExtent::Misc(_) | - CodeExtent::DestructionScope(_) => Some(blk.span), - - CodeExtent::Remainder(r) => { - assert_eq!(r.block, blk.id); - // Want span for extent starting after the - // indexed statement and ending at end of - // `blk`; reuse span of `blk` and shift `lo` - // forward to end of indexed statement. - // - // (This is the special case aluded to in the - // doc-comment for this method) - let stmt_span = blk.stmts[r.first_statement_index as usize].span; - Some(Span::new(stmt_span.hi(), blk.span.hi(), stmt_span.ctxt())) - } + pub fn span(&self, tcx: TyCtxt, region_maps: &RegionMaps) -> Span { + let root_node = region_maps.root_body.unwrap().node_id; + assert_eq!(DefId::local(tcx.hir.node_to_hir_id(self.node_id()).owner), + DefId::local(tcx.hir.node_to_hir_id(root_node).owner)); + let span = tcx.hir.span(self.node_id()); + if let CodeExtent::Remainder(r) = *self { + if let hir::map::NodeBlock(ref blk) = tcx.hir.get(r.block) { + // Want span for extent starting after the + // indexed statement and ending at end of + // `blk`; reuse span of `blk` and shift `lo` + // forward to end of indexed statement. + // + // (This is the special case aluded to in the + // doc-comment for this method) + + let stmt_span = blk.stmts[r.first_statement_index as usize].span; + + // To avoid issues with macro-generated spans, the span + // of the statement must be nested in that of the block. + if span.lo() <= stmt_span.lo() && stmt_span.lo() <= span.hi() { + return Span::new(stmt_span.lo(), span.hi(), span.ctxt()); } } - Some(hir_map::NodeExpr(ref expr)) => Some(expr.span), - Some(hir_map::NodeStmt(ref stmt)) => Some(stmt.span), - Some(hir_map::NodeItem(ref item)) => Some(item.span), - Some(_) | None => None, } + span } } diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs index 802994ae0948a..49d7f40000f07 100644 --- a/src/librustc/ty/error.rs +++ b/src/librustc/ty/error.rs @@ -36,11 +36,11 @@ pub enum TypeError<'tcx> { TupleSize(ExpectedFound), FixedArraySize(ExpectedFound), ArgCount, + RegionsDoesNotOutlive(Region<'tcx>, Region<'tcx>), - RegionsNotSame(Region<'tcx>, Region<'tcx>), - RegionsNoOverlap(Region<'tcx>, Region<'tcx>), RegionsInsufficientlyPolymorphic(BoundRegion, Region<'tcx>), RegionsOverlyPolymorphic(BoundRegion, Region<'tcx>), + Sorts(ExpectedFound>), IntMismatch(ExpectedFound), FloatMismatch(ExpectedFound), @@ -110,12 +110,6 @@ impl<'tcx> fmt::Display for TypeError<'tcx> { RegionsDoesNotOutlive(..) => { write!(f, "lifetime mismatch") } - RegionsNotSame(..) => { - write!(f, "lifetimes are not the same") - } - RegionsNoOverlap(..) => { - write!(f, "lifetimes do not intersect") - } RegionsInsufficientlyPolymorphic(br, _) => { write!(f, "expected bound lifetime parameter{}{}, found concrete lifetime", @@ -243,33 +237,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { use self::TypeError::*; match err.clone() { - RegionsDoesNotOutlive(subregion, superregion) => { - self.note_and_explain_region(db, "", subregion, "..."); - self.note_and_explain_region(db, "...does not necessarily outlive ", - superregion, ""); - } - RegionsNotSame(region1, region2) => { - self.note_and_explain_region(db, "", region1, "..."); - self.note_and_explain_region(db, "...is not the same lifetime as ", - region2, ""); - } - RegionsNoOverlap(region1, region2) => { - self.note_and_explain_region(db, "", region1, "..."); - self.note_and_explain_region(db, "...does not overlap ", - region2, ""); - } - RegionsInsufficientlyPolymorphic(_, conc_region) => { - self.note_and_explain_region(db, "concrete lifetime that was found is ", - conc_region, ""); - } - RegionsOverlyPolymorphic(_, &ty::ReVar(_)) => { - // don't bother to print out the message below for - // inference variables, it's not very illuminating. - } - RegionsOverlyPolymorphic(_, conc_region) => { - self.note_and_explain_region(db, "expected concrete lifetime is ", - conc_region, ""); - } Sorts(values) => { let expected_str = values.expected.sort_string(self); let found_str = values.found.sort_string(self); diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs index 6353c5e0dd0e0..ae05568ab4148 100644 --- a/src/librustc/ty/structural_impls.rs +++ b/src/librustc/ty/structural_impls.rs @@ -371,12 +371,6 @@ impl<'a, 'tcx> Lift<'tcx> for ty::error::TypeError<'a> { RegionsDoesNotOutlive(a, b) => { return tcx.lift(&(a, b)).map(|(a, b)| RegionsDoesNotOutlive(a, b)) } - RegionsNotSame(a, b) => { - return tcx.lift(&(a, b)).map(|(a, b)| RegionsNotSame(a, b)) - } - RegionsNoOverlap(a, b) => { - return tcx.lift(&(a, b)).map(|(a, b)| RegionsNoOverlap(a, b)) - } RegionsInsufficientlyPolymorphic(a, b) => { return tcx.lift(&b).map(|b| RegionsInsufficientlyPolymorphic(a, b)) } @@ -1057,12 +1051,6 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> { RegionsDoesNotOutlive(a, b) => { RegionsDoesNotOutlive(a.fold_with(folder), b.fold_with(folder)) }, - RegionsNotSame(a, b) => { - RegionsNotSame(a.fold_with(folder), b.fold_with(folder)) - }, - RegionsNoOverlap(a, b) => { - RegionsNoOverlap(a.fold_with(folder), b.fold_with(folder)) - }, RegionsInsufficientlyPolymorphic(a, b) => { RegionsInsufficientlyPolymorphic(a, b.fold_with(folder)) }, @@ -1088,9 +1076,7 @@ impl<'tcx> TypeFoldable<'tcx> for ty::error::TypeError<'tcx> { match *self { UnsafetyMismatch(x) => x.visit_with(visitor), AbiMismatch(x) => x.visit_with(visitor), - RegionsDoesNotOutlive(a, b) | - RegionsNotSame(a, b) | - RegionsNoOverlap(a, b) => { + RegionsDoesNotOutlive(a, b) => { a.visit_with(visitor) || b.visit_with(visitor) }, RegionsInsufficientlyPolymorphic(_, b) | diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index 0b62da306db47..e4384935e3733 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -943,6 +943,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } None => { self.tcx.note_and_explain_region( + &self.region_maps, &mut db, "borrowed value must be valid for ", sub_scope, @@ -955,6 +956,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } None => { self.tcx.note_and_explain_region( + &self.region_maps, &mut db, "...but borrowed value is only valid for ", super_scope, @@ -984,12 +986,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { None => self.cmt_to_string(&err.cmt), }; self.tcx.note_and_explain_region( + &self.region_maps, &mut db, &format!("{} would have to be valid for ", descr), loan_scope, "..."); self.tcx.note_and_explain_region( + &self.region_maps, &mut db, &format!("...but {} is only valid for ", descr), ptr_scope, @@ -1245,14 +1249,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { fn region_end_span(&self, region: ty::Region<'tcx>) -> Option { match *region { ty::ReScope(scope) => { - match scope.span(&self.tcx.hir) { - Some(s) => { - Some(s.end_point()) - } - None => { - None - } - } + Some(scope.span(self.tcx, &self.region_maps).end_point()) } _ => None } diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index 4583d80b83ddc..5c0388a020c76 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -71,7 +71,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let outer_visibility_scope = this.visibility_scope; let source_info = this.source_info(span); for stmt in stmts { - let Stmt { span, kind, opt_destruction_extent } = this.hir.mirror(stmt); + let Stmt { kind, opt_destruction_extent } = this.hir.mirror(stmt); match kind { StmtKind::Expr { scope, expr } => { unpack!(block = this.in_opt_scope( @@ -83,15 +83,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { })); } StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => { - let tcx = this.hir.tcx(); - // Enter the remainder scope, i.e. the bindings' destruction scope. this.push_scope((remainder_scope, source_info)); let_extent_stack.push(remainder_scope); // Declare the bindings, which may create a visibility scope. - let remainder_span = remainder_scope.span(&tcx.hir); - let remainder_span = remainder_span.unwrap_or(span); + let remainder_span = remainder_scope.span(this.hir.tcx(), + &this.hir.region_maps); let scope = this.declare_bindings(None, remainder_span, &pattern); // Evaluate the initializer, if present. diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index 90f9c1c0d5f56..2471d8c2c56f7 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -633,8 +633,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { if let DropKind::Value { .. } = drop_kind { scope.needs_cleanup = true; } - let tcx = self.hir.tcx(); - let extent_span = extent.span(&tcx.hir).unwrap(); + let extent_span = extent.span(self.hir.tcx(), &self.hir.region_maps); // Attribute scope exit drops to scope's closing brace let scope_end = extent_span.with_lo(extent_span.hi()); scope.drops.push(DropData { diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 61d128fc84782..d38c72c37e80f 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -45,7 +45,6 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { result.push(StmtRef::Mirror(Box::new(Stmt { - span: stmt.span, kind: StmtKind::Expr { scope: CodeExtent::Misc(id), expr: expr.to_ref(), @@ -69,7 +68,6 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, cx.tables(), &local.pat); result.push(StmtRef::Mirror(Box::new(Stmt { - span: stmt.span, kind: StmtKind::Let { remainder_scope: remainder_extent, init_scope: CodeExtent::Misc(id), diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 9bd5df16a14e9..58051aaecdaab 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -46,7 +46,6 @@ pub enum StmtRef<'tcx> { #[derive(Clone, Debug)] pub struct Stmt<'tcx> { - pub span: Span, pub kind: StmtKind<'tcx>, pub opt_destruction_extent: Option, } diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index e9d400c64393b..46948b687d26d 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -13,7 +13,6 @@ //! is calculated in `rustc_mir::transform::generator` and may be a subset of the //! types computed here. -use log; use rustc::hir::def_id::DefId; use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::{self, Body, Pat, PatKind, Expr}; @@ -36,18 +35,15 @@ impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> { fn record(&mut self, ty: Ty<'tcx>, scope: Option, expr: Option<&'tcx Expr>) { use syntax_pos::DUMMY_SP; - let live_across_yield = scope.map(|s| { - self.fcx.tcx.yield_in_extent(s, &mut self.cache).is_some() - }).unwrap_or(true); + let live_across_yield = scope.map_or(Some(DUMMY_SP), |s| { + self.fcx.tcx.yield_in_extent(s, &mut self.cache) + }); - if live_across_yield { + if let Some(span) = live_across_yield { let ty = self.fcx.resolve_type_vars_if_possible(&ty); - if log_enabled!(log::LogLevel::Debug) { - let span = scope.map(|s| s.span(&self.fcx.tcx.hir).unwrap_or(DUMMY_SP)); - debug!("type in expr = {:?}, scope = {:?}, type = {:?}, span = {:?}", - expr, scope, ty, span); - } + debug!("type in expr = {:?}, scope = {:?}, type = {:?}, span = {:?}", + expr, scope, ty, span); // Map the type to the number of types added before it let entries = self.types.len(); diff --git a/src/test/ui/mismatched_types/closure-mismatch.stderr b/src/test/ui/mismatched_types/closure-mismatch.stderr index b7479f15b1812..d928a6a0a8e64 100644 --- a/src/test/ui/mismatched_types/closure-mismatch.stderr +++ b/src/test/ui/mismatched_types/closure-mismatch.stderr @@ -4,7 +4,6 @@ error[E0271]: type mismatch resolving `for<'r> <[closure@$DIR/closure-mismatch.r 18 | baz(|_| ()); | ^^^ expected bound lifetime parameter, found concrete lifetime | - = note: concrete lifetime that was found is lifetime '_#0r = note: required because of the requirements on the impl of `Foo` for `[closure@$DIR/closure-mismatch.rs:18:9: 18:15]` = note: required by `baz` From e4996ec49c832610f3044f49437b16527f2a726f Mon Sep 17 00:00:00 2001 From: Eduard-Mihai Burtescu Date: Tue, 29 Aug 2017 19:24:49 +0300 Subject: [PATCH 3/3] rustc: use hir::ItemLocalId instead of ast::NodeId in CodeExtent. --- src/librustc/cfg/construct.rs | 10 +- src/librustc/cfg/graphviz.rs | 3 +- src/librustc/infer/error_reporting/mod.rs | 2 +- src/librustc/middle/expr_use_visitor.rs | 12 +- src/librustc/middle/mem_categorization.rs | 5 +- src/librustc/middle/region.rs | 336 ++++++++---------- src/librustc/traits/mod.rs | 2 +- src/librustc/ty/mod.rs | 5 - src/librustc/util/ppaux.rs | 19 +- src/librustc_borrowck/borrowck/check_loans.rs | 16 +- .../borrowck/gather_loans/lifetime.rs | 3 +- .../borrowck/gather_loans/mod.rs | 11 +- src/librustc_borrowck/borrowck/mod.rs | 42 +-- src/librustc_borrowck/borrowck/move_data.rs | 6 +- src/librustc_driver/test.rs | 30 +- src/librustc_lint/builtin.rs | 2 +- src/librustc_mir/build/matches/mod.rs | 3 +- src/librustc_mir/build/mod.rs | 4 +- src/librustc_mir/hair/cx/block.rs | 24 +- src/librustc_mir/hair/cx/expr.rs | 22 +- src/librustc_typeck/check/compare_method.rs | 2 +- src/librustc_typeck/check/dropck.rs | 2 +- .../check/generator_interior.rs | 10 +- src/librustc_typeck/check/mod.rs | 5 +- src/librustc_typeck/check/regionck.rs | 18 +- src/librustc_typeck/coherence/builtin.rs | 2 +- src/test/mir-opt/end_region_1.rs | 6 +- src/test/mir-opt/end_region_2.rs | 14 +- src/test/mir-opt/end_region_3.rs | 14 +- src/test/mir-opt/end_region_4.rs | 14 +- src/test/mir-opt/end_region_5.rs | 14 +- src/test/mir-opt/end_region_6.rs | 18 +- src/test/mir-opt/end_region_7.rs | 6 +- src/test/mir-opt/end_region_8.rs | 16 +- src/test/mir-opt/validate_1.rs | 18 +- src/test/mir-opt/validate_3.rs | 14 +- src/test/mir-opt/validate_5.rs | 6 +- 37 files changed, 333 insertions(+), 403 deletions(-) diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs index 1448fb7c528c6..8908bcb886559 100644 --- a/src/librustc/cfg/construct.rs +++ b/src/librustc/cfg/construct.rs @@ -582,10 +582,10 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { target_scope: CodeExtent, to_index: CFGIndex) { let mut data = CFGEdgeData { exiting_scopes: vec![] }; - let mut scope = CodeExtent::Misc(from_expr.id); + let mut scope = CodeExtent::Misc(from_expr.hir_id.local_id); let region_maps = self.tcx.region_maps(self.owner_def_id); while scope != target_scope { - data.exiting_scopes.push(self.tcx.hir.node_to_hir_id(scope.node_id()).local_id); + data.exiting_scopes.push(scope.item_local_id()); scope = region_maps.encl_scope(scope); } self.graph.add_edge(from_index, to_index, data); @@ -612,7 +612,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ScopeTarget::Block(block_expr_id) => { for b in &self.breakable_block_scopes { if b.block_expr_id == self.tcx.hir.node_to_hir_id(block_expr_id).local_id { - return (CodeExtent::Misc(block_expr_id), match scope_cf_kind { + let scope_id = self.tcx.hir.node_to_hir_id(block_expr_id).local_id; + return (CodeExtent::Misc(scope_id), match scope_cf_kind { ScopeCfKind::Break => b.break_index, ScopeCfKind::Continue => bug!("can't continue to block"), }); @@ -623,7 +624,8 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> { hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => { for l in &self.loop_scopes { if l.loop_id == self.tcx.hir.node_to_hir_id(loop_id).local_id { - return (CodeExtent::Misc(loop_id), match scope_cf_kind { + let scope_id = self.tcx.hir.node_to_hir_id(loop_id).local_id; + return (CodeExtent::Misc(scope_id), match scope_cf_kind { ScopeCfKind::Break => l.break_index, ScopeCfKind::Continue => l.continue_index, }); diff --git a/src/librustc/cfg/graphviz.rs b/src/librustc/cfg/graphviz.rs index fa034744b62e2..9241240caf043 100644 --- a/src/librustc/cfg/graphviz.rs +++ b/src/librustc/cfg/graphviz.rs @@ -32,8 +32,9 @@ pub struct LabelledCFG<'a, 'tcx: 'a> { impl<'a, 'tcx> LabelledCFG<'a, 'tcx> { fn local_id_to_string(&self, local_id: hir::ItemLocalId) -> String { + assert!(self.cfg.owner_def_id.is_local()); let node_id = self.tcx.hir.hir_to_node_id(hir::HirId { - owner: self.tcx.closure_base_def_id(self.cfg.owner_def_id).index, + owner: self.tcx.hir.def_index_to_hir_id(self.cfg.owner_def_id.index).owner, local_id }); let s = self.tcx.hir.node_to_string(node_id); diff --git a/src/librustc/infer/error_reporting/mod.rs b/src/librustc/infer/error_reporting/mod.rs index d86626c210e14..90d781c6e3664 100644 --- a/src/librustc/infer/error_reporting/mod.rs +++ b/src/librustc/infer/error_reporting/mod.rs @@ -132,7 +132,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { prefix, scope, suffix) }; let span = scope.span(self, region_maps); - let tag = match self.hir.find(scope.node_id()) { + let tag = match self.hir.find(scope.node_id(self, region_maps)) { Some(hir_map::NodeBlock(_)) => "block", Some(hir_map::NodeExpr(expr)) => match expr.node { hir::ExprCall(..) => "call", diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs index e36e1f470eb69..1589ba6027590 100644 --- a/src/librustc/middle/expr_use_visitor.rs +++ b/src/librustc/middle/expr_use_visitor.rs @@ -23,7 +23,7 @@ use hir::def::Def; use hir::def_id::{DefId}; use infer::InferCtxt; use middle::mem_categorization as mc; -use middle::region::RegionMaps; +use middle::region::{CodeExtent, RegionMaps}; use ty::{self, TyCtxt, adjustment}; use hir::{self, PatKind}; @@ -298,7 +298,8 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { for arg in &body.arguments { let arg_ty = return_if_err!(self.mc.node_ty(arg.pat.hir_id)); - let fn_body_scope_r = self.tcx().node_scope_region(body.value.id); + let fn_body_scope_r = + self.tcx().mk_region(ty::ReScope(CodeExtent::Misc(body.value.hir_id.local_id))); let arg_cmt = self.mc.cat_rvalue( arg.id, arg.pat.span, @@ -542,16 +543,17 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { ty::TyError => { } _ => { let def_id = self.mc.tables.type_dependent_defs()[call.hir_id].def_id(); + let call_scope = CodeExtent::Misc(call.hir_id.local_id); match OverloadedCallType::from_method_id(self.tcx(), def_id) { FnMutOverloadedCall => { - let call_scope_r = self.tcx().node_scope_region(call.id); + let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope)); self.borrow_expr(callee, call_scope_r, ty::MutBorrow, ClosureInvocation); } FnOverloadedCall => { - let call_scope_r = self.tcx().node_scope_region(call.id); + let call_scope_r = self.tcx().mk_region(ty::ReScope(call_scope)); self.borrow_expr(callee, call_scope_r, ty::ImmBorrow, @@ -749,7 +751,7 @@ impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> { // Converting from a &T to *T (or &mut T to *mut T) is // treated as borrowing it for the enclosing temporary // scope. - let r = self.tcx().node_scope_region(expr.id); + let r = self.tcx().mk_region(ty::ReScope(CodeExtent::Misc(expr.hir_id.local_id))); self.delegate.borrow(expr.id, expr.span, diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs index 034861131e86e..fdab71ee00441 100644 --- a/src/librustc/middle/mem_categorization.rs +++ b/src/librustc/middle/mem_categorization.rs @@ -861,8 +861,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { /// Returns the lifetime of a temporary created by expr with id `id`. /// This could be `'static` if `id` is part of a constant expression. - pub fn temporary_scope(&self, id: ast::NodeId) -> ty::Region<'tcx> - { + pub fn temporary_scope(&self, id: hir::ItemLocalId) -> ty::Region<'tcx> { let scope = self.region_maps.temporary_scope(id); self.tcx.mk_region(match scope { Some(scope) => ty::ReScope(scope), @@ -890,7 +889,7 @@ impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> { let re = if promotable { self.tcx.types.re_static } else { - self.temporary_scope(id) + self.temporary_scope(self.tcx.hir.node_to_hir_id(id).local_id) }; let ret = self.cat_rvalue(id, span, re, expr_ty); debug!("cat_rvalue_node ret {:?}", ret); diff --git a/src/librustc/middle/region.rs b/src/librustc/middle/region.rs index 10a21a582f554..f58d1a0b41fec 100644 --- a/src/librustc/middle/region.rs +++ b/src/librustc/middle/region.rs @@ -16,15 +16,15 @@ //! Most of the documentation on regions can be found in //! `middle/infer/region_inference/README.md` -use util::nodemap::{FxHashMap, NodeMap, NodeSet}; +use util::nodemap::{FxHashMap, FxHashSet}; use ty; +use std::collections::hash_map::Entry; use std::mem; use std::rc::Rc; use syntax::codemap; use syntax::ast; -use syntax::ast::NodeId; -use syntax_pos::Span; +use syntax_pos::{Span, DUMMY_SP}; use ty::TyCtxt; use ty::maps::Providers; @@ -32,7 +32,6 @@ use hir; use hir::def_id::DefId; use hir::intravisit::{self, Visitor, NestedVisitorMap}; use hir::{Block, Arm, Pat, PatKind, Stmt, Expr, Local}; -use hir::map::Node; use mir::transform::MirSource; /// CodeExtent represents a statically-describable extent that can be @@ -98,18 +97,18 @@ use mir::transform::MirSource; /// generated via deriving here. #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, Debug, Copy, RustcEncodable, RustcDecodable)] pub enum CodeExtent { - Misc(ast::NodeId), + Misc(hir::ItemLocalId), // extent of the call-site for a function or closure (outlives // the parameters as well as the body). - CallSiteScope(hir::BodyId), + CallSiteScope(hir::ItemLocalId), // extent of parameters passed to a function or closure (they // outlive its body) - ParameterScope(hir::BodyId), + ParameterScope(hir::ItemLocalId), // extent of destructors for temporaries of node-id - DestructionScope(ast::NodeId), + DestructionScope(hir::ItemLocalId), // extent of code following a `let id = expr;` binding in a block Remainder(BlockRemainder) @@ -135,25 +134,37 @@ pub enum CodeExtent { #[derive(Clone, PartialEq, PartialOrd, Eq, Ord, Hash, RustcEncodable, RustcDecodable, Debug, Copy)] pub struct BlockRemainder { - pub block: ast::NodeId, + pub block: hir::ItemLocalId, pub first_statement_index: u32, } impl CodeExtent { - /// Returns a node id associated with this scope. + /// Returns a item-local id associated with this scope. /// /// NB: likely to be replaced as API is refined; e.g. pnkfelix /// anticipates `fn entry_node_id` and `fn each_exit_node_id`. - pub fn node_id(&self) -> ast::NodeId { + pub fn item_local_id(&self) -> hir::ItemLocalId { match *self { - CodeExtent::Misc(node_id) => node_id, + CodeExtent::Misc(id) => id, // These cases all return rough approximations to the // precise extent denoted by `self`. CodeExtent::Remainder(br) => br.block, - CodeExtent::DestructionScope(node_id) => node_id, - CodeExtent::CallSiteScope(body_id) | - CodeExtent::ParameterScope(body_id) => body_id.node_id, + CodeExtent::DestructionScope(id) | + CodeExtent::CallSiteScope(id) | + CodeExtent::ParameterScope(id) => id, + } + } + + pub fn node_id(&self, tcx: TyCtxt, region_maps: &RegionMaps) -> ast::NodeId { + match region_maps.root_body { + Some(hir_id) => { + tcx.hir.hir_to_node_id(hir::HirId { + owner: hir_id.owner, + local_id: self.item_local_id() + }) + } + None => ast::DUMMY_NODE_ID } } @@ -161,12 +172,13 @@ impl CodeExtent { /// returned span may not correspond to the span of any node id in /// the AST. pub fn span(&self, tcx: TyCtxt, region_maps: &RegionMaps) -> Span { - let root_node = region_maps.root_body.unwrap().node_id; - assert_eq!(DefId::local(tcx.hir.node_to_hir_id(self.node_id()).owner), - DefId::local(tcx.hir.node_to_hir_id(root_node).owner)); - let span = tcx.hir.span(self.node_id()); + let node_id = self.node_id(tcx, region_maps); + if node_id == ast::DUMMY_NODE_ID { + return DUMMY_SP; + } + let span = tcx.hir.span(node_id); if let CodeExtent::Remainder(r) = *self { - if let hir::map::NodeBlock(ref blk) = tcx.hir.get(r.block) { + if let hir::map::NodeBlock(ref blk) = tcx.hir.get(node_id) { // Want span for extent starting after the // indexed statement and ending at end of // `blk`; reuse span of `blk` and shift `lo` @@ -189,9 +201,10 @@ impl CodeExtent { } /// The region maps encode information about region relationships. +#[derive(Default)] pub struct RegionMaps { /// If not empty, this body is the root of this region hierarchy. - root_body: Option, + root_body: Option, /// The parent of the root body owner, if the latter is an /// an associated const or method, as impls/traits can also @@ -208,10 +221,10 @@ pub struct RegionMaps { /// `var_map` maps from a variable or binding id to the block in /// which that variable is declared. - var_map: NodeMap, + var_map: FxHashMap, /// maps from a node-id to the associated destruction scope (if any) - destruction_scopes: NodeMap, + destruction_scopes: FxHashMap, /// `rvalue_scopes` includes entries for those expressions whose cleanup scope is /// larger than the default. The map goes from the expression id @@ -221,7 +234,7 @@ pub struct RegionMaps { /// block (see `terminating_scopes`). /// In constants, None is used to indicate that certain expressions /// escape into 'static and should have no local cleanup scope. - rvalue_scopes: NodeMap>, + rvalue_scopes: FxHashMap>, /// Encodes the hierarchy of fn bodies. Every fn body (including /// closures) forms its own distinct region hierarchy, rooted in @@ -233,7 +246,11 @@ pub struct RegionMaps { /// closure defined by that fn. See the "Modeling closures" /// section of the README in infer::region_inference for /// more details. - fn_tree: NodeMap, + closure_tree: FxHashMap, + + /// If there are any `yield` nested within a scope, this map + /// stores the `Span` of the first one. + yield_in_scope: FxHashMap, } #[derive(Debug, Copy, Clone)] @@ -244,7 +261,7 @@ pub struct Context { /// arranged into a tree. See the "Modeling closures" section of /// the README in infer::region_inference for more /// details. - root_id: Option, + root_id: Option, /// the scope that contains any new variables declared var_parent: Option, @@ -281,23 +298,11 @@ struct RegionResolutionVisitor<'a, 'tcx: 'a> { /// arbitrary amounts of stack space. Terminating scopes end /// up being contained in a DestructionScope that contains the /// destructor's execution. - terminating_scopes: NodeSet, + terminating_scopes: FxHashSet, } impl<'tcx> RegionMaps { - pub fn new() -> Self { - RegionMaps { - root_body: None, - root_parent: None, - scope_map: FxHashMap(), - destruction_scopes: FxHashMap(), - var_map: NodeMap(), - rvalue_scopes: NodeMap(), - fn_tree: NodeMap(), - } - } - pub fn record_code_extent(&mut self, child: CodeExtent, parent: Option) { @@ -320,46 +325,51 @@ impl<'tcx> RegionMaps { } } - pub fn each_var_scope(&self, mut e:E) where E: FnMut(&ast::NodeId, CodeExtent) { + pub fn each_var_scope(&self, mut e:E) where E: FnMut(&hir::ItemLocalId, CodeExtent) { for (child, &parent) in self.var_map.iter() { e(child, parent) } } - pub fn opt_destruction_extent(&self, n: ast::NodeId) -> Option { + pub fn opt_destruction_extent(&self, n: hir::ItemLocalId) -> Option { self.destruction_scopes.get(&n).cloned() } - /// Records that `sub_fn` is defined within `sup_fn`. These ids + /// Records that `sub_closure` is defined within `sup_closure`. These ids /// should be the id of the block that is the fn body, which is /// also the root of the region hierarchy for that fn. - fn record_fn_parent(&mut self, sub_fn: ast::NodeId, sup_fn: ast::NodeId) { - debug!("record_fn_parent(sub_fn={:?}, sup_fn={:?})", sub_fn, sup_fn); - assert!(sub_fn != sup_fn); - let previous = self.fn_tree.insert(sub_fn, sup_fn); + fn record_closure_parent(&mut self, + sub_closure: hir::ItemLocalId, + sup_closure: hir::ItemLocalId) { + debug!("record_closure_parent(sub_closure={:?}, sup_closure={:?})", + sub_closure, sup_closure); + assert!(sub_closure != sup_closure); + let previous = self.closure_tree.insert(sub_closure, sup_closure); assert!(previous.is_none()); } - fn fn_is_enclosed_by(&self, mut sub_fn: ast::NodeId, sup_fn: ast::NodeId) -> bool { + fn closure_is_enclosed_by(&self, + mut sub_closure: hir::ItemLocalId, + sup_closure: hir::ItemLocalId) -> bool { loop { - if sub_fn == sup_fn { return true; } - match self.fn_tree.get(&sub_fn) { - Some(&s) => { sub_fn = s; } + if sub_closure == sup_closure { return true; } + match self.closure_tree.get(&sub_closure) { + Some(&s) => { sub_closure = s; } None => { return false; } } } } - fn record_var_scope(&mut self, var: ast::NodeId, lifetime: CodeExtent) { + fn record_var_scope(&mut self, var: hir::ItemLocalId, lifetime: CodeExtent) { debug!("record_var_scope(sub={:?}, sup={:?})", var, lifetime); - assert!(var != lifetime.node_id()); + assert!(var != lifetime.item_local_id()); self.var_map.insert(var, lifetime); } - fn record_rvalue_scope(&mut self, var: ast::NodeId, lifetime: Option) { + fn record_rvalue_scope(&mut self, var: hir::ItemLocalId, lifetime: Option) { debug!("record_rvalue_scope(sub={:?}, sup={:?})", var, lifetime); if let Some(lifetime) = lifetime { - assert!(var != lifetime.node_id()); + assert!(var != lifetime.item_local_id()); } self.rvalue_scopes.insert(var, lifetime); } @@ -376,14 +386,14 @@ impl<'tcx> RegionMaps { } /// Returns the lifetime of the local variable `var_id` - pub fn var_scope(&self, var_id: ast::NodeId) -> CodeExtent { + pub fn var_scope(&self, var_id: hir::ItemLocalId) -> CodeExtent { match self.var_map.get(&var_id) { Some(&r) => r, None => { bug!("no enclosing scope for id {:?}", var_id); } } } - pub fn temporary_scope(&self, expr_id: ast::NodeId) -> Option { + pub fn temporary_scope(&self, expr_id: hir::ItemLocalId) -> Option { //! Returns the scope when temp created by expr_id will be cleaned up // check for a designated rvalue scope @@ -413,7 +423,7 @@ impl<'tcx> RegionMaps { return None; } - pub fn var_region(&self, id: ast::NodeId) -> ty::RegionKind { + pub fn var_region(&self, id: hir::ItemLocalId) -> ty::RegionKind { //! Returns the lifetime of the variable `id`. let scope = ty::ReScope(self.var_scope(id)); @@ -493,10 +503,10 @@ impl<'tcx> RegionMaps { return match (a_root_scope, b_root_scope) { (CodeExtent::DestructionScope(a_root_id), CodeExtent::DestructionScope(b_root_id)) => { - if self.fn_is_enclosed_by(a_root_id, b_root_id) { + if self.closure_is_enclosed_by(a_root_id, b_root_id) { // `a` is enclosed by `b`, hence `b` is the ancestor of everything in `a` scope_b - } else if self.fn_is_enclosed_by(b_root_id, a_root_id) { + } else if self.closure_is_enclosed_by(b_root_id, a_root_id) { // `b` is enclosed by `a`, hence `a` is the ancestor of everything in `b` scope_a } else { @@ -561,20 +571,23 @@ impl<'tcx> RegionMaps { let param_owner = tcx.parent_def_id(br.def_id).unwrap(); let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap(); - let body_id = tcx.hir.maybe_body_owned_by(param_owner_id).unwrap_or_else(|| { + let scope = tcx.hir.maybe_body_owned_by(param_owner_id).map(|body_id| { + tcx.hir.body(body_id).value.hir_id.local_id + }).unwrap_or_else(|| { // The lifetime was defined on node that doesn't own a body, // which in practice can only mean a trait or an impl, that // is the parent of a method, and that is enforced below. assert_eq!(Some(param_owner_id), self.root_parent, - "free_extent: {:?} not recognized by the region maps for {:?}", + "free_extent: {:?} not recognized by the region maps for {:?} / {:?}", param_owner, - self.root_body.map(|body| tcx.hir.body_owner_def_id(body))); + self.root_parent.map(|id| tcx.hir.local_def_id(id)), + self.root_body.map(|hir_id| DefId::local(hir_id.owner))); // The trait/impl lifetime is in scope for the method's body. - self.root_body.unwrap() + self.root_body.unwrap().local_id }); - CodeExtent::CallSiteScope(body_id) + CodeExtent::CallSiteScope(scope) } /// Assuming that the provided region was defined within this `RegionMaps`, @@ -593,13 +606,20 @@ impl<'tcx> RegionMaps { assert_eq!(param_owner, fr.scope); let param_owner_id = tcx.hir.as_local_node_id(param_owner).unwrap(); - CodeExtent::CallSiteScope(tcx.hir.body_owned_by(param_owner_id)) + let body_id = tcx.hir.body_owned_by(param_owner_id); + CodeExtent::CallSiteScope(tcx.hir.body(body_id).value.hir_id.local_id) + } + + /// Checks whether the given code extent contains a `yield`. If so, + /// returns `Some(span)` with the span of a yield we found. + pub fn yield_in_scope(&self, scope: CodeExtent) -> Option { + self.yield_in_scope.get(&scope).cloned() } } /// Records the lifetime of a local variable as `cx.var_parent` fn record_var_lifetime(visitor: &mut RegionResolutionVisitor, - var_id: ast::NodeId, + var_id: hir::ItemLocalId, _sp: Span) { match visitor.cx.var_parent { None => { @@ -642,7 +662,7 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: // `other_argument()` has run and also the call to `quux(..)` // itself has returned. - visitor.enter_node_extent_with_dtor(blk.id); + visitor.enter_node_extent_with_dtor(blk.hir_id.local_id); visitor.cx.var_parent = visitor.cx.parent; { @@ -661,7 +681,7 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: // block itself as a parent. visitor.enter_code_extent( CodeExtent::Remainder(BlockRemainder { - block: blk.id, + block: blk.hir_id.local_id, first_statement_index: i as u32 }) ); @@ -676,28 +696,28 @@ fn resolve_block<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, blk: } fn resolve_arm<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, arm: &'tcx hir::Arm) { - visitor.terminating_scopes.insert(arm.body.id); + visitor.terminating_scopes.insert(arm.body.hir_id.local_id); if let Some(ref expr) = arm.guard { - visitor.terminating_scopes.insert(expr.id); + visitor.terminating_scopes.insert(expr.hir_id.local_id); } intravisit::walk_arm(visitor, arm); } fn resolve_pat<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, pat: &'tcx hir::Pat) { - visitor.record_code_extent(CodeExtent::Misc(pat.id)); + visitor.record_code_extent(CodeExtent::Misc(pat.hir_id.local_id)); // If this is a binding then record the lifetime of that binding. if let PatKind::Binding(..) = pat.node { - record_var_lifetime(visitor, pat.id, pat.span); + record_var_lifetime(visitor, pat.hir_id.local_id, pat.span); } intravisit::walk_pat(visitor, pat); } fn resolve_stmt<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, stmt: &'tcx hir::Stmt) { - let stmt_id = stmt.node.id(); + let stmt_id = visitor.tcx.hir.node_to_hir_id(stmt.node.id()).local_id; debug!("resolve_stmt(stmt.id={:?})", stmt_id); // Every statement will clean up the temporaries created during @@ -719,11 +739,11 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: debug!("resolve_expr(expr.id={:?})", expr.id); let prev_cx = visitor.cx; - visitor.enter_node_extent_with_dtor(expr.id); + visitor.enter_node_extent_with_dtor(expr.hir_id.local_id); { let terminating_scopes = &mut visitor.terminating_scopes; - let mut terminating = |id: ast::NodeId| { + let mut terminating = |id: hir::ItemLocalId| { terminating_scopes.insert(id); }; match expr.node { @@ -735,27 +755,27 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: hir::ExprBinary(codemap::Spanned { node: hir::BiOr, .. }, _, ref r) => { // For shortcircuiting operators, mark the RHS as a terminating // scope since it only executes conditionally. - terminating(r.id); + terminating(r.hir_id.local_id); } hir::ExprIf(ref expr, ref then, Some(ref otherwise)) => { - terminating(expr.id); - terminating(then.id); - terminating(otherwise.id); + terminating(expr.hir_id.local_id); + terminating(then.hir_id.local_id); + terminating(otherwise.hir_id.local_id); } hir::ExprIf(ref expr, ref then, None) => { - terminating(expr.id); - terminating(then.id); + terminating(expr.hir_id.local_id); + terminating(then.hir_id.local_id); } hir::ExprLoop(ref body, _, _) => { - terminating(body.id); + terminating(body.hir_id.local_id); } hir::ExprWhile(ref expr, ref body, _) => { - terminating(expr.id); - terminating(body.id); + terminating(expr.hir_id.local_id); + terminating(body.hir_id.local_id); } hir::ExprMatch(..) => { @@ -784,6 +804,29 @@ fn resolve_expr<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, expr: // record_superlifetime(new_cx, expr.callee_id); } + hir::ExprYield(..) => { + // Mark this expr's scope and all parent scopes as containing `yield`. + let mut scope = CodeExtent::Misc(expr.hir_id.local_id); + loop { + match visitor.region_maps.yield_in_scope.entry(scope) { + // Another `yield` has already been found. + Entry::Occupied(_) => break, + + Entry::Vacant(entry) => { + entry.insert(expr.span); + } + } + + // Keep traversing up while we can. + match visitor.region_maps.scope_map.get(&scope) { + // Don't cross from closure bodies to their parent. + Some(&CodeExtent::CallSiteScope(_)) => break, + Some(&superscope) => scope = superscope, + None => break + } + } + } + _ => {} } } @@ -1014,7 +1057,7 @@ fn resolve_local<'a, 'tcx>(visitor: &mut RegionResolutionVisitor<'a, 'tcx>, // because in trans if we must compile e.g. `*rvalue()` // into a temporary, we request the temporary scope of the // outer expression. - visitor.region_maps.record_rvalue_scope(expr.id, blk_scope); + visitor.region_maps.record_rvalue_scope(expr.hir_id.local_id, blk_scope); match expr.node { hir::ExprAddrOf(_, ref subexpr) | @@ -1046,7 +1089,7 @@ impl<'a, 'tcx> RegionResolutionVisitor<'a, 'tcx> { self.cx.parent = Some(child_scope); } - fn enter_node_extent_with_dtor(&mut self, id: ast::NodeId) { + fn enter_node_extent_with_dtor(&mut self, id: hir::ItemLocalId) { // If node was previously marked as a terminating scope during the // recursive visit of its parent node in the AST, then we need to // account for the destruction scope representing the extent of @@ -1078,16 +1121,16 @@ impl<'a, 'tcx> Visitor<'tcx> for RegionResolutionVisitor<'a, 'tcx> { self.cx.parent); let outer_cx = self.cx; - let outer_ts = mem::replace(&mut self.terminating_scopes, NodeSet()); - self.terminating_scopes.insert(body_id.node_id); + let outer_ts = mem::replace(&mut self.terminating_scopes, FxHashSet()); + self.terminating_scopes.insert(body.value.hir_id.local_id); if let Some(root_id) = self.cx.root_id { - self.region_maps.record_fn_parent(body_id.node_id, root_id); + self.region_maps.record_closure_parent(body.value.hir_id.local_id, root_id); } - self.cx.root_id = Some(body_id.node_id); + self.cx.root_id = Some(body.value.hir_id.local_id); - self.enter_code_extent(CodeExtent::CallSiteScope(body_id)); - self.enter_code_extent(CodeExtent::ParameterScope(body_id)); + self.enter_code_extent(CodeExtent::CallSiteScope(body.value.hir_id.local_id)); + self.enter_code_extent(CodeExtent::ParameterScope(body.value.hir_id.local_id)); // The arguments and `self` are parented to the fn. self.cx.var_parent = self.cx.parent.take(); @@ -1153,19 +1196,20 @@ fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) } let id = tcx.hir.as_local_node_id(def_id).unwrap(); - let maps = if let Some(body) = tcx.hir.maybe_body_owned_by(id) { + let maps = if let Some(body_id) = tcx.hir.maybe_body_owned_by(id) { let mut visitor = RegionResolutionVisitor { tcx, - region_maps: RegionMaps::new(), + region_maps: RegionMaps::default(), cx: Context { root_id: None, parent: None, var_parent: None, }, - terminating_scopes: NodeSet(), + terminating_scopes: FxHashSet(), }; - visitor.region_maps.root_body = Some(body); + let body = tcx.hir.body(body_id); + visitor.region_maps.root_body = Some(body.value.hir_id); // If the item is an associated const or a method, // record its impl/trait parent, as it can also have @@ -1178,112 +1222,16 @@ fn region_maps<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) _ => {} } - visitor.visit_body(tcx.hir.body(body)); + visitor.visit_body(body); visitor.region_maps } else { - RegionMaps::new() + RegionMaps::default() }; Rc::new(maps) } -struct YieldFinder<'a> { - cache: &'a mut FxHashMap>, - result: Option, -} - -impl<'a> YieldFinder<'a> { - fn lookup(&mut self, id: NodeId, f: F) { - // Don't traverse further if we found a yield expression - if self.result.is_some() { - return; - } - - // See if there's an entry in the cache - if let Some(result) = self.cache.get(&id) { - self.result = *result; - return; - } - - // Otherwise calculate the result and insert it into the cache - f(self); - self.cache.insert(id, self.result); - } -} - -impl<'a, 'tcx> Visitor<'tcx> for YieldFinder<'a> { - fn nested_visit_map<'this>(&'this mut self) -> NestedVisitorMap<'this, 'tcx> { - NestedVisitorMap::None - } - - fn visit_expr(&mut self, expr: &'tcx hir::Expr) { - if let hir::ExprYield(..) = expr.node { - self.result = Some(expr.span); - return; - } - - self.lookup(expr.id, |this| { - intravisit::walk_expr(this, expr); - }); - } - - fn visit_block(&mut self, block: &'tcx hir::Block) { - self.lookup(block.id, |this| { - intravisit::walk_block(this, block); - }); - } -} - -impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { - /// Checks whether the given code extent contains a `yield`. If so, - /// returns `Some(span)` with the span of a yield we found. - pub fn yield_in_extent(self, - extent: CodeExtent, - cache: &mut FxHashMap>) -> Option { - let mut finder = YieldFinder { - cache, - result: None, - }; - - match extent { - CodeExtent::DestructionScope(node_id) | - CodeExtent::Misc(node_id) => { - match self.hir.get(node_id) { - Node::NodeItem(_) | - Node::NodeTraitItem(_) | - Node::NodeImplItem(_) => { - let body = self.hir.body(self.hir.body_owned_by(node_id)); - finder.visit_body(body); - } - Node::NodeExpr(expr) => finder.visit_expr(expr), - Node::NodeStmt(stmt) => finder.visit_stmt(stmt), - Node::NodeBlock(block) => finder.visit_block(block), - _ => bug!(), - } - } - - CodeExtent::CallSiteScope(body_id) | - CodeExtent::ParameterScope(body_id) => { - finder.visit_body(self.hir.body(body_id)) - } - - CodeExtent::Remainder(r) => { - if let Node::NodeBlock(block) = self.hir.get(r.block) { - for stmt in &block.stmts[(r.first_statement_index as usize + 1)..] { - finder.visit_stmt(stmt); - } - block.expr.as_ref().map(|e| finder.visit_expr(e)); - } else { - bug!() - } - } - } - - finder.result - } -} - pub fn provide(providers: &mut Providers) { *providers = Providers { region_maps, diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs index 019f0a709116c..35ca8eb142283 100644 --- a/src/librustc/traits/mod.rs +++ b/src/librustc/traits/mod.rs @@ -532,7 +532,7 @@ pub fn normalize_param_env_or_error<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, debug!("normalize_param_env_or_error: normalized predicates={:?}", predicates); - let region_maps = RegionMaps::new(); + let region_maps = RegionMaps::default(); let free_regions = FreeRegionMap::new(); infcx.resolve_regions_and_report_errors(region_context, ®ion_maps, &free_regions); let predicates = match infcx.fully_resolve(&predicates) { diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs index ca735599a0da6..1851e1b8d34bb 100644 --- a/src/librustc/ty/mod.rs +++ b/src/librustc/ty/mod.rs @@ -23,7 +23,6 @@ use middle::const_val::ConstVal; use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem}; use middle::privacy::AccessLevels; use middle::resolve_lifetime::ObjectLifetimeDefault; -use middle::region::CodeExtent; use mir::Mir; use mir::GeneratorLayout; use traits; @@ -2309,10 +2308,6 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> { } } - pub fn node_scope_region(self, id: NodeId) -> Region<'tcx> { - self.mk_region(ty::ReScope(CodeExtent::Misc(id))) - } - /// Looks up the span of `impl_did` if the impl is local; otherwise returns `Err` /// with the name of the crate containing the impl. pub fn span_of_impl(self, impl_did: DefId) -> Result { diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs index a5642467474b3..2f5f31e0f63bc 100644 --- a/src/librustc/util/ppaux.rs +++ b/src/librustc/util/ppaux.rs @@ -8,7 +8,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use hir::BodyId; use hir::def_id::DefId; use hir::map::definitions::DefPathData; use middle::region::{CodeExtent, BlockRemainder}; @@ -527,16 +526,16 @@ impl fmt::Display for ty::RegionKind { } ty::ReScope(code_extent) if identify_regions() => { match code_extent { - CodeExtent::Misc(node_id) => - write!(f, "'{}mce", node_id.as_u32()), - CodeExtent::CallSiteScope(BodyId { node_id }) => - write!(f, "'{}cce", node_id.as_u32()), - CodeExtent::ParameterScope(BodyId { node_id }) => - write!(f, "'{}pce", node_id.as_u32()), - CodeExtent::DestructionScope(node_id) => - write!(f, "'{}dce", node_id.as_u32()), + CodeExtent::Misc(id) => + write!(f, "'{}mce", id.as_usize()), + CodeExtent::CallSiteScope(id) => + write!(f, "'{}cce", id.as_usize()), + CodeExtent::ParameterScope(id) => + write!(f, "'{}pce", id.as_usize()), + CodeExtent::DestructionScope(id) => + write!(f, "'{}dce", id.as_usize()), CodeExtent::Remainder(BlockRemainder { block, first_statement_index }) => - write!(f, "'{}_{}rce", block, first_statement_index), + write!(f, "'{}_{}rce", block.as_usize(), first_statement_index), } } ty::ReVar(region_vid) if identify_regions() => { diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs index e83c79fb4a414..7f31c53e63caf 100644 --- a/src/librustc_borrowck/borrowck/check_loans.rs +++ b/src/librustc_borrowck/borrowck/check_loans.rs @@ -246,7 +246,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { //! Like `each_issued_loan()`, but only considers loans that are //! currently in scope. - self.each_issued_loan(self.tcx().hir.node_to_hir_id(scope.node_id()).local_id, |loan| { + self.each_issued_loan(scope.item_local_id(), |loan| { if self.bccx.region_maps.is_subscope_of(scope, loan.kill_scope) { op(loan) } else { @@ -467,7 +467,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // 3. Where does old loan expire. let previous_end_span = - self.tcx().hir.span(old_loan.kill_scope.node_id()).end_point(); + old_loan.kill_scope.span(self.tcx(), &self.bccx.region_maps).end_point(); let mut err = match (new_loan.kind, old_loan.kind) { (ty::MutBorrow, ty::MutBorrow) => { @@ -713,12 +713,8 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { let mut ret = UseOk; - let node_id = self.tcx().hir.hir_to_node_id(hir::HirId { - owner: self.tcx().closure_base_def_id(self.bccx.owner_def_id).index, - local_id: expr_id - }); self.each_in_scope_loan_affecting_path( - region::CodeExtent::Misc(node_id), use_path, |loan| { + region::CodeExtent::Misc(expr_id), use_path, |loan| { if !compatible_borrow_kinds(loan.kind, borrow_kind) { ret = UseWhileBorrowed(loan.loan_path.clone(), loan.span); false @@ -837,11 +833,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> { // Check that we don't invalidate any outstanding loans if let Some(loan_path) = opt_loan_path(&assignee_cmt) { - let node_id = self.tcx().hir.hir_to_node_id(hir::HirId { - owner: self.tcx().closure_base_def_id(self.bccx.owner_def_id).index, - local_id: assignment_id - }); - let scope = region::CodeExtent::Misc(node_id); + let scope = region::CodeExtent::Misc(assignment_id); self.each_in_scope_loan_affecting_path(scope, &loan_path, |loan| { self.report_illegal_mutation(assignment_span, &loan_path, loan); false diff --git a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs index 22de3c759139d..461f1d6a43283 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/lifetime.rs @@ -115,8 +115,9 @@ impl<'a, 'tcx> GuaranteeLifetimeContext<'a, 'tcx> { self.bccx.tcx.mk_region(ty::ReScope(self.item_scope)) } Categorization::Local(local_id) => { + let hir_id = self.bccx.tcx.hir.node_to_hir_id(local_id); self.bccx.tcx.mk_region(ty::ReScope( - self.bccx.region_maps.var_scope(local_id))) + self.bccx.region_maps.var_scope(hir_id.local_id))) } Categorization::StaticItem | Categorization::Deref(_, mc::UnsafePtr(..)) => { diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs index e14edc43904ea..5689a30fd38c0 100644 --- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs +++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs @@ -43,7 +43,7 @@ pub fn gather_loans_in_fn<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>, let mut glcx = GatherLoanCtxt { bccx, all_loans: Vec::new(), - item_ub: region::CodeExtent::Misc(body.node_id), + item_ub: region::CodeExtent::Misc(bccx.tcx.hir.body(body).value.hir_id.local_id), move_data: MoveData::default(), move_error_collector: move_error::MoveErrorCollector::new(), }; @@ -126,7 +126,8 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for GatherLoanCtxt<'a, 'tcx> { bk={:?}, loan_cause={:?})", borrow_id, cmt, loan_region, bk, loan_cause); - self.guarantee_valid(borrow_id, + let hir_id = self.bccx.tcx.hir.node_to_hir_id(borrow_id); + self.guarantee_valid(hir_id.local_id, borrow_span, cmt, bk, @@ -291,13 +292,13 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { /// reports an error. This may entail taking out loans, which will be added to the /// `req_loan_map`. fn guarantee_valid(&mut self, - borrow_id: ast::NodeId, + borrow_id: hir::ItemLocalId, borrow_span: Span, cmt: mc::cmt<'tcx>, req_kind: ty::BorrowKind, loan_region: ty::Region<'tcx>, cause: euv::LoanCause) { - debug!("guarantee_valid(borrow_id={}, cmt={:?}, \ + debug!("guarantee_valid(borrow_id={:?}, cmt={:?}, \ req_mutbl={:?}, loan_region={:?})", borrow_id, cmt, @@ -396,7 +397,7 @@ impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> { } }; - debug!("guarantee_valid(borrow_id={}), loan={:?}", + debug!("guarantee_valid(borrow_id={:?}), loan={:?}", borrow_id, loan); // let loan_path = loan.loan_path; diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs index e4384935e3733..25aac92c13d85 100644 --- a/src/librustc_borrowck/borrowck/mod.rs +++ b/src/librustc_borrowck/borrowck/mod.rs @@ -36,7 +36,6 @@ use rustc::middle::region::{self, RegionMaps}; use rustc::middle::free_region::RegionRelations; use rustc::ty::{self, TyCtxt}; use rustc::ty::maps::Providers; -use rustc::util::nodemap::FxHashMap; use rustc_mir::util::borrowck_errors::{BorrowckErrors, Origin}; use std::fmt; @@ -167,10 +166,9 @@ fn build_borrowck_dataflow_data<'a, 'c, 'tcx, F>(this: &mut BorrowckCtxt<'a, 'tc id_range, all_loans.len()); for (loan_idx, loan) in all_loans.iter().enumerate() { - loan_dfcx.add_gen(this.tcx.hir.node_to_hir_id(loan.gen_scope.node_id()).local_id, - loan_idx); + loan_dfcx.add_gen(loan.gen_scope.item_local_id(), loan_idx); loan_dfcx.add_kill(KillFrom::ScopeEnd, - this.tcx.hir.node_to_hir_id(loan.kill_scope.node_id()).local_id, + loan.kill_scope.item_local_id(), loan_idx); } loan_dfcx.add_kills_from_flow_exits(cfg); @@ -366,10 +364,14 @@ fn closure_to_block(closure_id: DefIndex, impl<'a, 'tcx> LoanPath<'tcx> { pub fn kill_scope(&self, bccx: &BorrowckCtxt<'a, 'tcx>) -> region::CodeExtent { match self.kind { - LpVar(local_id) => bccx.region_maps.var_scope(local_id), + LpVar(local_id) => { + let hir_id = bccx.tcx.hir.node_to_hir_id(local_id); + bccx.region_maps.var_scope(hir_id.local_id) + } LpUpvar(upvar_id) => { let block_id = closure_to_block(upvar_id.closure_expr_id, bccx.tcx); - region::CodeExtent::Misc(block_id) + let hir_id = bccx.tcx.hir.node_to_hir_id(block_id); + region::CodeExtent::Misc(hir_id.local_id) } LpDowncast(ref base, _) | LpExtend(ref base, ..) => base.kill_scope(bccx), @@ -643,7 +645,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { // Get type of value and span where it was previously // moved. let node_id = self.tcx.hir.hir_to_node_id(hir::HirId { - owner: self.tcx.closure_base_def_id(self.owner_def_id).index, + owner: self.body.value.hir_id.owner, local_id: the_move.id }); let (move_span, move_note) = match the_move.kind { @@ -818,7 +820,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { debug!("err_out_of_scope: self.body.is_generator = {:?}", self.body.is_generator); let maybe_borrow_across_yield = if self.body.is_generator { - let body_extent = region::CodeExtent::Misc(self.body.id().node_id); + let body_extent = region::CodeExtent::Misc(self.body.value.hir_id.local_id); debug!("err_out_of_scope: body_extent = {:?}", body_extent); debug!("err_out_of_scope: super_scope = {:?}", super_scope); debug!("err_out_of_scope: sub_scope = {:?}", sub_scope); @@ -844,7 +846,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { // block remainder that starts with // `let a`) for a yield. We can cite // that for the user. - self.tcx.yield_in_extent(value_extent, &mut FxHashMap()) + self.region_maps.yield_in_scope(value_extent) } else { None } @@ -966,8 +968,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } } - if let Some(_) = statement_scope_span(self.tcx, super_scope) { - db.note("consider using a `let` binding to increase its lifetime"); + if let ty::ReScope(scope) = *super_scope { + let node_id = scope.node_id(self.tcx, &self.region_maps); + match self.tcx.hir.find(node_id) { + Some(hir_map::NodeStmt(_)) => { + db.note("consider using a `let` binding to increase its lifetime"); + } + _ => {} + } } db.emit(); @@ -1386,18 +1394,6 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> { } } -fn statement_scope_span(tcx: TyCtxt, region: ty::Region) -> Option { - match *region { - ty::ReScope(scope) => { - match tcx.hir.find(scope.node_id()) { - Some(hir_map::NodeStmt(stmt)) => Some(stmt.span), - _ => None - } - } - _ => None - } -} - impl BitwiseOperator for LoanDataFlowOperator { #[inline] fn join(&self, succ: usize, pred: usize) -> usize { diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs index 79a4a4f9f4d5b..7915eccbf7445 100644 --- a/src/librustc_borrowck/borrowck/move_data.rs +++ b/src/librustc_borrowck/borrowck/move_data.rs @@ -485,8 +485,7 @@ impl<'a, 'tcx> MoveData<'tcx> { LpVar(..) | LpUpvar(..) | LpDowncast(..) => { let kill_scope = path.loan_path.kill_scope(bccx); let path = *self.path_map.borrow().get(&path.loan_path).unwrap(); - self.kill_moves(path, - bccx.tcx.hir.node_to_hir_id(kill_scope.node_id()).local_id, + self.kill_moves(path, kill_scope.item_local_id(), KillFrom::ScopeEnd, dfcx_moves); } LpExtend(..) => {} @@ -501,8 +500,7 @@ impl<'a, 'tcx> MoveData<'tcx> { LpVar(..) | LpUpvar(..) | LpDowncast(..) => { let kill_scope = lp.kill_scope(bccx); dfcx_assign.add_kill(KillFrom::ScopeEnd, - bccx.tcx.hir.node_to_hir_id(kill_scope.node_id()) - .local_id, + kill_scope.item_local_id(), assignment_index); } LpExtend(..) => { diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs index b187cdaa480ed..247f51b1da443 100644 --- a/src/librustc_driver/test.rs +++ b/src/librustc_driver/test.rs @@ -50,7 +50,7 @@ struct Env<'a, 'gcx: 'a + 'tcx, 'tcx: 'a> { } struct RH<'a> { - id: ast::NodeId, + id: hir::ItemLocalId, sub: &'a [RH<'a>], } @@ -157,7 +157,7 @@ fn test_env(source_string: &str, "test_crate", |tcx| { tcx.infer_ctxt().enter(|infcx| { - let mut region_maps = RegionMaps::new(); + let mut region_maps = RegionMaps::default(); body(Env { infcx: &infcx, region_maps: &mut region_maps, @@ -188,21 +188,19 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { // creates a region hierarchy where 1 is root, 10 and 11 are // children of 1, etc - let node = ast::NodeId::from_u32; - let dscope = CodeExtent::DestructionScope(node(1)); + let dscope = CodeExtent::DestructionScope(hir::ItemLocalId(1)); self.region_maps.record_code_extent(dscope, None); self.create_region_hierarchy(&RH { - id: node(1), - sub: &[RH { - id: node(10), - sub: &[], - }, - RH { - id: node(11), - sub: &[], - }], - }, - dscope); + id: hir::ItemLocalId(1), + sub: &[RH { + id: hir::ItemLocalId(10), + sub: &[], + }, + RH { + id: hir::ItemLocalId(11), + sub: &[], + }], + }, dscope); } #[allow(dead_code)] // this seems like it could be useful, even if we don't use it now @@ -335,7 +333,7 @@ impl<'a, 'gcx, 'tcx> Env<'a, 'gcx, 'tcx> { } pub fn t_rptr_scope(&self, id: u32) -> Ty<'tcx> { - let r = ty::ReScope(CodeExtent::Misc(ast::NodeId::from_u32(id))); + let r = ty::ReScope(CodeExtent::Misc(hir::ItemLocalId(id))); self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r), self.tcx().types.isize) } diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs index 0fe30dcabb00d..52b645638b86f 100644 --- a/src/librustc_lint/builtin.rs +++ b/src/librustc_lint/builtin.rs @@ -854,7 +854,7 @@ impl<'a, 'tcx> LateLintPass<'a, 'tcx> for UnconditionalRecursion { let local_id = cfg.graph.node_data(idx).id(); if local_id != hir::DUMMY_ITEM_LOCAL_ID { let node_id = cx.tcx.hir.hir_to_node_id(hir::HirId { - owner: cx.tcx.closure_base_def_id(cfg.owner_def_id).index, + owner: body.value.hir_id.owner, local_id }); let self_recursive = match method { diff --git a/src/librustc_mir/build/matches/mod.rs b/src/librustc_mir/build/matches/mod.rs index fb345e944969a..fc6eca466a811 100644 --- a/src/librustc_mir/build/matches/mod.rs +++ b/src/librustc_mir/build/matches/mod.rs @@ -202,7 +202,8 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { pub fn schedule_drop_for_binding(&mut self, var: NodeId, span: Span) { let local_id = self.var_indices[&var]; let var_ty = self.local_decls[local_id].ty; - let extent = self.hir.region_maps.var_scope(var); + let hir_id = self.hir.tcx().hir.node_to_hir_id(var); + let extent = self.hir.region_maps.var_scope(hir_id.local_id); self.schedule_drop(span, extent, &Lvalue::Local(local_id), var_ty); } diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs index 904e30a01eba6..5cced32f7e69b 100644 --- a/src/librustc_mir/build/mod.rs +++ b/src/librustc_mir/build/mod.rs @@ -355,8 +355,8 @@ fn construct_fn<'a, 'gcx, 'tcx, A>(hir: Cx<'a, 'gcx, 'tcx>, arguments.len(), return_ty); - let call_site_extent = CodeExtent::CallSiteScope(body.id()); - let arg_extent = CodeExtent::ParameterScope(body.id()); + let call_site_extent = CodeExtent::CallSiteScope(body.value.hir_id.local_id); + let arg_extent = CodeExtent::ParameterScope(body.value.hir_id.local_id); let mut block = START_BLOCK; let source_info = builder.source_info(span); unpack!(block = builder.in_scope((call_site_extent, source_info), block, |builder| { diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index d38c72c37e80f..8a87751d846c8 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -13,7 +13,6 @@ use hair::cx::Cx; use hair::cx::to_ref::ToRef; use rustc::middle::region::{BlockRemainder, CodeExtent}; use rustc::hir; -use syntax::ast; impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { type Output = Block<'tcx>; @@ -21,11 +20,11 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Block<'tcx> { // We have to eagerly translate the "spine" of the statements // in order to get the lexical scoping correctly. - let stmts = mirror_stmts(cx, self.id, &*self.stmts); - let opt_destruction_extent = cx.region_maps.opt_destruction_extent(self.id); + let stmts = mirror_stmts(cx, self.hir_id.local_id, &*self.stmts); + let opt_destruction_extent = cx.region_maps.opt_destruction_extent(self.hir_id.local_id); Block { targeted_by_break: self.targeted_by_break, - extent: CodeExtent::Misc(self.id), + extent: CodeExtent::Misc(self.hir_id.local_id), opt_destruction_extent, span: self.span, stmts, @@ -35,24 +34,25 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { } fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, - block_id: ast::NodeId, + block_id: hir::ItemLocalId, stmts: &'tcx [hir::Stmt]) -> Vec> { let mut result = vec![]; for (index, stmt) in stmts.iter().enumerate() { - let opt_dxn_ext = cx.region_maps.opt_destruction_extent(stmt.node.id()); + let hir_id = cx.tcx.hir.node_to_hir_id(stmt.node.id()); + let opt_dxn_ext = cx.region_maps.opt_destruction_extent(hir_id.local_id); match stmt.node { - hir::StmtExpr(ref expr, id) | - hir::StmtSemi(ref expr, id) => { + hir::StmtExpr(ref expr, _) | + hir::StmtSemi(ref expr, _) => { result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Expr { - scope: CodeExtent::Misc(id), + scope: CodeExtent::Misc(hir_id.local_id), expr: expr.to_ref(), }, opt_destruction_extent: opt_dxn_ext, }))) } - hir::StmtDecl(ref decl, id) => { + hir::StmtDecl(ref decl, _) => { match decl.node { hir::DeclItem(..) => { // ignore for purposes of the MIR @@ -70,7 +70,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, result.push(StmtRef::Mirror(Box::new(Stmt { kind: StmtKind::Let { remainder_scope: remainder_extent, - init_scope: CodeExtent::Misc(id), + init_scope: CodeExtent::Misc(hir_id.local_id), pattern, initializer: local.init.to_ref(), }, @@ -88,7 +88,7 @@ pub fn to_expr_ref<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> { let block_ty = cx.tables().node_id_to_type(block.hir_id); - let temp_lifetime = cx.region_maps.temporary_scope(block.id); + let temp_lifetime = cx.region_maps.temporary_scope(block.hir_id.local_id); let expr = Expr { ty: block_ty, temp_lifetime, diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs index 553da2c978fe7..a877c61a47a91 100644 --- a/src/librustc_mir/hair/cx/expr.rs +++ b/src/librustc_mir/hair/cx/expr.rs @@ -25,8 +25,8 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { type Output = Expr<'tcx>; fn make_mirror<'a, 'gcx>(self, cx: &mut Cx<'a, 'gcx, 'tcx>) -> Expr<'tcx> { - let temp_lifetime = cx.region_maps.temporary_scope(self.id); - let expr_extent = CodeExtent::Misc(self.id); + let temp_lifetime = cx.region_maps.temporary_scope(self.hir_id.local_id); + let expr_extent = CodeExtent::Misc(self.hir_id.local_id); debug!("Expr::make_mirror(): id={}, span={:?}", self.id, self.span); @@ -52,7 +52,7 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr { }; // Finally, create a destruction scope, if any. - if let Some(extent) = cx.region_maps.opt_destruction_extent(self.id) { + if let Some(extent) = cx.region_maps.opt_destruction_extent(self.hir_id.local_id) { expr = Expr { temp_lifetime, ty: expr.ty, @@ -125,7 +125,7 @@ fn apply_adjustment<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // Convert this to a suitable `&foo` and // then an unsafe coercion. Limit the region to be just this // expression. - let region = ty::ReScope(CodeExtent::Misc(hir_expr.id)); + let region = ty::ReScope(CodeExtent::Misc(hir_expr.hir_id.local_id)); let region = cx.tcx.mk_region(region); expr = Expr { temp_lifetime, @@ -160,7 +160,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr) -> Expr<'tcx> { let expr_ty = cx.tables().expr_ty(expr); - let temp_lifetime = cx.region_maps.temporary_scope(expr.id); + let temp_lifetime = cx.region_maps.temporary_scope(expr.hir_id.local_id); let kind = match expr.node { // Here comes the interesting stuff: @@ -487,7 +487,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, match dest.target_id { hir::ScopeTarget::Block(target_id) | hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(target_id)) => ExprKind::Break { - label: CodeExtent::Misc(target_id), + label: CodeExtent::Misc(cx.tcx.hir.node_to_hir_id(target_id).local_id), value: value.to_ref(), }, hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => @@ -498,7 +498,7 @@ fn make_mirror_unadjusted<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, match dest.target_id { hir::ScopeTarget::Block(_) => bug!("cannot continue to blocks"), hir::ScopeTarget::Loop(hir::LoopIdResult::Ok(loop_id)) => ExprKind::Continue { - label: CodeExtent::Misc(loop_id), + label: CodeExtent::Misc(cx.tcx.hir.node_to_hir_id(loop_id).local_id), }, hir::ScopeTarget::Loop(hir::LoopIdResult::Err(err)) => bug!("invalid loop id for continue: {}", err) @@ -585,7 +585,7 @@ fn method_callee<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &hir::Expr, custom_callee: Option<(DefId, &'tcx Substs<'tcx>)>) -> Expr<'tcx> { - let temp_lifetime = cx.region_maps.temporary_scope(expr.id); + let temp_lifetime = cx.region_maps.temporary_scope(expr.hir_id.local_id); let (def_id, substs) = custom_callee.unwrap_or_else(|| { (cx.tables().type_dependent_defs()[expr.hir_id].def_id(), cx.tables().node_substs(expr.hir_id)) @@ -676,7 +676,7 @@ fn convert_var<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, expr: &'tcx hir::Expr, def: Def) -> ExprKind<'tcx> { - let temp_lifetime = cx.region_maps.temporary_scope(expr.id); + let temp_lifetime = cx.region_maps.temporary_scope(expr.hir_id.local_id); match def { Def::Local(def_id) => { @@ -867,7 +867,7 @@ fn overloaded_lvalue<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, // construct the complete expression `foo()` for the overloaded call, // which will yield the &T type - let temp_lifetime = cx.region_maps.temporary_scope(expr.id); + let temp_lifetime = cx.region_maps.temporary_scope(expr.hir_id.local_id); let fun = method_callee(cx, expr, custom_callee); let ref_expr = Expr { temp_lifetime, @@ -896,7 +896,7 @@ fn capture_freevar<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, closure_expr_id: cx.tcx.hir.local_def_id(closure_expr.id).index, }; let upvar_capture = cx.tables().upvar_capture(upvar_id); - let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.id); + let temp_lifetime = cx.region_maps.temporary_scope(closure_expr.hir_id.local_id); let var_ty = cx.tables() .node_id_to_type(cx.tcx.hir.node_to_hir_id(var_node_id)); let captured_var = Expr { diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs index bf134f9547d38..a4bbedfb26b38 100644 --- a/src/librustc_typeck/check/compare_method.rs +++ b/src/librustc_typeck/check/compare_method.rs @@ -340,7 +340,7 @@ fn compare_predicate_entailment<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, // region obligations that get overlooked. The right // thing to do is the code below. But we keep this old // pass around temporarily. - let region_maps = RegionMaps::new(); + let region_maps = RegionMaps::default(); let mut free_regions = FreeRegionMap::new(); free_regions.relate_free_regions_from_predicates(¶m_env.caller_bounds); infcx.resolve_regions_and_report_errors(impl_m.def_id, ®ion_maps, &free_regions); diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs index 72ff9eb6f5b0d..fd7dd052cd16d 100644 --- a/src/librustc_typeck/check/dropck.rs +++ b/src/librustc_typeck/check/dropck.rs @@ -114,7 +114,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>( return Err(ErrorReported); } - let region_maps = RegionMaps::new(); + let region_maps = RegionMaps::default(); let free_regions = FreeRegionMap::new(); infcx.resolve_regions_and_report_errors(drop_impl_did, ®ion_maps, &free_regions); Ok(()) diff --git a/src/librustc_typeck/check/generator_interior.rs b/src/librustc_typeck/check/generator_interior.rs index 46948b687d26d..60762134f0ffd 100644 --- a/src/librustc_typeck/check/generator_interior.rs +++ b/src/librustc_typeck/check/generator_interior.rs @@ -18,15 +18,12 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap}; use rustc::hir::{self, Body, Pat, PatKind, Expr}; use rustc::middle::region::{RegionMaps, CodeExtent}; use rustc::ty::Ty; -use syntax::ast::NodeId; -use syntax::codemap::Span; use std::rc::Rc; use super::FnCtxt; use util::nodemap::FxHashMap; struct InteriorVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> { fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, - cache: FxHashMap>, types: FxHashMap, usize>, region_maps: Rc, } @@ -36,7 +33,7 @@ impl<'a, 'gcx, 'tcx> InteriorVisitor<'a, 'gcx, 'tcx> { use syntax_pos::DUMMY_SP; let live_across_yield = scope.map_or(Some(DUMMY_SP), |s| { - self.fcx.tcx.yield_in_extent(s, &mut self.cache) + self.region_maps.yield_in_scope(s) }); if let Some(span) = live_across_yield { @@ -62,7 +59,6 @@ pub fn resolve_interior<'a, 'gcx, 'tcx>(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>, let mut visitor = InteriorVisitor { fcx, types: FxHashMap(), - cache: FxHashMap(), region_maps: fcx.tcx.region_maps(def_id), }; intravisit::walk_body(&mut visitor, body); @@ -97,7 +93,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'gcx, 'tcx> { fn visit_pat(&mut self, pat: &'tcx Pat) { if let PatKind::Binding(..) = pat.node { - let scope = self.region_maps.var_scope(pat.id); + let scope = self.region_maps.var_scope(pat.hir_id.local_id); let ty = self.fcx.tables.borrow().pat_ty(pat); self.record(ty, Some(scope), None); } @@ -106,7 +102,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'tcx> for InteriorVisitor<'a, 'gcx, 'tcx> { } fn visit_expr(&mut self, expr: &'tcx Expr) { - let scope = self.region_maps.temporary_scope(expr.id); + let scope = self.region_maps.temporary_scope(expr.hir_id.local_id); let ty = self.fcx.tables.borrow().expr_ty_adjusted(expr); self.record(ty, scope, Some(expr)); diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs index bd362c3535373..2fa80a10d12e4 100644 --- a/src/librustc_typeck/check/mod.rs +++ b/src/librustc_typeck/check/mod.rs @@ -606,8 +606,9 @@ impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> { let tcx = infcx.tcx; let item_id = tcx.hir.as_local_node_id(def_id); let body_id = item_id.and_then(|id| tcx.hir.maybe_body_owned_by(id)); - let implicit_region_bound = body_id.map(|body| { - tcx.mk_region(ty::ReScope(CodeExtent::CallSiteScope(body))) + let implicit_region_bound = body_id.map(|body_id| { + let body = tcx.hir.body(body_id); + tcx.mk_region(ty::ReScope(CodeExtent::CallSiteScope(body.value.hir_id.local_id))) }); Inherited { diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs index 377908b1ab9d4..0cd38a49adef2 100644 --- a/src/librustc_typeck/check/regionck.rs +++ b/src/librustc_typeck/check/regionck.rs @@ -305,7 +305,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let body_id = body.id(); - let call_site = CodeExtent::CallSiteScope(body_id); + let call_site = CodeExtent::CallSiteScope(body.value.hir_id.local_id); let old_call_site_scope = self.set_call_site_scope(Some(call_site)); let fn_sig = { @@ -330,7 +330,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { let old_body_id = self.set_body_id(body_id.node_id); self.relate_free_regions(&fn_sig_tys[..], body_id.node_id, span); - self.link_fn_args(CodeExtent::Misc(body_id.node_id), &body.arguments); + self.link_fn_args(CodeExtent::Misc(body.value.hir_id.local_id), &body.arguments); self.visit_body(body); self.visit_region_obligations(body_id.node_id); @@ -610,11 +610,11 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // that the lifetime of any regions that appear in a // variable's type enclose at least the variable's scope. - let var_scope = self.region_maps.var_scope(id); + let hir_id = self.tcx.hir.node_to_hir_id(id); + let var_scope = self.region_maps.var_scope(hir_id.local_id); let var_region = self.tcx.mk_region(ty::ReScope(var_scope)); let origin = infer::BindingTypeIsNotValidAtDecl(span); - let hir_id = self.tcx.hir.node_to_hir_id(id); self.type_of_node_must_outlive(origin, hir_id, var_region); let typ = self.resolve_node_type(hir_id); @@ -668,7 +668,7 @@ impl<'a, 'gcx, 'tcx> Visitor<'gcx> for RegionCtxt<'a, 'gcx, 'tcx> { // scope of that expression. This also guarantees basic WF. let expr_ty = self.resolve_node_type(expr.hir_id); // the region corresponding to this expression - let expr_region = self.tcx.node_scope_region(expr.id); + let expr_region = self.tcx.mk_region(ty::ReScope(CodeExtent::Misc(expr.hir_id.local_id))); self.type_must_outlive(infer::ExprTypeIsNotInScope(expr_ty, expr.span), expr_ty, expr_region); @@ -950,7 +950,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // call occurs. // // FIXME(#6268) to support nested method calls, should be callee_id - let callee_scope = CodeExtent::Misc(call_expr.id); + let callee_scope = CodeExtent::Misc(call_expr.hir_id.local_id); let callee_region = self.tcx.mk_region(ty::ReScope(callee_scope)); debug!("callee_region={:?}", callee_region); @@ -1002,7 +1002,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { // expression. self.check_safety_of_rvalue_destructor_if_necessary(cmt.clone(), expr.span); - let expr_region = self.tcx.node_scope_region(expr.id); + let expr_region = self.tcx.mk_region(ty::ReScope(CodeExtent::Misc(expr.hir_id.local_id))); for adjustment in adjustments { debug!("constrain_adjustments: adjustment={:?}, cmt={:?}", adjustment, cmt); @@ -1095,7 +1095,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { debug!("constrain_index(index_expr=?, indexed_ty={}", self.ty_to_string(indexed_ty)); - let r_index_expr = ty::ReScope(CodeExtent::Misc(index_expr.id)); + let r_index_expr = ty::ReScope(CodeExtent::Misc(index_expr.hir_id.local_id)); if let ty::TyRef(r_ptr, mt) = indexed_ty.sty { match mt.ty.sty { ty::TySlice(_) | ty::TyStr => { @@ -1232,7 +1232,7 @@ impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> { } adjustment::AutoBorrow::RawPtr(m) => { - let r = self.tcx.node_scope_region(expr.id); + let r = self.tcx.mk_region(ty::ReScope(CodeExtent::Misc(expr.hir_id.local_id))); self.link_region(expr.span, r, ty::BorrowKind::from_mutbl(m), expr_cmt); } } diff --git a/src/librustc_typeck/coherence/builtin.rs b/src/librustc_typeck/coherence/builtin.rs index 9305eff143652..9cf15e2145d36 100644 --- a/src/librustc_typeck/coherence/builtin.rs +++ b/src/librustc_typeck/coherence/builtin.rs @@ -390,7 +390,7 @@ pub fn coerce_unsized_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, } // Finally, resolve all regions. - let region_maps = RegionMaps::new(); + let region_maps = RegionMaps::default(); let mut free_regions = FreeRegionMap::new(); free_regions.relate_free_regions_from_predicates(¶m_env.caller_bounds); infcx.resolve_regions_and_report_errors(impl_did, ®ion_maps, &free_regions); diff --git a/src/test/mir-opt/end_region_1.rs b/src/test/mir-opt/end_region_1.rs index 55dac4440275f..7be677c184b73 100644 --- a/src/test/mir-opt/end_region_1.rs +++ b/src/test/mir-opt/end_region_1.rs @@ -22,16 +22,16 @@ fn main() { // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // let _1: i32; -// let _2: &'6_1rce i32; +// let _2: &'10_1rce i32; // // bb0: { // StorageLive(_1); // _1 = const 3i32; // StorageLive(_2); -// _2 = &'6_1rce _1; +// _2 = &'10_1rce _1; // _0 = (); // StorageDead(_2); -// EndRegion('6_1rce); +// EndRegion('10_1rce); // StorageDead(_1); // return; // } diff --git a/src/test/mir-opt/end_region_2.rs b/src/test/mir-opt/end_region_2.rs index a1386ec47a13b..2cb9b38e7bb94 100644 --- a/src/test/mir-opt/end_region_2.rs +++ b/src/test/mir-opt/end_region_2.rs @@ -27,8 +27,8 @@ fn main() { // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // let _2: bool; -// let _3: &'7_1rce bool; -// let _7: &'7_3rce bool; +// let _3: &'23_1rce bool; +// let _7: &'23_3rce bool; // let mut _4: (); // let mut _5: bool; // bb0: { @@ -38,7 +38,7 @@ fn main() { // StorageLive(_2); // _2 = const true; // StorageLive(_3); -// _3 = &'7_1rce _2; +// _3 = &'23_1rce _2; // StorageLive(_5); // _5 = _2; // switchInt(_5) -> [0u8: bb3, otherwise: bb2]; @@ -47,19 +47,19 @@ fn main() { // _0 = (); // StorageDead(_5); // StorageDead(_3); -// EndRegion('7_1rce); +// EndRegion('23_1rce); // StorageDead(_2); // return; // } // bb3: { // StorageDead(_5); // StorageLive(_7); -// _7 = &'7_3rce _2; +// _7 = &'23_3rce _2; // _1 = (); // StorageDead(_7); -// EndRegion('7_3rce); +// EndRegion('23_3rce); // StorageDead(_3); -// EndRegion('7_1rce); +// EndRegion('23_1rce); // StorageDead(_2); // goto -> bb1; // } diff --git a/src/test/mir-opt/end_region_3.rs b/src/test/mir-opt/end_region_3.rs index b3d2809e76ceb..001bb9c1a0284 100644 --- a/src/test/mir-opt/end_region_3.rs +++ b/src/test/mir-opt/end_region_3.rs @@ -28,8 +28,8 @@ fn main() { // START rustc.node4.SimplifyCfg-qualify-consts.after.mir // let mut _0: (); // let mut _1: bool; -// let _3: &'9_1rce bool; -// let _7: &'9_3rce bool; +// let _3: &'26_1rce bool; +// let _7: &'26_3rce bool; // let mut _2: (); // let mut _4: (); // let mut _5: bool; @@ -41,7 +41,7 @@ fn main() { // bb1: { // _1 = const true; // StorageLive(_3); -// _3 = &'9_1rce _1; +// _3 = &'26_1rce _1; // StorageLive(_5); // _5 = _1; // switchInt(_5) -> [0u8: bb3, otherwise: bb2]; @@ -50,7 +50,7 @@ fn main() { // _0 = (); // StorageDead(_5); // StorageDead(_3); -// EndRegion('9_1rce); +// EndRegion('26_1rce); // StorageDead(_1); // return; // } @@ -58,12 +58,12 @@ fn main() { // _4 = (); // StorageDead(_5); // StorageLive(_7); -// _7 = &'9_3rce _1; +// _7 = &'26_3rce _1; // _2 = (); // StorageDead(_7); -// EndRegion('9_3rce); +// EndRegion('26_3rce); // StorageDead(_3); -// EndRegion('9_1rce); +// EndRegion('26_1rce); // goto -> bb1; // } // END rustc.node4.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_4.rs b/src/test/mir-opt/end_region_4.rs index 0b34231b4eec6..8c854ce87a2c6 100644 --- a/src/test/mir-opt/end_region_4.rs +++ b/src/test/mir-opt/end_region_4.rs @@ -33,8 +33,8 @@ fn foo(i: i32) { // let mut _0: (); // let _1: D; // let _2: i32; -// let _3: &'6_2rce i32; -// let _6: &'6_4rce i32; +// let _3: &'26_2rce i32; +// let _6: &'26_4rce i32; // let mut _4: (); // let mut _5: i32; // bb0: { @@ -43,7 +43,7 @@ fn foo(i: i32) { // StorageLive(_2); // _2 = const 0i32; // StorageLive(_3); -// _3 = &'6_2rce _2; +// _3 = &'26_2rce _2; // StorageLive(_5); // _5 = (*_3); // _4 = const foo(_5) -> [return: bb1, unwind: bb3]; @@ -51,12 +51,12 @@ fn foo(i: i32) { // bb1: { // StorageDead(_5); // StorageLive(_6); -// _6 = &'6_4rce _2; +// _6 = &'26_4rce _2; // _0 = (); // StorageDead(_6); -// EndRegion('6_4rce); +// EndRegion('26_4rce); // StorageDead(_3); -// EndRegion('6_2rce); +// EndRegion('26_2rce); // StorageDead(_2); // drop(_1) -> bb4; // } @@ -64,7 +64,7 @@ fn foo(i: i32) { // resume; // } // bb3: { -// EndRegion('6_2rce); +// EndRegion('26_2rce); // drop(_1) -> bb2; // } // bb4: { diff --git a/src/test/mir-opt/end_region_5.rs b/src/test/mir-opt/end_region_5.rs index e51bb9350db60..ae1b4e2e83abb 100644 --- a/src/test/mir-opt/end_region_5.rs +++ b/src/test/mir-opt/end_region_5.rs @@ -31,21 +31,21 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let mut _0: (); // let _1: D; // let mut _2: (); -// let mut _3: [closure@NodeId(18) d:&'19mce D]; -// let mut _4: &'19mce D; +// let mut _3: [closure@NodeId(18) d:&'14mce D]; +// let mut _4: &'14mce D; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // StorageLive(_3); // StorageLive(_4); -// _4 = &'19mce _1; +// _4 = &'14mce _1; // _3 = [closure@NodeId(18)] { d: _4 }; // StorageDead(_4); // _2 = const foo(_3) -> [return: bb1, unwind: bb3]; // } // bb1: { // StorageDead(_3); -// EndRegion('19mce); +// EndRegion('14mce); // _0 = (); // drop(_1) -> bb4; // } @@ -53,7 +53,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // resume; // } // bb3: { -// EndRegion('19mce); +// EndRegion('14mce); // drop(_1) -> bb2; // } // bb4: { @@ -64,13 +64,13 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.node4.SimplifyCfg-qualify-consts.after.mir // START rustc.node18.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(18) d:&'19mce D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(18) d:&'14mce D]) -> i32 { // let mut _0: i32; // let mut _2: i32; // // bb0: { // StorageLive(_2); -// _2 = ((*(_1.0: &'19mce D)).0: i32); +// _2 = ((*(_1.0: &'14mce D)).0: i32); // _0 = _2; // StorageDead(_2); // return; diff --git a/src/test/mir-opt/end_region_6.rs b/src/test/mir-opt/end_region_6.rs index c55e6d105cbdc..8054b64400669 100644 --- a/src/test/mir-opt/end_region_6.rs +++ b/src/test/mir-opt/end_region_6.rs @@ -31,21 +31,21 @@ fn foo(f: F) where F: FnOnce() -> i32 { // let mut _0: (); // let _1: D; // let mut _2: (); -// let mut _3: [closure@NodeId(22) d:&'23mce D]; -// let mut _4: &'23mce D; +// let mut _3: [closure@NodeId(22) d:&'19mce D]; +// let mut _4: &'19mce D; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // StorageLive(_3); // StorageLive(_4); -// _4 = &'23mce _1; +// _4 = &'19mce _1; // _3 = [closure@NodeId(22)] { d: _4 }; // StorageDead(_4); // _2 = const foo(_3) -> [return: bb1, unwind: bb3]; // } // bb1: { // StorageDead(_3); -// EndRegion('23mce); +// EndRegion('19mce); // _0 = (); // drop(_1) -> bb4; // } @@ -53,7 +53,7 @@ fn foo(f: F) where F: FnOnce() -> i32 { // resume; // } // bb3: { -// EndRegion('23mce); +// EndRegion('19mce); // drop(_1) -> bb2; // } // bb4: { @@ -63,20 +63,20 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.node4.SimplifyCfg-qualify-consts.after.mir // START rustc.node22.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'23mce D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(22) d:&'19mce D]) -> i32 { // let mut _0: i32; -// let _2: &'14_0rce D; +// let _2: &'15_0rce D; // let mut _3: i32; // // bb0: { // StorageLive(_2); -// _2 = &'14_0rce (*(_1.0: &'23mce D)); +// _2 = &'15_0rce (*(_1.0: &'19mce D)); // StorageLive(_3); // _3 = ((*_2).0: i32); // _0 = _3; // StorageDead(_3); // StorageDead(_2); -// EndRegion('14_0rce); +// EndRegion('15_0rce); // return; // } // END rustc.node22.SimplifyCfg-qualify-consts.after.mir diff --git a/src/test/mir-opt/end_region_7.rs b/src/test/mir-opt/end_region_7.rs index 9c8e3ec08d498..d68439087615b 100644 --- a/src/test/mir-opt/end_region_7.rs +++ b/src/test/mir-opt/end_region_7.rs @@ -74,18 +74,18 @@ fn foo(f: F) where F: FnOnce() -> i32 { // START rustc.node22.SimplifyCfg-qualify-consts.after.mir // fn main::{{closure}}(_1: [closure@NodeId(22) d:D]) -> i32 { // let mut _0: i32; -// let _2: &'14_0rce D; +// let _2: &'15_0rce D; // let mut _3: i32; // // bb0: { // StorageLive(_2); -// _2 = &'14_0rce (_1.0: D); +// _2 = &'15_0rce (_1.0: D); // StorageLive(_3); // _3 = ((*_2).0: i32); // _0 = _3; // StorageDead(_3); // StorageDead(_2); -// EndRegion('14_0rce); +// EndRegion('15_0rce); // drop(_1) -> bb1; // } // bb1: { diff --git a/src/test/mir-opt/end_region_8.rs b/src/test/mir-opt/end_region_8.rs index b4dbec5cd2dd7..8d7050941e7eb 100644 --- a/src/test/mir-opt/end_region_8.rs +++ b/src/test/mir-opt/end_region_8.rs @@ -31,15 +31,15 @@ fn foo(f: F) where F: FnOnce() -> i32 { // fn main() -> () { // let mut _0: (); // let _1: D; -// let _2: &'6_1rce D; +// let _2: &'21_1rce D; // let mut _3: (); -// let mut _4: [closure@NodeId(22) r:&'6_1rce D]; -// let mut _5: &'6_1rce D; +// let mut _4: [closure@NodeId(22) r:&'21_1rce D]; +// let mut _5: &'21_1rce D; // bb0: { // StorageLive(_1); // _1 = D::{{constructor}}(const 0i32,); // StorageLive(_2); -// _2 = &'6_1rce _1; +// _2 = &'21_1rce _1; // StorageLive(_4); // StorageLive(_5); // _5 = _2; @@ -51,14 +51,14 @@ fn foo(f: F) where F: FnOnce() -> i32 { // StorageDead(_4); // _0 = (); // StorageDead(_2); -// EndRegion('6_1rce); +// EndRegion('21_1rce); // drop(_1) -> bb4; // } // bb2: { // resume; // } // bb3: { -// EndRegion('6_1rce); +// EndRegion('21_1rce); // drop(_1) -> bb2; // } // bb4: { @@ -69,13 +69,13 @@ fn foo(f: F) where F: FnOnce() -> i32 { // END rustc.node4.SimplifyCfg-qualify-consts.after.mir // START rustc.node22.SimplifyCfg-qualify-consts.after.mir -// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'6_1rce D]) -> i32 { +// fn main::{{closure}}(_1: [closure@NodeId(22) r:&'21_1rce D]) -> i32 { // let mut _0: i32; // let mut _2: i32; // // bb0: { // StorageLive(_2); -// _2 = ((*(_1.0: &'6_1rce D)).0: i32); +// _2 = ((*(_1.0: &'21_1rce D)).0: i32); // _0 = _2; // StorageDead(_2); // return; diff --git a/src/test/mir-opt/validate_1.rs b/src/test/mir-opt/validate_1.rs index 677c92ea71b7a..9c528da8b348d 100644 --- a/src/test/mir-opt/validate_1.rs +++ b/src/test/mir-opt/validate_1.rs @@ -37,19 +37,19 @@ fn main() { // START rustc.node23.EraseRegions.after.mir // fn main() -> () { // bb0: { -// Validate(Suspend(ReScope(Misc(NodeId(34)))), [_1: i32]); +// Validate(Suspend(ReScope(Misc(ItemLocalId(10)))), [_1: i32]); // _6 = &ReErased mut _1; -// Validate(Acquire, [(*_6): i32/ReScope(Misc(NodeId(34)))]); -// Validate(Suspend(ReScope(Misc(NodeId(34)))), [(*_6): i32/ReScope(Misc(NodeId(34)))]); +// Validate(Acquire, [(*_6): i32/ReScope(Misc(ItemLocalId(10)))]); +// Validate(Suspend(ReScope(Misc(ItemLocalId(10)))), [(*_6): i32/ReScope(Misc(ItemLocalId(10)))]); // _5 = &ReErased mut (*_6); -// Validate(Acquire, [(*_5): i32/ReScope(Misc(NodeId(34)))]); -// Validate(Release, [_2: (), _3: &ReScope(Misc(NodeId(34))) Test, _5: &ReScope(Misc(NodeId(34))) mut i32]); +// Validate(Acquire, [(*_5): i32/ReScope(Misc(ItemLocalId(10)))]); +// Validate(Release, [_2: (), _3: &ReScope(Misc(ItemLocalId(10))) Test, _5: &ReScope(Misc(ItemLocalId(10))) mut i32]); // _2 = const Test::foo(_3, _5) -> bb1; // } // // bb1: { // Validate(Acquire, [_2: ()]); -// EndRegion(ReScope(Misc(NodeId(34)))); +// EndRegion(ReScope(Misc(ItemLocalId(10)))); // return; // } // } @@ -61,15 +61,15 @@ fn main() { // StorageLive(_3); // _3 = _2; // StorageLive(_4); -// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: NodeId(41), first_statement_index: 0 }))), [(*_3): i32]); +// Validate(Suspend(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 }))), [(*_3): i32]); // _4 = &ReErased (*_3); -// Validate(Acquire, [(*_4): i32/ReScope(Remainder(BlockRemainder { block: NodeId(41), first_statement_index: 0 })) (imm)]); +// Validate(Acquire, [(*_4): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 })) (imm)]); // StorageLive(_5); // _5 = (*_4); // _0 = _5; // StorageDead(_5); // StorageDead(_4); -// EndRegion(ReScope(Remainder(BlockRemainder { block: NodeId(41), first_statement_index: 0 }))); +// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(22), first_statement_index: 0 }))); // StorageDead(_3); // return; // } diff --git a/src/test/mir-opt/validate_3.rs b/src/test/mir-opt/validate_3.rs index 9140cf5768f59..cd556564b7913 100644 --- a/src/test/mir-opt/validate_3.rs +++ b/src/test/mir-opt/validate_3.rs @@ -32,18 +32,18 @@ fn main() { // fn main() -> () { // let mut _5: &ReErased i32; // bb0: { -// Validate(Suspend(ReScope(Misc(NodeId(46)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: NodeId(18), first_statement_index: 3 })) (imm)]); +// Validate(Suspend(ReScope(Misc(ItemLocalId(17)))), [((*_2).0: i32): i32/ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 })) (imm)]); // _5 = &ReErased ((*_2).0: i32); -// Validate(Acquire, [(*_5): i32/ReScope(Misc(NodeId(46))) (imm)]); -// Validate(Suspend(ReScope(Misc(NodeId(46)))), [(*_5): i32/ReScope(Misc(NodeId(46))) (imm)]); +// Validate(Acquire, [(*_5): i32/ReScope(Misc(ItemLocalId(17))) (imm)]); +// Validate(Suspend(ReScope(Misc(ItemLocalId(17)))), [(*_5): i32/ReScope(Misc(ItemLocalId(17))) (imm)]); // _4 = &ReErased (*_5); -// Validate(Acquire, [(*_4): i32/ReScope(Misc(NodeId(46))) (imm)]); -// Validate(Release, [_3: (), _4: &ReScope(Misc(NodeId(46))) i32]); +// Validate(Acquire, [(*_4): i32/ReScope(Misc(ItemLocalId(17))) (imm)]); +// Validate(Release, [_3: (), _4: &ReScope(Misc(ItemLocalId(17))) i32]); // _3 = const foo(_4) -> bb1; // } // bb1: { -// EndRegion(ReScope(Misc(NodeId(46)))); -// EndRegion(ReScope(Remainder(BlockRemainder { block: NodeId(18), first_statement_index: 3 }))); +// EndRegion(ReScope(Misc(ItemLocalId(17)))); +// EndRegion(ReScope(Remainder(BlockRemainder { block: ItemLocalId(19), first_statement_index: 3 }))); // return; // } // } diff --git a/src/test/mir-opt/validate_5.rs b/src/test/mir-opt/validate_5.rs index 0182e6e296445..224f4ce2effe3 100644 --- a/src/test/mir-opt/validate_5.rs +++ b/src/test/mir-opt/validate_5.rs @@ -50,12 +50,12 @@ fn main() { // _3 = _2; // StorageLive(_4); // StorageLive(_5); -// Validate(Suspend(ReScope(Misc(NodeId(44)))), [(*_3): i32]); +// Validate(Suspend(ReScope(Misc(ItemLocalId(9)))), [(*_3): i32]); // _5 = &ReErased mut (*_3); -// Validate(Acquire, [(*_5): i32/ReScope(Misc(NodeId(44)))]); +// Validate(Acquire, [(*_5): i32/ReScope(Misc(ItemLocalId(9)))]); // _4 = _5 as *mut i32 (Misc); // StorageDead(_5); -// EndRegion(ReScope(Misc(NodeId(44)))); +// EndRegion(ReScope(Misc(ItemLocalId(9)))); // Validate(Release, [_0: bool, _4: *mut i32]); // _0 = const write_42(_4) -> bb1; // }