about summary refs log tree commit diff
diff options
context:
space:
mode:
authorkennytm <kennytm@gmail.com>2018-10-26 18:25:02 +0800
committerkennytm <kennytm@gmail.com>2018-10-26 23:06:25 +0800
commit9111fab74df4e0f6f2b8bfb5936f3772ba59a960 (patch)
tree8242128230ababd385bb4fccf0de66c501f3d9e7
parent46f504543d47e18484a65251918a937147bb8a45 (diff)
parent80a6b736acca2c109547e100d217fe5ca5f4ec30 (diff)
downloadrust-9111fab74df4e0f6f2b8bfb5936f3772ba59a960.tar.gz
rust-9111fab74df4e0f6f2b8bfb5936f3772ba59a960.zip
Rollup merge of #55271 - sinkuu:traversal_iter, r=matthewjasper
Unimplement ExactSizeIterator for MIR traversing iterators

If `root` is not `START_BLOCK`, `basic_blocks().len() - visited` does not represent their exact size.
-rw-r--r--src/librustc/mir/traversal.rs36
1 files changed, 24 insertions, 12 deletions
diff --git a/src/librustc/mir/traversal.rs b/src/librustc/mir/traversal.rs
index db1bc3e7519..a1e2b7a0646 100644
--- a/src/librustc/mir/traversal.rs
+++ b/src/librustc/mir/traversal.rs
@@ -34,6 +34,7 @@ pub struct Preorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     visited: BitSet<BasicBlock>,
     worklist: Vec<BasicBlock>,
+    root_is_start_block: bool,
 }
 
 impl<'a, 'tcx> Preorder<'a, 'tcx> {
@@ -44,6 +45,7 @@ impl<'a, 'tcx> Preorder<'a, 'tcx> {
             mir,
             visited: BitSet::new_empty(mir.basic_blocks().len()),
             worklist,
+            root_is_start_block: root == START_BLOCK,
         }
     }
 }
@@ -75,15 +77,19 @@ impl<'a, 'tcx> Iterator for Preorder<'a, 'tcx> {
 
     fn size_hint(&self) -> (usize, Option<usize>) {
         // All the blocks, minus the number of blocks we've visited.
-        let remaining = self.mir.basic_blocks().len() - self.visited.count();
+        let upper = self.mir.basic_blocks().len() - self.visited.count();
 
-        // We will visit all remaining blocks exactly once.
-        (remaining, Some(remaining))
+        let lower = if self.root_is_start_block {
+            // We will visit all remaining blocks exactly once.
+            upper
+        } else {
+            self.worklist.len()
+        };
+
+        (lower, Some(upper))
     }
 }
 
-impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
-
 /// Postorder traversal of a graph.
 ///
 /// Postorder traversal is when each node is visited after all of it's
@@ -105,7 +111,8 @@ impl<'a, 'tcx> ExactSizeIterator for Preorder<'a, 'tcx> {}
 pub struct Postorder<'a, 'tcx: 'a> {
     mir: &'a Mir<'tcx>,
     visited: BitSet<BasicBlock>,
-    visit_stack: Vec<(BasicBlock, Successors<'a>)>
+    visit_stack: Vec<(BasicBlock, Successors<'a>)>,
+    root_is_start_block: bool,
 }
 
 impl<'a, 'tcx> Postorder<'a, 'tcx> {
@@ -113,7 +120,8 @@ impl<'a, 'tcx> Postorder<'a, 'tcx> {
         let mut po = Postorder {
             mir,
             visited: BitSet::new_empty(mir.basic_blocks().len()),
-            visit_stack: Vec::new()
+            visit_stack: Vec::new(),
+            root_is_start_block: root == START_BLOCK,
         };
 
 
@@ -214,15 +222,19 @@ impl<'a, 'tcx> Iterator for Postorder<'a, 'tcx> {
 
     fn size_hint(&self) -> (usize, Option<usize>) {
         // All the blocks, minus the number of blocks we've visited.
-        let remaining = self.mir.basic_blocks().len() - self.visited.count();
+        let upper = self.mir.basic_blocks().len() - self.visited.count();
 
-        // We will visit all remaining blocks exactly once.
-        (remaining, Some(remaining))
+        let lower = if self.root_is_start_block {
+            // We will visit all remaining blocks exactly once.
+            upper
+        } else {
+            self.visit_stack.len()
+        };
+
+        (lower, Some(upper))
     }
 }
 
-impl<'a, 'tcx> ExactSizeIterator for Postorder<'a, 'tcx> {}
-
 /// Reverse postorder traversal of a graph
 ///
 /// Reverse postorder is the reverse order of a postorder traversal.