]> git.lizzy.rs Git - rust.git/commitdiff
extract storage of region values from `RegionVarBindings`
authorNiko Matsakis <niko@alum.mit.edu>
Sun, 5 Nov 2017 10:48:16 +0000 (05:48 -0500)
committerNiko Matsakis <niko@alum.mit.edu>
Thu, 16 Nov 2017 10:57:42 +0000 (05:57 -0500)
src/librustc/infer/lexical_region_resolve/mod.rs
src/librustc/infer/mod.rs
src/librustc/infer/region_inference/mod.rs
src/librustc/infer/resolve.rs
src/librustc/lib.rs

index 217387befd89fa41f1241e0e394d00b6f604ea55..7dbb5b1ff11ae59942f723d62d34c1ef39b971c2 100644 (file)
 use infer::region_inference::Constraint;
 use infer::region_inference::GenericKind;
 use infer::region_inference::RegionVarBindings;
-use infer::region_inference::VarValue;
 use infer::region_inference::VerifyBound;
 use middle::free_region::RegionRelations;
 use rustc_data_structures::fx::FxHashSet;
 use rustc_data_structures::graph::{self, Direction, NodeIndex, OUTGOING};
 use std::fmt;
 use std::u32;
-use ty::{self, TyCtxt};
+use ty;
 use ty::{Region, RegionVid};
 use ty::{ReEarlyBound, ReEmpty, ReErased, ReFree, ReStatic};
 use ty::{ReLateBound, ReScope, ReSkolemized, ReVar};
 
 mod graphviz;
 
+pub struct LexicalRegionResolutions<'tcx> {
+    values: Vec<VarValue<'tcx>>,
+    error_region: ty::Region<'tcx>,
+}
+
+#[derive(Copy, Clone, Debug)]
+enum VarValue<'tcx> {
+    Value(Region<'tcx>),
+    ErrorValue,
+}
+
 #[derive(Clone, Debug)]
 pub enum RegionResolutionError<'tcx> {
     /// `ConcreteFailure(o, a, b)`:
@@ -72,27 +82,14 @@ impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
     pub fn resolve_regions(
         &self,
         region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
-    ) -> Vec<RegionResolutionError<'tcx>> {
+    ) -> (
+        LexicalRegionResolutions<'tcx>,
+        Vec<RegionResolutionError<'tcx>>,
+    ) {
         debug!("RegionVarBindings: resolve_regions()");
         let mut errors = vec![];
-        let v = self.infer_variable_values(region_rels, &mut errors);
-        *self.values.borrow_mut() = Some(v);
-        errors
-    }
-
-    pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
-        match *self.values.borrow() {
-            None => span_bug!(
-                (*self.var_origins.borrow())[rid.index as usize].span(),
-                "attempt to resolve region variable before values have \
-                 been computed!"
-            ),
-            Some(ref values) => {
-                let r = lookup(self.tcx, values, rid);
-                debug!("resolve_var({:?}) = {:?}", rid, r);
-                r
-            }
-        }
+        let values = self.infer_variable_values(region_rels, &mut errors);
+        (values, errors)
     }
 
     fn lub_concrete_regions(
@@ -188,7 +185,7 @@ fn infer_variable_values(
         &self,
         region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
-    ) -> Vec<VarValue<'tcx>> {
+    ) -> LexicalRegionResolutions<'tcx> {
         let mut var_data = self.construct_var_data();
 
         // Dorky hack to cause `dump_constraints` to only get called
@@ -208,10 +205,13 @@ fn infer_variable_values(
         var_data
     }
 
