about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/infer/lexical_region_resolve/graphviz.rs20
-rw-r--r--src/librustc/infer/lexical_region_resolve/mod.rs10
-rw-r--r--src/librustc/infer/mod.rs9
-rw-r--r--src/librustc/infer/region_constraints/mod.rs203
4 files changed, 123 insertions, 119 deletions
diff --git a/src/librustc/infer/lexical_region_resolve/graphviz.rs b/src/librustc/infer/lexical_region_resolve/graphviz.rs
index 880c0e22947..41209487395 100644
--- a/src/librustc/infer/lexical_region_resolve/graphviz.rs
+++ b/src/librustc/infer/lexical_region_resolve/graphviz.rs
@@ -25,7 +25,7 @@ use middle::free_region::RegionRelations;
 use middle::region;
 use super::Constraint;
 use infer::SubregionOrigin;
-use infer::region_constraints::RegionConstraintCollector;
+use infer::region_constraints::RegionConstraintData;
 use util::nodemap::{FxHashMap, FxHashSet};
 
 use std::borrow::Cow;
@@ -57,7 +57,7 @@ graphs will be printed.                                                     \n\
 }
 
 pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
-    region_constraints: &RegionConstraintCollector<'tcx>,
+    region_data: &RegionConstraintData<'tcx>,
     region_rels: &RegionRelations<'a, 'gcx, 'tcx>)
 {
     let tcx = region_rels.tcx;
@@ -113,7 +113,7 @@ pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
         }
     };
 
