]> git.lizzy.rs Git - rust.git/commitdiff
Make list of statements flat
authorSimonas Kazlauskas <git@kazlauskas.me>
Wed, 24 Feb 2016 15:14:03 +0000 (17:14 +0200)
committerSimonas Kazlauskas <git@kazlauskas.me>
Wed, 24 Feb 2016 20:04:22 +0000 (22:04 +0200)
In MIR we previously tried to match `let x in { exprs; let y in { exprs; }}` with our data
structures which is rather unwieldy, espeicially because it requires some sort of recursion or
stack to process, while, a flat list of statements is enough – lets only relinquish their lifetime
at the end of the block (i.e. end of the list).

Also fixes #31853.

src/librustc/dep_graph/mod.rs
src/librustc_mir/build/block.rs
src/librustc_mir/build/mod.rs
src/librustc_mir/build/scope.rs
src/librustc_mir/build/stmt.rs [deleted file]
src/librustc_mir/hair/cx/block.rs
src/librustc_mir/hair/mod.rs

index faf97f5808e36b1b490431dfda73f633976e3e88..a4d222d24cac1619c6f1f6efebb88d1b07a8010c 100644 (file)
@@ -198,8 +198,8 @@ impl<'visit, 'tcx, F, V> Visitor<'tcx> for TrackingVisitor<'visit, 'tcx, F, V>
         fn visit_item(&mut self, i: &'tcx hir::Item) {
             let item_def_id = self.tcx.map.local_def_id(i.id);
             let task_id = (self.dep_node_fn)(item_def_id);
-            debug!("About to start task {:?}", task_id);
             let _task = self.tcx.dep_graph.in_task(task_id);
+            debug!("Started task {:?}", task_id);
             self.tcx.dep_graph.read(DepNode::Hir(item_def_id));
             self.visitor.visit_item(i)
         }
