]> git.lizzy.rs Git - rust.git/commitdiff
make `RegionVid` implement `Idx` and use `IndexVec`
authorNiko Matsakis <niko@alum.mit.edu>
Sun, 5 Nov 2017 19:06:46 +0000 (14:06 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 16 Nov 2017 10:57:44 +0000 (05:57 -0500)
src/librustc/infer/lexical_region_resolve/mod.rs
src/librustc/infer/region_constraints/mod.rs
src/librustc/ty/sty.rs
src/librustc_data_structures/indexed_vec.rs

index 3522420a5dc135c68debb63b86fb7f65c1d75203..3aeecaf166ac6d66815048b3178343579bfe48bb 100644 (file)
@@ -17,6 +17,7 @@
 use infer::region_constraints::RegionConstraintData;
 use infer::region_constraints::VerifyBound;
 use middle::free_region::RegionRelations;
+use rustc_data_structures::indexed_vec::{Idx, IndexVec};
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING};
 use std::fmt;
@@ -29,7 +30,7 @@
 mod graphviz;
 
 pub struct LexicalRegionResolutions<'tcx> {
-    values: Vec<VarValue<'tcx>>,
+    values: IndexVec<RegionVid, VarValue<'tcx>>,
     error_region: ty::Region<'tcx>,
 }
 