-    match dump_region_constraints_to(region_rels, &region_constraints.constraints, &output_path) {
+    match dump_region_data_to(region_rels, &region_data.constraints, &output_path) {
         Ok(()) => {}
         Err(e) => {
             let msg = format!("io error dumping region constraints: {}", e);
@@ -267,15 +267,15 @@ impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
 
 pub type ConstraintMap<'tcx> = BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>;
 
-fn dump_region_constraints_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
-                                              map: &ConstraintMap<'tcx>,
-                                              path: &str)
-                                              -> io::Result<()> {
-    debug!("dump_region_constraints map (len: {}) path: {}",
+fn dump_region_data_to<'a, 'gcx, 'tcx>(region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
+                                       map: &ConstraintMap<'tcx>,
+                                       path: &str)
+                                       -> io::Result<()> {
+    debug!("dump_region_data map (len: {}) path: {}",
            map.len(),
            path);
-    let g = ConstraintGraph::new(format!("region_constraints"), region_rels, map);
-    debug!("dump_region_constraints calling render");
+    let g = ConstraintGraph::new(format!("region_data"), region_rels, map);
+    debug!("dump_region_data calling render");
     let mut v = Vec::new();
     dot::render(&g, &mut v).unwrap();
     File::create(path).and_then(|mut f| f.write_all(&v))
diff --git a/src/librustc/infer/lexical_region_resolve/mod.rs b/src/librustc/infer/lexical_region_resolve/mod.rs
index 9a02b274b5f..3522420a5dc 100644
--- a/src/librustc/infer/lexical_region_resolve/mod.rs
+++ b/src/librustc/infer/lexical_region_resolve/mod.rs
@@ -14,7 +14,7 @@ use infer::SubregionOrigin;
 use infer::RegionVariableOrigin;
 use infer::region_constraints::Constraint;
 use infer::region_constraints::GenericKind;
-use infer::region_constraints::RegionConstraintCollector;
+use infer::region_constraints::RegionConstraintData;
 use infer::region_constraints::VerifyBound;
 use middle::free_region::RegionRelations;
 use rustc_data_structures::fx::FxHashSet;
@@ -73,20 +73,20 @@ struct RegionAndOrigin<'tcx> {
 
 type RegionGraph<'tcx> = graph::Graph<(), Constraint<'tcx>>;
 
-impl<'tcx> RegionConstraintCollector<'tcx> {
+impl<'tcx> RegionConstraintData<'tcx> {
     /// This function performs the actual region resolution.  It must be
     /// called after all constraints have been added.  It performs a
     /// fixed-point iteration to find region values which satisfy all
     /// constraints, assuming such values can be found; if they cannot,
     /// errors are reported.
     pub fn resolve_regions(
-        &mut self,
+        mut self,
         region_rels: &RegionRelations<'_, '_, 'tcx>,
     ) -> (
         LexicalRegionResolutions<'tcx>,
         Vec<RegionResolutionError<'tcx>>,
     ) {
-        debug!("RegionConstraintCollector: resolve_regions()");
+        debug!("RegionConstraintData: resolve_regions()");
         let mut errors = vec![];
         let values = self.infer_variable_values(region_rels, &mut errors);
         (values, errors)
@@ -642,7 +642,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         return (result, dup_found);
 
         fn process_edges<'tcx>(
-            this: &RegionConstraintCollector<'tcx>,
+            this: &RegionConstraintData<'tcx>,
             state: &mut WalkState<'tcx>,
             graph: &RegionGraph<'tcx>,
             source_vid: RegionVid,
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index a5cae839aa7..53112bcd880 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -1132,10 +1132,11 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                                region_context,
                                                region_map,
                                                free_regions);
-        let mut region_constraints = self.region_constraints.borrow_mut()
-                                                            .take()
-                                                            .expect("regions already resolved");
-        let (lexical_region_resolutions, errors) = region_constraints.resolve_regions(&region_rels);
+        let region_data = self.region_constraints.borrow_mut()
+                                                 .take()
+                                                 .expect("regions already resolved")
+                                                 .into_data();
+        let (lexical_region_resolutions, errors) = region_data.resolve_regions(&region_rels);
 
         let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
         assert!(old_value.is_none());
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 446acac4fd1..d2cd52c73e2 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -30,6 +30,69 @@ use std::u32;
 
 mod taint;
 
+pub struct RegionConstraintCollector<'tcx> {
+    data: RegionConstraintData<'tcx>,
+    lubs: CombineMap<'tcx>,
+    glbs: CombineMap<'tcx>,
+    skolemization_count: u32,
+    bound_count: u32,
+
+    /// The undo log records actions that might later be undone.
+    ///
+    /// Note: when the undo_log is empty, we are not actively
+    /// snapshotting. When the `start_snapshot()` method is called, we
+    /// push an OpenSnapshot entry onto the list to indicate that we
+    /// are now actively snapshotting. The reason for this is that
+    /// otherwise we end up adding entries for things like the lower
+    /// bound on a variable and so forth, which can never be rolled
+    /// back.
+    undo_log: Vec<UndoLogEntry<'tcx>>,
+
+    unification_table: UnificationTable<ty::RegionVid>,
+}
+
+/// The full set of region constraints gathered up by the collector.
+/// Describes a set of region variables ranging from 0..N (where N is
+/// the length of the `var_origins` vector), and various constraints
+/// between them.
+#[derive(Default)]
+pub struct RegionConstraintData<'tcx> {
+    /// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
+    pub var_origins: Vec<RegionVariableOrigin>,
+
+    /// Constraints of the form `A <= B`, where either `A` or `B` can
+    /// be a region variable (or neither, as it happens).
+    pub constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
+
+    /// A "verify" is something that we need to verify after inference
+    /// is done, but which does not directly affect inference in any
+    /// way.
+    ///
+    /// An example is a `A <= B` where neither `A` nor `B` are
+    /// inference variables.
+    pub verifys: Vec<Verify<'tcx>>,
+
+    /// A "given" is a relationship that is known to hold. In
+    /// particular, we often know from closure fn signatures that a
+    /// particular free region must be a subregion of a region
+    /// variable:
+    ///
+    ///    foo.iter().filter(<'a> |x: &'a &'b T| ...)
+    ///
+    /// In situations like this, `'b` is in fact a region variable
+    /// introduced by the call to `iter()`, and `'a` is a bound region
+    /// on the closure (as indicated by the `<'a>` prefix). If we are
+    /// naive, we wind up inferring that `'b` must be `'static`,
+    /// because we require that it be greater than `'a` and we do not
+    /// know what `'a` is precisely.
+    ///
+    /// This hashmap is used to avoid that naive scenario. Basically
+    /// we record the fact that `'a <= 'b` is implied by the fn
+    /// signature, and then ignore the constraint when solving
+    /// equations. This is a bit of a hack but seems to work.
+    pub givens: FxHashSet<(Region<'tcx>, ty::RegionVid)>,
+}
+
 /// A constraint that influences the inference process.
 #[derive(Clone, Copy, PartialEq, Eq, Hash, Debug, PartialOrd, Ord)]
 pub enum Constraint<'tcx> {
@@ -143,65 +206,6 @@ enum CombineMapType {
 
 type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
 
-pub struct RegionConstraintCollector<'tcx> {
-    pub(in infer) var_origins: Vec<RegionVariableOrigin>,
-
-    /// Constraints of the form `A <= B` introduced by the region
-    /// checker.  Here at least one of `A` and `B` must be a region
-    /// variable.
-    ///
-    /// Using `BTreeMap` because the order in which we iterate over
-    /// these constraints can affect the way we build the region graph,
-    /// which in turn affects the way that region errors are reported,
-    /// leading to small variations in error output across runs and
-    /// platforms.
-    pub(in infer) constraints: BTreeMap<Constraint<'tcx>, SubregionOrigin<'tcx>>,
-
-    /// A "verify" is something that we need to verify after inference is
-    /// done, but which does not directly affect inference in any way.
-    ///
-    /// An example is a `A <= B` where neither `A` nor `B` are
-    /// inference variables.
-    pub(in infer) verifys: Vec<Verify<'tcx>>,
-
-    /// A "given" is a relationship that is known to hold. In particular,
-    /// we often know from closure fn signatures that a particular free
-    /// region must be a subregion of a region variable:
-    ///
-    ///    foo.iter().filter(<'a> |x: &'a &'b T| ...)
-    ///
-    /// In situations like this, `'b` is in fact a region variable
-    /// introduced by the call to `iter()`, and `'a` is a bound region
-    /// on the closure (as indicated by the `<'a>` prefix). If we are
-    /// naive, we wind up inferring that `'b` must be `'static`,
-    /// because we require that it be greater than `'a` and we do not
-    /// know what `'a` is precisely.
-    ///
-    /// This hashmap is used to avoid that naive scenario. Basically we
-    /// record the fact that `'a <= 'b` is implied by the fn signature,
-    /// and then ignore the constraint when solving equations. This is
-    /// a bit of a hack but seems to work.
-    pub(in infer) givens: FxHashSet<(Region<'tcx>, ty::RegionVid)>,
-
-    lubs: CombineMap<'tcx>,
-    glbs: CombineMap<'tcx>,
-    skolemization_count: u32,
-    bound_count: u32,
-
-    /// The undo log records actions that might later be undone.
-    ///
-    /// Note: when the undo_log is empty, we are not actively
-    /// snapshotting. When the `start_snapshot()` method is called, we
-    /// push an OpenSnapshot entry onto the list to indicate that we
-    /// are now actively snapshotting. The reason for this is that
-    /// otherwise we end up adding entries for things like the lower
-    /// bound on a variable and so forth, which can never be rolled
-    /// back.
-    undo_log: Vec<UndoLogEntry<'tcx>>,
-
-    unification_table: UnificationTable<ty::RegionVid>,
-}
-
 pub struct RegionSnapshot {
     length: usize,
     region_snapshot: unify::Snapshot<ty::RegionVid>,
@@ -245,10 +249,7 @@ impl TaintDirections {
 impl<'tcx> RegionConstraintCollector<'tcx> {
     pub fn new() -> RegionConstraintCollector<'tcx> {
         RegionConstraintCollector {
-            var_origins: Vec::new(),
-            constraints: BTreeMap::new(),
-            verifys: Vec::new(),
-            givens: FxHashSet(),
+            data: RegionConstraintData::default(),
             lubs: FxHashMap(),
             glbs: FxHashMap(),
             skolemization_count: 0,
@@ -258,6 +259,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         }
     }
 
+    /// Once all the constraints have been gathered, extract out the final data.
+    pub fn into_data(self) -> RegionConstraintData<'tcx> {
+        self.data
+    }
+
     fn in_snapshot(&self) -> bool {
         !self.undo_log.is_empty()
     }
@@ -289,8 +295,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         } else {
             (*self.undo_log)[snapshot.length] = CommitedSnapshot;
         }
-        self.unification_table
-            .commit(snapshot.region_snapshot);
+        self.unification_table.commit(snapshot.region_snapshot);
     }
 
     pub fn rollback_to(&mut self, snapshot: RegionSnapshot) {
@@ -304,8 +309,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         let c = self.undo_log.pop().unwrap();
         assert!(c == OpenSnapshot);
         self.skolemization_count = snapshot.skolemization_count;
-        self.unification_table
-            .rollback_to(snapshot.region_snapshot);
+        self.unification_table.rollback_to(snapshot.region_snapshot);
     }
 
     fn rollback_undo_entry(&mut self, undo_entry: UndoLogEntry<'tcx>) {
@@ -317,18 +321,18 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
                 // nothing to do here
             }
             AddVar(vid) => {
-                self.var_origins.pop().unwrap();
-                assert_eq!(self.var_origins.len(), vid.index as usize);
+                self.data.var_origins.pop().unwrap();
+                assert_eq!(self.data.var_origins.len(), vid.index as usize);
             }
             AddConstraint(ref constraint) => {
-                self.constraints.remove(constraint);
+                self.data.constraints.remove(constraint);
             }
             AddVerify(index) => {
-                self.verifys.pop();
-                assert_eq!(self.verifys.len(), index);
+                self.data.verifys.pop();
+                assert_eq!(self.data.verifys.len(), index);
             }
             AddGiven(sub, sup) => {
-                self.givens.remove(&(sub, sup));
+                self.data.givens.remove(&(sub, sup));
             }
             AddCombination(Glb, ref regions) => {
                 self.glbs.remove(regions);
@@ -339,18 +343,11 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         }
     }
 
-    pub fn num_vars(&self) -> u32 {
-        let len = self.var_origins.len();
-        // enforce no overflow
-        assert!(len as u32 as usize == len);
-        len as u32
-    }
-
     pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid {
         let vid = RegionVid {
-            index: self.num_vars(),
+            index: self.data.num_vars(),
         };
-        self.var_origins.push(origin.clone());
+        self.data.var_origins.push(origin.clone());
 
         let u_vid = self.unification_table
             .new_key(unify_key::RegionVidKey { min_vid: vid });
@@ -367,7 +364,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
     }
 
     pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
-        self.var_origins[vid.index as usize].clone()
+        self.data.var_origins[vid.index as usize].clone()
     }
 
     /// Creates a new skolemized region. Skolemized regions are fresh
@@ -523,21 +520,22 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
 
     fn add_constraint(&mut self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
         // cannot add constraints once regions are resolved
-        debug!("RegionConstraintCollector: add_constraint({:?})", constraint);
+        debug!(
+            "RegionConstraintCollector: add_constraint({:?})",
+            constraint
+        );
 
         // never overwrite an existing (constraint, origin) - only insert one if it isn't
         // present in the map yet. This prevents origins from outside the snapshot being
         // replaced with "less informative" origins e.g. during calls to `can_eq`
         let in_snapshot = self.in_snapshot();
         let undo_log = &mut self.undo_log;
-        self.constraints
-            .entry(constraint)
-            .or_insert_with(|| {
-                if in_snapshot {
-                    undo_log.push(AddConstraint(constraint));
-                }
-                origin
-            });
+        self.data.constraints.entry(constraint).or_insert_with(|| {
+            if in_snapshot {
+                undo_log.push(AddConstraint(constraint));
+            }
+            origin
+        });
     }
 
     fn add_verify(&mut self, verify: Verify<'tcx>) {
@@ -552,8 +550,8 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
             _ => {}
         }
 
-        let index = self.verifys.len();
-        self.verifys.push(verify);
+        let index = self.data.verifys.len();
+        self.data.verifys.push(verify);
         if self.in_snapshot() {
             self.undo_log.push(AddVerify(index));
         }
@@ -561,7 +559,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
 
     pub fn add_given(&mut self, sub: Region<'tcx>, sup: ty::RegionVid) {
         // cannot add givens once regions are resolved
-        if self.givens.insert((sub, sup)) {
+        if self.data.givens.insert((sub, sup)) {
             debug!("add_given({:?} <= {:?})", sub, sup);
 
             self.undo_log.push(AddGiven(sub, sup));
@@ -767,11 +765,7 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         // edges and add any new regions we find to result_set.  This
         // is not a terribly efficient implementation.
         let mut taint_set = taint::TaintSet::new(directions, r0);
-        taint_set.fixed_point(
-            tcx,
-            &self.undo_log[mark.length..],
-            &self.verifys,
-        );
+        taint_set.fixed_point(tcx, &self.undo_log[mark.length..], &self.data.verifys);
         debug!("tainted: result={:?}", taint_set);
         return taint_set.into_set();
     }
@@ -866,3 +860,12 @@ impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
         }
     }
 }
+
+impl<'tcx> RegionConstraintData<'tcx> {
+    pub fn num_vars(&self) -> u32 {
+        let len = self.var_origins.len();
+        // enforce no overflow
+        assert!(len as u32 as usize == len);
+        len as u32
+    }
+}