index 12b9130b48c612c9081914e2af66f6597a819951..7d8a35165d286e5b47c136b58238d40cfbbe6436 100644 (file)
@@ -21,14 +21,70 @@ pub fn ast_block(&mut self,
                      -> BlockAnd<()> {
         let Block { extent, span, stmts, expr } = self.hir.mirror(ast_block);
         self.in_scope(extent, block, move |this| {
-            unpack!(block = this.stmts(block, stmts));
-            match expr {
-                Some(expr) => this.into(destination, block, expr),
-                None => {
-                    this.cfg.push_assign_unit(block, span, destination);
-                    block.unit()
+            // This convoluted structure is to avoid using recursion as we walk down a list
+            // of statements. Basically, the structure we get back is something like:
+            //
+            //    let x = <init> in {
+            //       expr1;
+            //       let y = <init> in {
+            //           expr2;
+            //           expr3;
+            //           ...
+            //       }
+            //    }
+            //
+            // The let bindings are valid till the end of block so all we have to do is to pop all
+            // the let-scopes at the end.
+            //
+            // First we build all the statements in the block.
+            let mut let_extent_stack = Vec::with_capacity(8);
+            for stmt in stmts {
+                let Stmt { span: _, kind } = this.hir.mirror(stmt);
+                match kind {
+                    StmtKind::Expr { scope, expr } => {
+                        unpack!(block = this.in_scope(scope, block, |this| {
+                            let expr = this.hir.mirror(expr);
+                            let temp = this.temp(expr.ty.clone());
+                            unpack!(block = this.into(&temp, block, expr));
+                            unpack!(block = this.build_drop(block, temp));
+                            block.unit()
+                        }));
+                    }
+                    StmtKind::Let { remainder_scope, init_scope, pattern, initializer } => {
+                        this.push_scope(remainder_scope);
+                        let_extent_stack.push(remainder_scope);
+                        unpack!(block = this.in_scope(init_scope, block, move |this| {
+                            // FIXME #30046                              ^~~~
+                            match initializer {
+                                Some(initializer) => {
+                                    this.expr_into_pattern(block,
+                                                           remainder_scope,
+                                                           pattern,
+                                                           initializer)
+                                }
+                                None => {
+                                    this.declare_bindings(remainder_scope, &pattern);
+                                    block.unit()
+                                }
+                            }
+                        }));
+                    }
                 }
             }
+            // Then, the block may have an optional trailing expression which is a “return” value
+            // of the block.
+            if let Some(expr) = expr {
+                unpack!(block = this.into(destination, block, expr));
+            } else {
+                // FIXME(#31472)
+                this.cfg.push_assign_unit(block, span, destination);
+            }
+            // Finally, we pop all the let scopes before exiting out from the scope of block
+            // itself.
+            for extent in let_extent_stack.into_iter().rev() {
+                unpack!(block = this.pop_scope(extent, block));
+            }
+            block.unit()
         })
     }
 }
index b83d0f6a9803a96c2990b61910367fcc36822b73..5d9f827984e0e116e45a1039d2fd653412f6c3a6 100644 (file)
@@ -185,4 +185,3 @@ fn get_unit_temp(&mut self) -> Lvalue<'tcx> {
 mod matches;
 mod misc;
 mod scope;
-mod stmt;
index 7be70867796ff0088aa7350ebaf1384eb7afdb32..a738663bf8cc50a8e9f0678eb79b42b54a28877b 100644 (file)
@@ -249,6 +249,7 @@ pub fn exit_scope(&mut self,
                       extent: CodeExtent,
                       mut block: BasicBlock,
                       target: BasicBlock) {
+        debug!("exit_scope(extent={:?}, block={:?}, target={:?})", extent, block, target);
         let scope_count = 1 + self.scopes.iter().rev().position(|scope| scope.extent == extent)
                                                       .unwrap_or_else(||{
             self.hir.span_bug(span, &format!("extent {:?} does not enclose", extent))
diff --git a/src/librustc_mir/build/stmt.rs b/src/librustc_mir/build/stmt.rs
deleted file mode 100644 (file)
index 6c0f1c7..0000000
+++ /dev/null
@@ -1,83 +0,0 @@
-// Copyright 2015 The Rust Project Developers. See the COPYRIGHT
-// file at the top-level directory of this distribution and at
-// http://rust-lang.org/COPYRIGHT.
-//
-// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
-// http://www.apache.org/licenses/LICENSE-2.0> or the MIT license
-// <LICENSE-MIT or http://opensource.org/licenses/MIT>, at your
-// option. This file may not be copied, modified, or distributed
-// except according to those terms.
-
-use build::{BlockAnd, BlockAndExtension, Builder};
-use hair::*;
-use rustc::mir::repr::*;
-
-impl<'a,'tcx> Builder<'a,'tcx> {
-    pub fn stmts(&mut self, mut block: BasicBlock, stmts: Vec<StmtRef<'tcx>>) -> BlockAnd<()> {
-        // This convoluted structure is to avoid using recursion as we walk down a list
-        // of statements. Basically, the structure we get back is something like:
-        //
-        //    let x = <init> in {
-        //       let y = <init> in {
-        //           expr1;
-        //           expr2;
-        //       }
-        //    }
-        //
-        // To process this, we keep a stack of (Option<CodeExtent>,
-        // vec::IntoIter<Stmt>) pairs.  At each point we pull off the
-        // top most pair and extract one statement from the
-        // iterator. Once it's complete, we pop the scope from the
-        // first half the pair.
-        let this = self;
-        let mut stmt_lists = vec![(None, stmts.into_iter())];
-        while !stmt_lists.is_empty() {
-            let stmt = {
-                let &mut (_, ref mut stmts) = stmt_lists.last_mut().unwrap();
-                stmts.next()
-            };
-
-            let stmt = match stmt {
-                Some(stmt) => stmt,
-                None => {
-                    let (extent, _) = stmt_lists.pop().unwrap();
-                    if let Some(extent) = extent {
-                        unpack!(block = this.pop_scope(extent, block));
-                    }
-                    continue
-                }
-            };
-
-            let Stmt { span: _, kind } = this.hir.mirror(stmt);
-            match kind {
-                StmtKind::Let { remainder_scope, init_scope, pattern, initializer, stmts } => {
-                    this.push_scope(remainder_scope);
-                    stmt_lists.push((Some(remainder_scope), stmts.into_iter()));
-                    unpack!(block = this.in_scope(init_scope, block, move |this| {
-                        // FIXME #30046                              ^~~~
-                        match initializer {
-                            Some(initializer) => {
-                                this.expr_into_pattern(block, remainder_scope, pattern, initializer)
-                            }
-                            None => {
-                                this.declare_bindings(remainder_scope, &pattern);
-                                block.unit()
-                            }
-                        }
-                    }));
-                }
-
-                StmtKind::Expr { scope, expr } => {
-                    unpack!(block = this.in_scope(scope, block, |this| {
-                        let expr = this.hir.mirror(expr);
-                        let temp = this.temp(expr.ty.clone());
-                        unpack!(block = this.into(&temp, block, expr));
-                        unpack!(block = this.build_drop(block, temp));
-                        block.unit()
-                    }));
-                }
-            }
-        }
-        block.unit()
-    }
-}
index 49617ed5171bdd39e100bc8cc8185e120c83f952..66cb1f56b916bb24449fa6723fe353922cbbafb9 100644 (file)
@@ -26,7 +26,7 @@ fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
             extent: cx.tcx.region_maps.node_extent(self.id),
             span: self.span,
             stmts: stmts,
-            expr: self.expr.to_ref(),
+            expr: self.expr.to_ref()
         }
     }
 }
@@ -41,13 +41,13 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
     while let Some((index, stmt)) = stmts.next() {
         match stmt.node {
             hir::StmtExpr(ref expr, id) | hir::StmtSemi(ref expr, id) =>
-                result.push(
-                    StmtRef::Mirror(
-                        Box::new(Stmt { span: stmt.span,
-                                        kind: StmtKind::Expr {
-                                            scope: cx.tcx.region_maps.node_extent(id),
-                                            expr: expr.to_ref() } }))),
-
+                result.push(StmtRef::Mirror(Box::new(Stmt {
+                    span: stmt.span,
+                    kind: StmtKind::Expr {
+                        scope: cx.tcx.region_maps.node_extent(id),
+                        expr: expr.to_ref()
+                    }
+                }))),
             hir::StmtDecl(ref decl, id) => {
                 match decl.node {
                     hir::DeclItem(..) => { /* ignore for purposes of the MIR */ }
@@ -59,10 +59,6 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
                         let remainder_extent =
                             cx.tcx.region_maps.lookup_code_extent(remainder_extent);
 
-                        // pull in all following statements, since
-                        // they are within the scope of this let:
-                        let following_stmts = mirror_stmts(cx, block_id, stmts);
-
                         let pattern = cx.irrefutable_pat(&local.pat);
                         result.push(StmtRef::Mirror(Box::new(Stmt {
                             span: stmt.span,
@@ -71,11 +67,8 @@ fn mirror_stmts<'a,'tcx:'a,STMTS>(cx: &mut Cx<'a,'tcx>,
                                 init_scope: cx.tcx.region_maps.node_extent(id),
                                 pattern: pattern,
                                 initializer: local.init.to_ref(),
-                                stmts: following_stmts,
                             },
                         })));
-
-                        return result;
                     }
                 }
             }
index e8edd4067e2f827dd0971a80b130aa17e2b896c1..707dd972003ff465859c9ac24d4961162918e3d5 100644 (file)
@@ -78,10 +78,7 @@ pub enum StmtKind<'tcx> {
         pattern: Pattern<'tcx>,
 
         /// let pat = <INIT> ...
-        initializer: Option<ExprRef<'tcx>>,
-
-        /// let pat = init; <STMTS>
-        stmts: Vec<StmtRef<'tcx>>,
+        initializer: Option<ExprRef<'tcx>>
     },
 }