@@ -114,7 +115,7 @@ fn lub_concrete_regions(
 
             (&ReVar(v_id), _) | (_, &ReVar(v_id)) => {
                 span_bug!(
-                    self.var_origins[v_id.index as usize].span(),
+                    self.var_origins[v_id].span(),
                     "lub_concrete_regions invoked with non-concrete \
                      regions: {:?}, {:?}",
                     a,
@@ -211,7 +212,7 @@ fn infer_variable_values(
     fn construct_var_data(&self, tcx: TyCtxt<'_, '_, 'tcx>) -> LexicalRegionResolutions<'tcx> {
         LexicalRegionResolutions {
             error_region: tcx.types.re_static,
-            values: (0..self.num_vars() as usize)
+            values: (0..self.num_vars())
                 .map(|_| VarValue::Value(tcx.types.re_empty))
                 .collect(),
         }
@@ -240,11 +241,20 @@ fn expand_givens(&mut self, graph: &RegionGraph) {
 
         let seeds: Vec<_> = self.givens.iter().cloned().collect();
         for (r, vid) in seeds {
+
+            // While all things transitively reachable in the graph
+            // from the variable (`'0` in the example above).
             let seed_index = NodeIndex(vid.index as usize);
             for succ_index in graph.depth_traverse(seed_index, OUTGOING) {
-                let succ_index = succ_index.0 as u32;
+                let succ_index = succ_index.0;
+
+                // The first N nodes correspond to the region
+                // variables. Other nodes correspond to constant
+                // regions.
                 if succ_index < self.num_vars() {
-                    let succ_vid = RegionVid { index: succ_index };
+                    let succ_vid = RegionVid::new(succ_index);
+
+                    // Add `'c <= '1`.
                     self.givens.insert((r, succ_vid));
                 }
             }
@@ -442,11 +452,10 @@ fn collect_var_errors(
         // idea is to report errors that derive from independent
         // regions of the graph, but not those that derive from
         // overlapping locations.
-        let mut dup_vec = vec![u32::MAX; self.num_vars() as usize];
+        let mut dup_vec = vec![u32::MAX; self.num_vars()];
 
-        for index in 0..self.num_vars() {
-            let node_vid = RegionVid { index };
-            match var_data.value(node_vid) {
+        for (node_vid, value) in var_data.values.iter_enumerated() {
+            match *value {
                 VarValue::Value(_) => { /* Inference successful */ }
                 VarValue::ErrorValue => {
                     /* Inference impossible, this value contains
@@ -560,7 +569,7 @@ fn region_order_key(x: &RegionAndOrigin) -> u8 {
         for lower_bound in &lower_bounds {
             for upper_bound in &upper_bounds {
                 if !region_rels.is_subregion_of(lower_bound.region, upper_bound.region) {
-                    let origin = self.var_origins[node_idx.index as usize].clone();
+                    let origin = self.var_origins[node_idx].clone();
                     debug!(
                         "region inference error at {:?} for {:?}: SubSupConflict sub: {:?} \
                          sup: {:?}",
@@ -582,7 +591,7 @@ fn region_order_key(x: &RegionAndOrigin) -> u8 {
         }
 
         span_bug!(
-            self.var_origins[node_idx.index as usize].span(),
+            self.var_origins[node_idx].span(),
             "collect_error_for_expanding_node() could not find \
              error for var {:?}, lower_bounds={:?}, \
              upper_bounds={:?}",
@@ -741,15 +750,15 @@ fn normalize(&self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
     }
 
     fn value(&self, rid: RegionVid) -> &VarValue<'tcx> {
-        &self.values[rid.index as usize]
+        &self.values[rid]
     }
 
     fn value_mut(&mut self, rid: RegionVid) -> &mut VarValue<'tcx> {
-        &mut self.values[rid.index as usize]
+        &mut self.values[rid]
     }
 
     pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
-        let result = match self.values[rid.index as usize] {
+        let result = match self.values[rid] {
             VarValue::Value(r) => r,
             VarValue::ErrorValue => self.error_region,
         };
index d2cd52c73e2c88c9c07655bc882f1d09664a0460..634e4642600681bedf7a396653c2801c8fc6551d 100644 (file)
@@ -16,6 +16,7 @@
 use super::{MiscVariable, RegionVariableOrigin, SubregionOrigin};
 use super::unify_key;
 
+use rustc_data_structures::indexed_vec::IndexVec;
 use rustc_data_structures::fx::{FxHashMap, FxHashSet};
 use rustc_data_structures::unify::{self, UnificationTable};
 use ty::{self, Ty, TyCtxt};
@@ -51,6 +52,8 @@ pub struct RegionConstraintCollector<'tcx> {
     unification_table: UnificationTable<ty::RegionVid>,
 }
 
+pub type VarOrigins = IndexVec<RegionVid, RegionVariableOrigin>;
+
 /// 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
@@ -58,7 +61,7 @@ pub struct RegionConstraintCollector<'tcx> {
 #[derive(Default)]
 pub struct RegionConstraintData<'tcx> {
     /// For each `RegionVid`, the corresponding `RegionVariableOrigin`.
-    pub var_origins: Vec<RegionVariableOrigin>,
+    pub var_origins: IndexVec<RegionVid, RegionVariableOrigin>,
 
     /// Constraints of the form `A <= B`, where either `A` or `B` can
     /// be a region variable (or neither, as it happens).
@@ -344,10 +347,7 @@ fn rollback_undo_entry(&mut self, undo_entry: UndoLogEntry<'tcx>) {
     }
 
     pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid {
-        let vid = RegionVid {
-            index: self.data.num_vars(),
-        };
-        self.data.var_origins.push(origin.clone());
+        let vid = self.data.var_origins.push(origin.clone());
 
         let u_vid = self.unification_table
             .new_key(unify_key::RegionVidKey { min_vid: vid });
@@ -364,7 +364,7 @@ pub fn new_region_var(&mut self, origin: RegionVariableOrigin) -> RegionVid {
     }
 
     pub fn var_origin(&self, vid: RegionVid) -> RegionVariableOrigin {
-        self.data.var_origins[vid.index as usize].clone()
+        self.data.var_origins[vid].clone()
     }
 
     /// Creates a new skolemized region. Skolemized regions are fresh
@@ -862,10 +862,7 @@ pub fn and(self, vb: VerifyBound<'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
+    pub fn num_vars(&self) -> usize {
+        self.var_origins.len()
     }
 }
index a60cad0de9f76b32fdbb9cc09097816c385bb6a6..a73b234ffbea4ab12d25d3006579f2d6e9c2cca6 100644 (file)
@@ -14,6 +14,7 @@
 
 use middle::const_val::ConstVal;
 use middle::region;
+use rustc_data_structures::indexed_vec::Idx;
 use ty::subst::{Substs, Subst};
 use ty::{self, AdtDef, TypeFlags, Ty, TyCtxt, TypeFoldable};
 use ty::{Slice, TyS};
@@ -898,6 +899,18 @@ pub struct RegionVid {
     pub index: u32,
 }
 
+// TODO after rebasing, should be able to use `newtype_index!`
+impl Idx for RegionVid {
+    fn new(value: usize) -> Self {
+        assert!(value < ::std::u32::MAX as usize);
+        RegionVid { index: value as u32 }
+    }
+
+    fn index(self) -> usize {
+        self.index as usize
+    }
+}
+
 #[derive(Clone, Copy, PartialEq, Eq, Hash, RustcEncodable, RustcDecodable, PartialOrd, Ord)]
 pub struct SkolemizedRegionVid {
     pub index: u32,
index a733e9de5a1ab0df6fc58bbf055e4283ac4be063..622e8c51bee9d2fb13d1debe0903a806307a05ec 100644 (file)
@@ -384,6 +384,11 @@ pub fn push(&mut self, d: T) -> I {
         idx
     }
 
+    #[inline]
+    pub fn pop(&mut self) -> Option<T> {
+        self.raw.pop()
+    }
+
     #[inline]
     pub fn len(&self) -> usize {
         self.raw.len()