]> git.lizzy.rs Git - rust.git/commitdiff
Drop "solved" constraints during region expansion
authorBjörn Steinbrink <bsteinbr@gmail.com>
Wed, 9 Jan 2019 17:40:30 +0000 (18:40 +0100)
committerBjörn Steinbrink <bsteinbr@gmail.com>
Thu, 10 Jan 2019 19:10:11 +0000 (20:10 +0100)
Once a region has been expanded to cover a fixed region, a corresponding
RegSubVar constraint won't have any effect on the expansion anymore, the
same is true for constraints where the variable on the RHS has already
reached static scope. By removing those constraints from the set that
we're iterating over, we remove a lot of needless overhead in case of
slow convergences (i.e. lots of iterations).

For the unicode_normalization crate, this about cuts the time required
for item_bodies checking in half.

src/librustc/infer/lexical_region_resolve/mod.rs

index dbf8f270ab0c988fb88e6ebb7c4ffddbbd90ad3b..2a93217b9b423b3efb74eccae15c2e99c785669d 100644 (file)
@@ -13,6 +13,7 @@
     Direction, Graph, NodeIndex, INCOMING, OUTGOING,
 };
 use rustc_data_structures::indexed_vec::{Idx, IndexVec};
+use smallvec::SmallVec;
 use std::fmt;
 use std::u32;
 use ty::fold::TypeFoldable;
@@ -190,19 +191,24 @@ fn expansion(&self, var_values: &mut LexicalRegionResolutions<'tcx>) {
             match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
                     let b_data = var_values.value_mut(b_vid);
-                    self.expand_node(a_region, b_vid, b_data)
+                    (self.expand_node(a_region, b_vid, b_data), false)
                 }
                 Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
-                    VarValue::ErrorValue => false,
+                    VarValue::ErrorValue => (false, false),
                     VarValue::Value(a_region) => {
                         let b_node = var_values.value_mut(b_vid);
-                        self.expand_node(a_region, b_vid, b_node)
+                        let changed = self.expand_node(a_region, b_vid, b_node);
+                        let retain = match *b_node {
+                            VarValue::Value(ReStatic) | VarValue::ErrorValue => false,
+                            _ => true
+                        };
+                        (changed, retain)
                     }
                 },
                 Constraint::RegSubReg(..) | Constraint::VarSubReg(..) => {
                     // These constraints are checked after expansion
                     // is done, in `collect_errors`.
-                    false
+                    (false, false)
                 }
             }
         })
@@ -710,21 +716,23 @@ fn process_edges<'tcx>(
 
     fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
     where
-        F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> bool,
+        F: FnMut(&Constraint<'tcx>, &SubregionOrigin<'tcx>) -> (bool, bool),
     {
+        let mut constraints: SmallVec<[_; 16]> = self.data.constraints.iter().collect();
         let mut iteration = 0;
         let mut changed = true;
         while changed {
             changed = false;
             iteration += 1;
             debug!("---- {} Iteration {}{}", "#", tag, iteration);
-            for (constraint, origin) in &self.data.constraints {
-                let edge_changed = body(constraint, origin);
+            constraints.retain(|(constraint, origin)| {
+                let (edge_changed, retain) = body(constraint, origin);
                 if edge_changed {
                     debug!("Updated due to constraint {:?}", constraint);
                     changed = true;
                 }
-            }
+                retain
+            });
         }
         debug!("---- {} Complete after {} iteration(s)", tag, iteration);
     }