about summary refs log tree commit diff
diff options
context:
space:
mode:
authorFelix S. Klock II <pnkfelix@pnkfx.org>2018-11-08 14:31:12 +0100
committerFelix S. Klock II <pnkfelix@pnkfx.org>2018-11-08 14:31:12 +0100
commite7e1a52f63433c4e5d37836104b8080b3ad4e8c7 (patch)
tree88491952325e56594074439bd3180d407c7174b1
parent556f583587ce87bfaa5e1fd27bc89d8fdfe84339 (diff)
downloadrust-e7e1a52f63433c4e5d37836104b8080b3ad4e8c7.tar.gz
rust-e7e1a52f63433c4e5d37836104b8080b3ad4e8c7.zip
Refactor code so that block_context observations has nicely named (and documented) methods.
-rw-r--r--src/librustc_mir/build/block.rs12
-rw-r--r--src/librustc_mir/build/expr/as_temp.rs16
-rw-r--r--src/librustc_mir/build/mod.rs56
3 files changed, 58 insertions, 26 deletions
diff --git a/src/librustc_mir/build/block.rs b/src/librustc_mir/build/block.rs
index 83e132054a9..2ef71617b7c 100644
--- a/src/librustc_mir/build/block.rs
+++ b/src/librustc_mir/build/block.rs
@@ -177,17 +177,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
         let destination_ty = destination.ty(&this.local_decls, tcx).to_ty(tcx);
         if let Some(expr) = expr {
             let tail_result_is_ignored = destination_ty.is_unit() ||
-                match this.block_context.last() {
-                    // no context: conservatively assume result is read
-                    None => false,
-
-                    // sub-expression: block result feeds into some computation
-                    Some(BlockFrame::SubExpr) => false,
-
-                    // otherwise: use accumualated is_ignored state.
-                    Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) |
-                    Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
-                };
+                this.block_context.currently_ignores_tail_results();
             this.block_context.push(BlockFrame::TailExpr { tail_result_is_ignored });
 
             unpack!(block = this.into(destination, block, expr));
diff --git a/src/librustc_mir/build/expr/as_temp.rs b/src/librustc_mir/build/expr/as_temp.rs
index e0bf02c6739..8f50a1e9a21 100644
--- a/src/librustc_mir/build/expr/as_temp.rs
+++ b/src/librustc_mir/build/expr/as_temp.rs
@@ -10,7 +10,7 @@
 
 //! See docs in build/expr/mod.rs
 
-use build::{BlockAnd, BlockAndExtension, BlockFrame, Builder};
+use build::{BlockAnd, BlockAndExtension, Builder};
 use hair::*;
 use rustc::middle::region;
 use rustc::mir::*;
@@ -68,19 +68,9 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             debug!("creating temp {:?} with block_context: {:?}", local_decl, this.block_context);
             // Find out whether this temp is being created within the
             // tail expression of a block whose result is ignored.
-            for bf in this.block_context.iter().rev() {
-                match bf {
-                    BlockFrame::SubExpr => continue,
-                    BlockFrame::Statement { .. } => break,
-                    &BlockFrame::TailExpr { tail_result_is_ignored } => {
-                        local_decl = local_decl.block_tail(BlockTailInfo {
-                            tail_result_is_ignored
-                        });
-                        break;
-                    }
-                }
+            if let Some(tail_info) = this.block_context.currently_in_block_tail() {
+                local_decl = local_decl.block_tail(tail_info);
             }
-
             this.local_decls.push(local_decl)
         };
         if !expr_ty.is_never() {
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index 5b4001f0652..a01f8940a94 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -336,6 +336,9 @@ impl BlockFrame {
     }
  }
 
+#[derive(Debug)]
+struct BlockContext(Vec<BlockFrame>);
+
 struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     hir: Cx<'a, 'gcx, 'tcx>,
     cfg: CFG<'tcx>,
@@ -359,7 +362,7 @@ struct Builder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     /// start just throwing new entries onto that vector in order to
     /// distinguish the context of EXPR1 from the context of EXPR2 in
     /// `{ STMTS; EXPR1 } + EXPR2`
-    block_context: Vec<BlockFrame>,
+    block_context: BlockContext,
 
     /// The current unsafe block in scope, even if it is hidden by
     /// a PushUnsafeBlock
@@ -409,6 +412,55 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
     }
 }
 
+impl BlockContext {
+    fn new() -> Self { BlockContext(vec![]) }
+    fn push(&mut self, bf: BlockFrame) { self.0.push(bf); }
+    fn pop(&mut self) -> Option<BlockFrame> { self.0.pop() }
+
+    /// Traverses the frames on the BlockContext, searching for either
+    /// the first block-tail expression frame with no intervening
+    /// statement frame.
+    ///
+    /// Notably, this skips over `SubExpr` frames; this method is
+    /// meant to be used in the context of understanding the
+    /// relationship of a temp (created within some complicated
+    /// expression) with its containing expression, and whether the
+    /// value of that *containing expression* (not the temp!) is
+    /// ignored.
+    fn currently_in_block_tail(&self) -> Option<BlockTailInfo> {
+        for bf in self.0.iter().rev() {
+            match bf {
+                BlockFrame::SubExpr => continue,
+                BlockFrame::Statement { .. } => break,
+                &BlockFrame::TailExpr { tail_result_is_ignored } =>
+                    return Some(BlockTailInfo { tail_result_is_ignored })
+            }
+        }
+
+        return None;
+    }
+
+    /// Looks at the topmost frame on the BlockContext and reports
+    /// whether its one that would discard a block tail result.
+    ///
+    /// Unlike `currently_within_ignored_tail_expression`, this does
+    /// *not* skip over `SubExpr` frames: here, we want to know
+    /// whether the block result itself is discarded.
+    fn currently_ignores_tail_results(&self) -> bool {
+        match self.0.last() {
+            // no context: conservatively assume result is read
+            None => false,
+
+            // sub-expression: block result feeds into some computation
+            Some(BlockFrame::SubExpr) => false,
+
+            // otherwise: use accumulated is_ignored state.
+            Some(BlockFrame::TailExpr { tail_result_is_ignored: ignored }) |
+            Some(BlockFrame::Statement { ignores_expr_result: ignored }) => *ignored,
+        }
+    }
+}
+
 #[derive(Debug)]
 enum LocalsForNode {
     /// In the usual case, a node-id for an identifier maps to at most
@@ -764,7 +816,7 @@ impl<'a, 'gcx, 'tcx> Builder<'a, 'gcx, 'tcx> {
             fn_span: span,
             arg_count,
             scopes: vec![],
-            block_context: vec![],
+            block_context: BlockContext::new(),
             source_scopes: IndexVec::new(),
             source_scope: OUTERMOST_SOURCE_SCOPE,
             source_scope_local_data: IndexVec::new(),