From cbed41a174aad44e069bec09bf1e502591c132ae Mon Sep 17 00:00:00 2001 From: "Felix S. Klock II" Date: Tue, 23 May 2017 13:18:20 +0200 Subject: [PATCH] Add destruction extents around blocks and statements in HAIR. --- src/librustc_mir/build/block.rs | 52 ++++++++++++++++++------------- src/librustc_mir/build/scope.rs | 17 ++++++++++ src/librustc_mir/hair/cx/block.rs | 11 +++++++ src/librustc_mir/hair/mod.rs | 2 ++ 4 files changed, 60 insertions(+), 22 deletions(-) diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs index d81de954dbf1..1933ef29b539 100644 --- a/src/librustc_mir/build/block.rs +++ b/src/librustc_mir/build/block.rs @@ -21,21 +21,24 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { ast_block: &'tcx hir::Block, source_info: SourceInfo) -> BlockAnd<()> { - let Block { extent, span, stmts, expr, targeted_by_break } = self.hir.mirror(ast_block); - self.in_scope(extent, block, move |this| { - if targeted_by_break { - // This is a `break`-able block (currently only `catch { ... }`) - let exit_block = this.cfg.start_new_block(); - let block_exit = this.in_breakable_scope(None, exit_block, - destination.clone(), |this| { + let Block { extent, opt_destruction_extent, span, stmts, expr, targeted_by_break } = + self.hir.mirror(ast_block); + self.in_opt_scope(opt_destruction_extent, block, move |this| { + this.in_scope(extent, block, move |this| { + if targeted_by_break { + // This is a `break`-able block (currently only `catch { ... }`) + let exit_block = this.cfg.start_new_block(); + let block_exit = this.in_breakable_scope( + None, exit_block, destination.clone(), |this| { + this.ast_block_stmts(destination, block, span, stmts, expr) + }); + this.cfg.terminate(unpack!(block_exit), source_info, + TerminatorKind::Goto { target: exit_block }); + exit_block.unit() + } else { this.ast_block_stmts(destination, block, span, stmts, expr) - }); - this.cfg.terminate(unpack!(block_exit), source_info, - TerminatorKind::Goto { target: exit_block }); - exit_block.unit() - } else { - this.ast_block_stmts(destination, block, span, stmts, expr) - } + } + }) }) } @@ -67,12 +70,14 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { let mut let_extent_stack = Vec::with_capacity(8); let outer_visibility_scope = this.visibility_scope; for stmt in stmts { - let Stmt { span: _, kind } = this.hir.mirror(stmt); + let Stmt { span: _, kind, opt_destruction_extent } = this.hir.mirror(stmt); match kind { StmtKind::Expr { scope, expr } => { - unpack!(block = this.in_scope(scope, block, |this| { - let expr = this.hir.mirror(expr); - this.stmt_expr(block, expr) + unpack!(block = this.in_opt_scope(opt_destruction_extent, block, |this| { + this.in_scope(scope, block, |this| { + let expr = this.hir.mirror(expr); + this.stmt_expr(block, expr) + }) })); } StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => { @@ -89,10 +94,13 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { // Evaluate the initializer, if present. if let Some(init) = initializer { - unpack!(block = this.in_scope(init_scope, block, move |this| { - // FIXME #30046 ^~~~ - this.expr_into_pattern(block, pattern, init) - })); + unpack!(block = this.in_opt_scope( + opt_destruction_extent, block, move |this| { + this.in_scope(init_scope, block, move |this| { + // FIXME #30046 ^~~~ + this.expr_into_pattern(block, pattern, init) + }) + })); } else { this.visit_bindings(&pattern, &mut |this, _, _, node, span, _| { this.storage_live_binding(block, node, span); diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs index a99e7b4be576..d9c303369ccd 100644 --- a/src/librustc_mir/build/scope.rs +++ b/src/librustc_mir/build/scope.rs @@ -269,6 +269,23 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> { res } + pub fn in_opt_scope(&mut self, + opt_extent: Option, + mut block: BasicBlock, + f: F) + -> BlockAnd + where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd + { + debug!("in_opt_scope(opt_extent={:?}, block={:?})", opt_extent, block); + if let Some(extent) = opt_extent { self.push_scope(extent); } + let rv = unpack!(block = f(self)); + if let Some(extent) = opt_extent { + unpack!(block = self.pop_scope(extent, block)); + } + debug!("in_scope: exiting opt_extent={:?} block={:?}", opt_extent, block); + block.and(rv) + } + /// Convenience wrapper that pushes a scope and then executes `f` /// to build its contents, popping the scope afterwards. pub fn in_scope(&mut self, diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs index 47c50b78f3ac..fad070ca8d8f 100644 --- a/src/librustc_mir/hair/cx/block.rs +++ b/src/librustc_mir/hair/cx/block.rs @@ -22,9 +22,14 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block { // 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_def_id = cx.tcx.hir.opt_local_def_id(self.id); + let opt_destruction_extent = opt_def_id.and_then(|def_id| { + cx.tcx.region_maps(def_id).opt_destruction_extent(self.id) + }); Block { targeted_by_break: self.targeted_by_break, extent: CodeExtent::Misc(self.id), + opt_destruction_extent: opt_destruction_extent, span: self.span, stmts: stmts, expr: self.expr.to_ref(), @@ -37,7 +42,11 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, stmts: &'tcx [hir::Stmt]) -> Vec> { let mut result = vec![]; + let opt_def_id = cx.tcx.hir.opt_local_def_id(block_id); for (index, stmt) in stmts.iter().enumerate() { + let opt_dxn_ext = opt_def_id.and_then(|def_id| { + cx.tcx.region_maps(def_id).opt_destruction_extent(stmt.node.id()) + }); match stmt.node { hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) => { @@ -47,6 +56,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, scope: CodeExtent::Misc(id), expr: expr.to_ref(), }, + opt_destruction_extent: opt_dxn_ext, }))) } hir::StmtDecl(ref decl, id) => { @@ -69,6 +79,7 @@ fn mirror_stmts<'a, 'gcx, 'tcx>(cx: &mut Cx<'a, 'gcx, 'tcx>, pattern: pattern, initializer: local.init.to_ref(), }, + opt_destruction_extent: opt_dxn_ext, }))); } } diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs index 044096699b1a..bb11cce74875 100644 --- a/src/librustc_mir/hair/mod.rs +++ b/src/librustc_mir/hair/mod.rs @@ -33,6 +33,7 @@ pub use rustc_const_eval::pattern::{BindingMode, Pattern, PatternKind, FieldPatt pub struct Block<'tcx> { pub targeted_by_break: bool, pub extent: CodeExtent, + pub opt_destruction_extent: Option, pub span: Span, pub stmts: Vec>, pub expr: Option>, @@ -47,6 +48,7 @@ pub enum StmtRef<'tcx> { pub struct Stmt<'tcx> { pub span: Span, pub kind: StmtKind<'tcx>, + pub opt_destruction_extent: Option, } #[derive(Clone, Debug)]