From 47425e476b8fd087799d1229a23f7aa81c1835bf Mon Sep 17 00:00:00 2001
From: Josh Stone <jistone@redhat.com>
Date: Tue, 30 Jun 2020 17:53:45 -0700
Subject: [PATCH] Rewrite a few manual index loops with while-let

There were a few instances of this pattern:

```rust
while index < vec.len() {
    let item = &vec[index];
    // ...
}
```

These can be indexed at once:

```rust
while let Some(item) = vec.get(index) {
    // ...
}
```

Particularly in `ObligationForest::process_obligations`, this mitigates
a codegen regression found with LLVM 11 (#73526).
---
 src/librustc_data_structures/obligation_forest/mod.rs | 10 ++++------
 src/librustc_data_structures/transitive_relation.rs   |  6 ++----
 2 files changed, 6 insertions(+), 10 deletions(-)

diff --git a/src/librustc_data_structures/obligation_forest/mod.rs b/src/librustc_data_structures/obligation_forest/mod.rs
index 197169b7036e0..7cf5202d919f8 100644
--- a/src/librustc_data_structures/obligation_forest/mod.rs
+++ b/src/librustc_data_structures/obligation_forest/mod.rs
@@ -412,9 +412,7 @@ impl<O: ForestObligation> ObligationForest<O> {
         // be computed with the initial length, and we would miss the appended
         // nodes. Therefore we use a `while` loop.
         let mut index = 0;
-        while index < self.nodes.len() {
-            let node = &mut self.nodes[index];
-
+        while let Some(node) = self.nodes.get_mut(index) {
             // `processor.process_obligation` can modify the predicate within
             // `node.obligation`, and that predicate is the key used for
             // `self.active_cache`. This means that `self.active_cache` can get
@@ -666,8 +664,8 @@ impl<O: ForestObligation> ObligationForest<O> {
 
         for node in &mut self.nodes {
             let mut i = 0;
-            while i < node.dependents.len() {
-                let new_index = node_rewrites[node.dependents[i]];
+            while let Some(dependent) = node.dependents.get_mut(i) {
+                let new_index = node_rewrites[*dependent];
                 if new_index >= orig_nodes_len {
                     node.dependents.swap_remove(i);
                     if i == 0 && node.has_parent {
@@ -675,7 +673,7 @@ impl<O: ForestObligation> ObligationForest<O> {
                         node.has_parent = false;
                     }
                 } else {
-                    node.dependents[i] = new_index;
+                    *dependent = new_index;
                     i += 1;
                 }
             }
diff --git a/src/librustc_data_structures/transitive_relation.rs b/src/librustc_data_structures/transitive_relation.rs
index de503fe8228aa..189da3395ad1b 100644
--- a/src/librustc_data_structures/transitive_relation.rs
+++ b/src/librustc_data_structures/transitive_relation.rs
@@ -391,14 +391,12 @@ impl<T: Clone + Debug + Eq + Hash> TransitiveRelation<T> {
 /// - Input: `[a, x, b, y]`. Output: `[a, x]`.
 fn pare_down(candidates: &mut Vec<usize>, closure: &BitMatrix<usize, usize>) {
     let mut i = 0;
-    while i < candidates.len() {
-        let candidate_i = candidates[i];
+    while let Some(&candidate_i) = candidates.get(i) {
         i += 1;
 
         let mut j = i;
         let mut dead = 0;
-        while j < candidates.len() {
-            let candidate_j = candidates[j];
+        while let Some(&candidate_j) = candidates.get(j) {
             if closure.contains(candidate_i, candidate_j) {
                 // If `i` can reach `j`, then we can remove `j`. So just
                 // mark it as dead and move on; subsequent indices will be