-    fn construct_var_data(&self) -> Vec<VarValue<'tcx>> {
-        (0..self.num_vars() as usize)
-            .map(|_| VarValue::Value(self.tcx.types.re_empty))
-            .collect()
+    fn construct_var_data(&self) -> LexicalRegionResolutions<'tcx> {
+        LexicalRegionResolutions {
+            error_region: self.tcx.types.re_static,
+            values: (0..self.num_vars() as usize)
+                .map(|_| VarValue::Value(self.tcx.types.re_empty))
+                .collect(),
+        }
     }
 
     fn dump_constraints(&self, free_regions: &RegionRelations<'a, 'gcx, 'tcx>) {
@@ -252,19 +252,19 @@ fn expand_givens(&self, graph: &RegionGraph) {
     fn expansion(
         &self,
         region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
-        var_values: &mut [VarValue<'tcx>],
+        var_values: &mut LexicalRegionResolutions<'tcx>,
     ) {
         self.iterate_until_fixed_point("Expansion", |constraint, origin| {
             debug!("expansion: constraint={:?} origin={:?}", constraint, origin);
             match *constraint {
                 Constraint::RegSubVar(a_region, b_vid) => {
-                    let b_data = &mut var_values[b_vid.index as usize];
+                    let b_data = var_values.value_mut(b_vid);
                     self.expand_node(region_rels, a_region, b_vid, b_data)
                 }
-                Constraint::VarSubVar(a_vid, b_vid) => match var_values[a_vid.index as usize] {
+                Constraint::VarSubVar(a_vid, b_vid) => match *var_values.value(a_vid) {
                     VarValue::ErrorValue => false,
                     VarValue::Value(a_region) => {
-                        let b_node = &mut var_values[b_vid.index as usize];
+                        let b_node = var_values.value_mut(b_vid);
                         self.expand_node(region_rels, a_region, b_vid, b_node)
                     }
                 },
@@ -327,7 +327,7 @@ fn expand_node(
     fn collect_errors(
         &self,
         region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
-        var_data: &mut Vec<VarValue<'tcx>>,
+        var_data: &mut LexicalRegionResolutions<'tcx>,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
     ) {
         let constraints = self.constraints.borrow();
@@ -363,7 +363,7 @@ fn collect_errors(
                 }
 
                 Constraint::VarSubReg(a_vid, b_region) => {
-                    let a_data = &mut var_data[a_vid.index as usize];
+                    let a_data = var_data.value_mut(a_vid);
                     debug!("contraction: {:?} == {:?}, {:?}", a_vid, a_data, b_region);
 
                     let a_region = match *a_data {
@@ -391,7 +391,7 @@ fn collect_errors(
 
         for verify in self.verifys.borrow().iter() {
             debug!("collect_errors: verify={:?}", verify);
-            let sub = normalize(self.tcx, var_data, verify.region);
+            let sub = var_data.normalize(verify.region);
 
             // This was an inference variable which didn't get
             // constrained, therefore it can be assume to hold.
@@ -424,7 +424,7 @@ fn collect_errors(
     fn collect_var_errors(
         &self,
         region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
-        var_data: &[VarValue<'tcx>],
+        var_data: &LexicalRegionResolutions<'tcx>,
         graph: &RegionGraph<'tcx>,
         errors: &mut Vec<RegionResolutionError<'tcx>>,
     ) {
@@ -443,8 +443,9 @@ fn collect_var_errors(
         // overlapping locations.
         let mut dup_vec = vec![u32::MAX; self.num_vars() as usize];
 
-        for idx in 0..self.num_vars() as usize {
-            match var_data[idx] {
+        for index in 0..self.num_vars() {
+            let node_vid = RegionVid { index };
+            match var_data.value(node_vid) {
                 VarValue::Value(_) => { /* Inference successful */ }
                 VarValue::ErrorValue => {
                     /* Inference impossible, this value contains
@@ -469,8 +470,6 @@ fn collect_var_errors(
                        that is not used is not a problem, so if this rule
                        starts to create problems we'll have to revisit
                        this portion of the code and think hard about it. =) */
-
-                    let node_vid = RegionVid { index: idx as u32 };
                     self.collect_error_for_expanding_node(
                         region_rels,
                         graph,
@@ -704,28 +703,6 @@ fn iterate_until_fixed_point<F>(&self, tag: &str, mut body: F)
     }
 }
 
-fn normalize<'a, 'gcx, 'tcx>(
-    tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    values: &Vec<VarValue<'tcx>>,
-    r: ty::Region<'tcx>,
-) -> ty::Region<'tcx> {
-    match *r {
-        ty::ReVar(rid) => lookup(tcx, values, rid),
-        _ => r,
-    }
-}
-
-fn lookup<'a, 'gcx, 'tcx>(
-    tcx: TyCtxt<'a, 'gcx, 'tcx>,
-    values: &Vec<VarValue<'tcx>>,
-    rid: ty::RegionVid,
-) -> ty::Region<'tcx> {
-    match values[rid.index as usize] {
-        VarValue::Value(r) => r,
-        VarValue::ErrorValue => tcx.types.re_static, // Previously reported error.
-    }
-}
-
 impl<'tcx> fmt::Debug for RegionAndOrigin<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "RegionAndOrigin({:?},{:?})", self.region, self.origin)
@@ -737,26 +714,47 @@ impl<'a, 'gcx, 'tcx> VerifyBound<'tcx> {
     fn is_met(
         &self,
         region_rels: &RegionRelations<'a, 'gcx, 'tcx>,
-        var_values: &Vec<VarValue<'tcx>>,
+        var_values: &LexicalRegionResolutions<'tcx>,
         min: ty::Region<'tcx>,
     ) -> bool {
-        let tcx = region_rels.tcx;
         match self {
-            &VerifyBound::AnyRegion(ref rs) => rs.iter()
-                .map(|&r| normalize(tcx, var_values, r))
+            VerifyBound::AnyRegion(rs) => rs.iter()
+                .map(|&r| var_values.normalize(r))
                 .any(|r| region_rels.is_subregion_of(min, r)),
 
-            &VerifyBound::AllRegions(ref rs) => rs.iter()
-                .map(|&r| normalize(tcx, var_values, r))
+            VerifyBound::AllRegions(rs) => rs.iter()
+                .map(|&r| var_values.normalize(r))
                 .all(|r| region_rels.is_subregion_of(min, r)),
 
-            &VerifyBound::AnyBound(ref bs) => {
-                bs.iter().any(|b| b.is_met(region_rels, var_values, min))
-            }
+            VerifyBound::AnyBound(bs) => bs.iter().any(|b| b.is_met(region_rels, var_values, min)),
 
-            &VerifyBound::AllBounds(ref bs) => {
-                bs.iter().all(|b| b.is_met(region_rels, var_values, min))
-            }
+            VerifyBound::AllBounds(bs) => bs.iter().all(|b| b.is_met(region_rels, var_values, min)),
+        }
+    }
+}
+
+impl<'tcx> LexicalRegionResolutions<'tcx> {
+    fn normalize(&self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
+        match *r {
+            ty::ReVar(rid) => self.resolve_var(rid),
+            _ => r,
         }
     }
+
+    fn value(&self, rid: RegionVid) -> &VarValue<'tcx> {
+        &self.values[rid.index as usize]
+    }
+
+    fn value_mut(&mut self, rid: RegionVid) -> &mut VarValue<'tcx> {
+        &mut self.values[rid.index as usize]
+    }
+
+    pub fn resolve_var(&self, rid: RegionVid) -> ty::Region<'tcx> {
+        let result = match self.values[rid.index as usize] {
+            VarValue::Value(r) => r,
+            VarValue::ErrorValue => self.error_region,
+        };
+        debug!("resolve_var({:?}) = {:?}", rid, result);
+        result
+    }
 }
index cf32113343df39043f2c88260cf757f6c8ab1f53..d50d31d34bb8d945a6a80f60c494134a98c4fe4a 100644 (file)
@@ -42,6 +42,7 @@
 use self::combine::CombineFields;
 use self::higher_ranked::HrMatchResult;
 use self::region_inference::{RegionVarBindings, RegionSnapshot};
+use self::lexical_region_resolve::LexicalRegionResolutions;
 use self::type_variable::TypeVariableOrigin;
 use self::unify_key::ToType;
 
@@ -105,6 +106,9 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // For region variables.
     region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
 
+    // Once region inference is done, the values for each variable.
+    lexical_region_resolutions: RefCell<Option<LexicalRegionResolutions<'tcx>>>,
+
     /// Caches the results of trait selection. This cache is used
     /// for things that have to do with the parameters in scope.
     pub selection_cache: traits::SelectionCache<'tcx>,
@@ -421,6 +425,7 @@ pub fn enter<F, R>(&'tcx mut self, f: F) -> R
             int_unification_table: RefCell::new(UnificationTable::new()),
             float_unification_table: RefCell::new(UnificationTable::new()),
             region_vars: RegionVarBindings::new(tcx),
+            lexical_region_resolutions: RefCell::new(None),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             reported_trait_errors: RefCell::new(FxHashMap()),
@@ -1123,7 +1128,10 @@ pub fn resolve_regions_and_report_errors(&self,
                                                region_context,
                                                region_map,
                                                free_regions);
-        let errors = self.region_vars.resolve_regions(&region_rels);
+        let (lexical_region_resolutions, errors) = self.region_vars.resolve_regions(&region_rels);
+
+        let old_value = self.lexical_region_resolutions.replace(Some(lexical_region_resolutions));
+        assert!(old_value.is_none());
 
         if !self.is_tainted_by_errors() {
             // As a heuristic, just skip reporting region errors
index d5997aa0662f52adaa96c3828ca5afff3a0bfc20..26c206f1b568055e40903cac6b7fc4e7499309a5 100644 (file)
@@ -142,12 +142,6 @@ enum CombineMapType {
     Glb,
 }
 
-#[derive(Copy, Clone, Debug)]
-pub enum VarValue<'tcx> {
-    Value(Region<'tcx>),
-    ErrorValue,
-}
-
 type CombineMap<'tcx> = FxHashMap<TwoRegions<'tcx>, RegionVid>;
 
 pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
@@ -208,10 +202,6 @@ pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     undo_log: RefCell<Vec<UndoLogEntry<'tcx>>>,
 
     unification_table: RefCell<UnificationTable<ty::RegionVid>>,
-
-    /// This contains the results of inference.  It begins as an empty
-    /// option and only acquires a value after inference is complete.
-    pub(in infer) values: RefCell<Option<Vec<VarValue<'tcx>>>>,
 }
 
 pub struct RegionSnapshot {
@@ -250,7 +240,6 @@ pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> RegionVarBindings<'a, 'gcx, 'tcx> {
         RegionVarBindings {
             tcx,
             var_origins: RefCell::new(Vec::new()),
-            values: RefCell::new(None),
             constraints: RefCell::new(BTreeMap::new()),
             verifys: RefCell::new(Vec::new()),
             givens: RefCell::new(FxHashSet()),
@@ -517,14 +506,8 @@ pub fn new_bound(&self, debruijn: ty::DebruijnIndex) -> Region<'tcx> {
         self.tcx.mk_region(ReLateBound(debruijn, BrFresh(sc)))
     }
 
-    fn values_are_none(&self) -> bool {
-        self.values.borrow().is_none()
-    }
-
     fn add_constraint(&self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'tcx>) {
         // cannot add constraints once regions are resolved
-        assert!(self.values_are_none());
-
         debug!("RegionVarBindings: add_constraint({:?})", constraint);
 
         // never overwrite an existing (constraint, origin) - only insert one if it isn't
@@ -540,8 +523,6 @@ fn add_constraint(&self, constraint: Constraint<'tcx>, origin: SubregionOrigin<'
 
     fn add_verify(&self, verify: Verify<'tcx>) {
         // cannot add verifys once regions are resolved
-        assert!(self.values_are_none());
-
         debug!("RegionVarBindings: add_verify({:?})", verify);
 
         // skip no-op cases known to be satisfied
@@ -560,8 +541,6 @@ fn add_verify(&self, verify: Verify<'tcx>) {
 
     pub fn add_given(&self, sub: Region<'tcx>, sup: ty::RegionVid) {
         // cannot add givens once regions are resolved
-        assert!(self.values_are_none());
-
         let mut givens = self.givens.borrow_mut();
         if givens.insert((sub, sup)) {
             debug!("add_given({:?} <= {:?})", sub, sup);
@@ -591,8 +570,6 @@ pub fn make_subregion(&self,
                           sub: Region<'tcx>,
                           sup: Region<'tcx>) {
         // cannot add constraints once regions are resolved
-        assert!(self.values_are_none());
-
         debug!("RegionVarBindings: make_subregion({:?}, {:?}) due to {:?}",
                sub,
                sup,
@@ -644,8 +621,6 @@ pub fn lub_regions(&self,
                        b: Region<'tcx>)
                        -> Region<'tcx> {
         // cannot add constraints once regions are resolved
-        assert!(self.values_are_none());
-
         debug!("RegionVarBindings: lub_regions({:?}, {:?})", a, b);
         match (a, b) {
             (r @ &ReStatic, _) | (_, r @ &ReStatic) => {
@@ -670,8 +645,6 @@ pub fn glb_regions(&self,
                        b: Region<'tcx>)
                        -> Region<'tcx> {
         // cannot add constraints once regions are resolved
-        assert!(self.values_are_none());
-
         debug!("RegionVarBindings: glb_regions({:?}, {:?})", a, b);
         match (a, b) {
             (&ReStatic, r) | (r, &ReStatic) => {
index 10899e42afb819b74ad124db8506ca87a939f930..f01be0cd9e4a9b574ab6ce7b40854baae98a7989 100644 (file)
@@ -185,7 +185,11 @@ fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
         match *r {
-            ty::ReVar(rid) => self.infcx.region_vars.resolve_var(rid),
+            ty::ReVar(rid) => self.infcx.lexical_region_resolutions
+                                        .borrow()
+                                        .as_ref()
+                                        .expect("region resolution not performed")
+                                        .resolve_var(rid),
             _ => r,
         }
     }
index 498e1aa3520d5bf45489fe352637a4de51aa2c24..31c09c4cd5756146443952b4cf62890eaa438893 100644 (file)
 #![feature(const_fn)]
 #![feature(core_intrinsics)]
 #![feature(i128_type)]
+#![feature(match_default_bindings)]
 #![feature(inclusive_range_syntax)]
 #![cfg_attr(windows, feature(libc))]
 #![feature(macro_vis_matcher)]
 #![feature(never_type)]
 #![feature(nonzero)]
 #![feature(quote)]
+#![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(slice_patterns)]
 #![feature(specialization)]