about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc_mir/build/block.rs52
-rw-r--r--src/librustc_mir/build/scope.rs17
-rw-r--r--src/librustc_mir/hair/cx/block.rs11
-rw-r--r--src/librustc_mir/hair/mod.rs2
4 files changed, 60 insertions, 22 deletions
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index d81de954dbf..1933ef29b53 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 a99e7b4be57..d9c303369cc 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<F, R>(&mut self,
+                              opt_extent: Option<CodeExtent>,
+                              mut block: BasicBlock,
+                              f: F)
+                              -> BlockAnd<R>
+        where F: FnOnce(&mut Builder<'a, 'gcx, 'tcx>) -> BlockAnd<R>
+    {
+        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<F, R>(&mut self,
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index 47c50b78f3a..fad070ca8d8 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<StmtRef<'tcx>> {
     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 044096699b1..bb11cce7487 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<CodeExtent>,
     pub span: Span,
     pub stmts: Vec<StmtRef<'tcx>>,
     pub expr: Option<ExprRef<'tcx>>,
@@ -47,6 +48,7 @@ pub enum StmtRef<'tcx> {
 pub struct Stmt<'tcx> {
     pub span: Span,
     pub kind: StmtKind<'tcx>,
+    pub opt_destruction_extent: Option<CodeExtent>,
 }
 
 #[derive(Clone, Debug)]