about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--Cargo.lock11
-rw-r--r--src/librustc/infer/canonical/mod.rs4
-rw-r--r--src/librustc/infer/fudge.rs143
-rw-r--r--src/librustc/infer/mod.rs12
-rw-r--r--src/librustc/infer/region_constraints/mod.rs16
-rw-r--r--src/librustc/infer/type_variable.rs33
-rw-r--r--src/librustc/lib.rs1
-rw-r--r--src/librustc_data_structures/Cargo.toml2
-rw-r--r--src/librustc_typeck/check/mod.rs10
9 files changed, 132 insertions, 100 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 7fd39bd1f6e..73adb762e48 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -781,6 +781,14 @@ dependencies = [
 ]
 
 [[package]]
+name = "ena"
+version = "0.13.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+dependencies = [
+ "log 0.4.6 (registry+https://github.com/rust-lang/crates.io-index)",
+]
+
+[[package]]
 name = "env_logger"
 version = "0.5.13"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2662,7 +2670,7 @@ name = "rustc_data_structures"
 version = "0.0.0"
 dependencies = [
  "cfg-if 0.1.6 (registry+https://github.com/rust-lang/crates.io-index)",
- "ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)",
+ "ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)",
  "graphviz 0.0.0",
  "jobserver 0.1.12 (registry+https://github.com/rust-lang/crates.io-index)",
  "lazy_static 1.2.0 (registry+https://github.com/rust-lang/crates.io-index)",
@@ -4043,6 +4051,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
 "checksum either 1.5.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3be565ca5c557d7f59e7cfcf1844f9e3033650c929c6566f511e8005f205c1d0"
 "checksum elasticlunr-rs 2.3.4 (registry+https://github.com/rust-lang/crates.io-index)" = "a99a310cd1f9770e7bf8e48810c7bcbb0e078c8fb23a8c7bcf0da4c2bf61a455"
 "checksum ena 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "f56c93cc076508c549d9bb747f79aa9b4eb098be7b8cad8830c3137ef52d1e00"
+"checksum ena 0.13.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3dc01d68e08ca384955a3aeba9217102ca1aa85b6e168639bf27739f1d749d87"
 "checksum env_logger 0.5.13 (registry+https://github.com/rust-lang/crates.io-index)" = "15b0a4d2e39f8420210be8b27eeda28029729e2fd4291019455016c348240c38"
 "checksum env_logger 0.6.0 (registry+https://github.com/rust-lang/crates.io-index)" = "afb070faf94c85d17d50ca44f6ad076bce18ae92f0037d350947240a36e9d42e"
 "checksum error-chain 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff511d5dc435d703f4971bc399647c9bc38e20cb41452e3b9feb4765419ed3f3"
diff --git a/src/librustc/infer/canonical/mod.rs b/src/librustc/infer/canonical/mod.rs
index 95fdd6f01e2..39b84fabff6 100644
--- a/src/librustc/infer/canonical/mod.rs
+++ b/src/librustc/infer/canonical/mod.rs
@@ -360,9 +360,9 @@ impl<'cx, 'gcx, 'tcx> InferCtxt<'cx, 'gcx, 'tcx> {
                         )
                     }
 
-                    CanonicalTyVarKind::Int => self.tcx.mk_int_var(self.next_int_var_id()),
+                    CanonicalTyVarKind::Int => self.next_int_var(),
 
-                    CanonicalTyVarKind::Float => self.tcx.mk_float_var(self.next_float_var_id()),
+                    CanonicalTyVarKind::Float => self.next_float_var(),
                 };
                 ty.into()
             }
diff --git a/src/librustc/infer/fudge.rs b/src/librustc/infer/fudge.rs
index 5f6a8802b4d..7788ae2b88f 100644
--- a/src/librustc/infer/fudge.rs
+++ b/src/librustc/infer/fudge.rs
@@ -1,9 +1,11 @@
-use crate::infer::type_variable::TypeVariableMap;
-use crate::ty::{self, Ty, TyCtxt};
+use crate::ty::{self, Ty, TyCtxt, TyVid, IntVid, FloatVid, RegionVid};
 use crate::ty::fold::{TypeFoldable, TypeFolder};
 
 use super::InferCtxt;
 use super::RegionVariableOrigin;
+use super::type_variable::TypeVariableOrigin;
+
+use std::ops::Range;
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// This rather funky routine is used while processing expected
@@ -17,7 +19,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// from `&[u32; 3]` to `&[u32]` and make the users life more
     /// pleasant.
     ///
-    /// The way we do this is using `fudge_regions_if_ok`. What the
+    /// The way we do this is using `fudge_inference_if_ok`. What the
     /// routine actually does is to start a snapshot and execute the
     /// closure `f`. In our example above, what this closure will do
     /// is to unify the expectation (`Option<&[u32]>`) with the actual
@@ -26,7 +28,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// with `&?a [u32]`, where `?a` is a fresh lifetime variable. The
     /// input type (`?T`) is then returned by `f()`.
     ///
-    /// At this point, `fudge_regions_if_ok` will normalize all type
+    /// At this point, `fudge_inference_if_ok` will normalize all type
     /// variables, converting `?T` to `&?a [u32]` and end the
     /// snapshot. The problem is that we can't just return this type
     /// out, because it references the region variable `?a`, and that
@@ -42,36 +44,51 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// regions in question are not particularly important. We will
     /// use the expected types to guide coercions, but we will still
     /// type-check the resulting types from those coercions against
-    /// the actual types (`?T`, `Option<?T`) -- and remember that
+    /// the actual types (`?T`, `Option<?T>`) -- and remember that
     /// after the snapshot is popped, the variable `?T` is no longer
     /// unified.
-    pub fn fudge_regions_if_ok<T, E, F>(&self,
-                                        origin: &RegionVariableOrigin,
-                                        f: F) -> Result<T, E> where
+    pub fn fudge_inference_if_ok<T, E, F>(
+        &self,
+        f: F,
+    ) -> Result<T, E> where
         F: FnOnce() -> Result<T, E>,
         T: TypeFoldable<'tcx>,
     {
-        debug!("fudge_regions_if_ok(origin={:?})", origin);
+        debug!("fudge_inference_if_ok()");
 
-        let (type_variables, region_vars, value) = self.probe(|snapshot| {
+        let (mut fudger, value) = self.probe(|snapshot| {
             match f() {
                 Ok(value) => {
                     let value = self.resolve_type_vars_if_possible(&value);
 
                     // At this point, `value` could in principle refer
-                    // to types/regions that have been created during
+                    // to inference variables that have been created during
                     // the snapshot. Once we exit `probe()`, those are
                     // going to be popped, so we will have to
                     // eliminate any references to them.
 
-                    let type_variables =
-                        self.type_variables.borrow_mut().types_created_since_snapshot(
-                            &snapshot.type_snapshot);
-                    let region_vars =
-                        self.borrow_region_constraints().vars_created_since_snapshot(
-                            &snapshot.region_constraints_snapshot);
+                    let type_vars = self.type_variables.borrow_mut().vars_since_snapshot(
+                        &snapshot.type_snapshot,
+                    );
+                    let int_vars = self.int_unification_table.borrow_mut().vars_since_snapshot(
+                        &snapshot.int_snapshot,
+                    );
+                    let float_vars = self.float_unification_table.borrow_mut().vars_since_snapshot(
+                        &snapshot.float_snapshot,
+                    );
+                    let region_vars = self.borrow_region_constraints().vars_since_snapshot(
+                        &snapshot.region_constraints_snapshot,
+                    );
+
+                    let fudger = InferenceFudger {
+                        infcx: self,
+                        type_vars,
+                        int_vars,
+                        float_vars,
+                        region_vars,
+                    };
 
-                    Ok((type_variables, region_vars, value))
+                    Ok((fudger, value))
                 }
                 Err(e) => Err(e),
             }
@@ -84,29 +101,26 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
         // Micro-optimization: if no variables have been created, then
         // `value` can't refer to any of them. =) So we can just return it.
-        if type_variables.is_empty() && region_vars.is_empty() {
-            return Ok(value);
+        if fudger.type_vars.0.is_empty() &&
+            fudger.int_vars.is_empty() &&
+            fudger.float_vars.is_empty() &&
+            fudger.region_vars.0.is_empty() {
+            Ok(value)
+        } else {
+            Ok(value.fold_with(&mut fudger))
         }
-
-        let mut fudger = RegionFudger {
-            infcx: self,
-            type_variables: &type_variables,
-            region_vars: &region_vars,
-            origin,
-        };
-
-        Ok(value.fold_with(&mut fudger))
     }
 }
 
-pub struct RegionFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+pub struct InferenceFudger<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
-    type_variables: &'a TypeVariableMap,
-    region_vars: &'a Vec<ty::RegionVid>,
-    origin: &'a RegionVariableOrigin,
+    type_vars: (Range<TyVid>, Vec<TypeVariableOrigin>),
+    int_vars: Range<IntVid>,
+    float_vars: Range<FloatVid>,
+    region_vars: (Range<RegionVid>, Vec<RegionVariableOrigin>),
 }
 
-impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for InferenceFudger<'a, 'gcx, 'tcx> {
     fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> {
         self.infcx.tcx
     }
@@ -114,25 +128,36 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> {
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         match ty.sty {
             ty::Infer(ty::InferTy::TyVar(vid)) => {
-                match self.type_variables.get(&vid) {
-                    None => {
-                        // This variable was created before the
-                        // "fudging".  Since we refresh all type
-                        // variables to their binding anyhow, we know
-                        // that it is unbound, so we can just return
-                        // it.
-                        debug_assert!(self.infcx.type_variables.borrow_mut()
-                                      .probe(vid)
-                                      .is_unknown());
-                        ty
-                    }
-
-                    Some(&origin) => {
-                        // This variable was created during the
-                        // fudging. Recreate it with a fresh variable
-                        // here.
-                        self.infcx.next_ty_var(origin)
-                    }
+                if self.type_vars.0.contains(&vid) {
+                    // This variable was created during the fudging.
+                    // Recreate it with a fresh variable here.
+                    let idx = (vid.index - self.type_vars.0.start.index) as usize;
+                    let origin = self.type_vars.1[idx];
+                    self.infcx.next_ty_var(origin)
+                } else {
+                    // This variable was created before the
+                    // "fudging". Since we refresh all type
+                    // variables to their binding anyhow, we know
+                    // that it is unbound, so we can just return
+                    // it.
+                    debug_assert!(self.infcx.type_variables.borrow_mut()
+                                  .probe(vid)
+                                  .is_unknown());
+                    ty
+                }
+            }
+            ty::Infer(ty::InferTy::IntVar(vid)) => {
+                if self.int_vars.contains(&vid) {
+                    self.infcx.next_int_var()
+                } else {
+                    ty
+                }
+            }
+            ty::Infer(ty::InferTy::FloatVar(vid)) => {
+                if self.float_vars.contains(&vid) {
+                    self.infcx.next_float_var()
+                } else {
+                    ty
                 }
             }
             _ => ty.super_fold_with(self),
@@ -140,13 +165,13 @@ impl<'a, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for RegionFudger<'a, 'gcx, 'tcx> {
     }
 
     fn fold_region(&mut self, r: ty::Region<'tcx>) -> ty::Region<'tcx> {
-        match *r {
-            ty::ReVar(v) if self.region_vars.contains(&v) => {
-                self.infcx.next_region_var(self.origin.clone())
-            }
-            _ => {
-                r
+        if let ty::ReVar(vid) = r {
+            if self.region_vars.0.contains(&vid) {
+                let idx = (vid.index() - self.region_vars.0.start.index()) as usize;
+                let origin = self.region_vars.1[idx];
+                return self.infcx.next_region_var(origin);
             }
         }
+        r
     }
 }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index cc1c439f3bd..16140d006bf 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -999,14 +999,22 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.tcx.mk_ty_var(self.next_ty_var_id(true, origin))
     }
 
-    pub fn next_int_var_id(&self) -> IntVid {
+    fn next_int_var_id(&self) -> IntVid {
         self.int_unification_table.borrow_mut().new_key(None)
     }
 
-    pub fn next_float_var_id(&self) -> FloatVid {
+    pub fn next_int_var(&self) -> Ty<'tcx> {
+        self.tcx.mk_int_var(self.next_int_var_id())
+    }
+
+    fn next_float_var_id(&self) -> FloatVid {
         self.float_unification_table.borrow_mut().new_key(None)
     }
 
+    pub fn next_float_var(&self) -> Ty<'tcx> {
+        self.tcx.mk_float_var(self.next_float_var_id())
+    }
+
     /// Creates a fresh region variable with the next available index.
     /// The variable will be created in the maximum universe created
     /// thus far, allowing it to name any region created thus far.
diff --git a/src/librustc/infer/region_constraints/mod.rs b/src/librustc/infer/region_constraints/mod.rs
index 8389f0ab1aa..6a20d95cc3a 100644
--- a/src/librustc/infer/region_constraints/mod.rs
+++ b/src/librustc/infer/region_constraints/mod.rs
@@ -16,6 +16,7 @@ use crate::ty::{Region, RegionVid};
 
 use std::collections::BTreeMap;
 use std::{cmp, fmt, mem, u32};
+use std::ops::Range;
 
 mod leak_check;
 
@@ -840,13 +841,14 @@ impl<'tcx> RegionConstraintCollector<'tcx> {
         }
     }
 
-    pub fn vars_created_since_snapshot(&self, mark: &RegionSnapshot) -> Vec<RegionVid> {
-        self.undo_log[mark.length..]
-            .iter()
-            .filter_map(|&elt| match elt {
-                AddVar(vid) => Some(vid),
-                _ => None,
-            }).collect()
+    pub fn vars_since_snapshot(
+        &self,
+        mark: &RegionSnapshot,
+    ) -> (Range<RegionVid>, Vec<RegionVariableOrigin>) {
+        let range = self.unification_table.vars_since_snapshot(&mark.region_snapshot);
+        (range.clone(), (range.start.index()..range.end.index()).map(|index| {
+            self.var_infos[ty::RegionVid::from(index)].origin.clone()
+        }).collect())
     }
 
     /// See [`RegionInference::region_constraints_added_in_snapshot`].
diff --git a/src/librustc/infer/type_variable.rs b/src/librustc/infer/type_variable.rs
index 4c76818346b..8a719ff2bf3 100644
--- a/src/librustc/infer/type_variable.rs
+++ b/src/librustc/infer/type_variable.rs
@@ -1,11 +1,11 @@
 use syntax::symbol::InternedString;
 use syntax_pos::Span;
-use crate::ty::{self, Ty};
+use crate::ty::{self, Ty, TyVid};
 
 use std::cmp;
 use std::marker::PhantomData;
 use std::u32;
-use rustc_data_structures::fx::FxHashMap;
+use std::ops::Range;
 use rustc_data_structures::snapshot_vec as sv;
 use rustc_data_structures::unify as ut;
 
@@ -58,8 +58,6 @@ pub enum TypeVariableOrigin {
     Generalized(ty::TyVid),
 }
 
-pub type TypeVariableMap = FxHashMap<ty::TyVid, TypeVariableOrigin>;
-
 struct TypeVariableData {
     origin: TypeVariableOrigin,
     diverging: bool,
@@ -292,24 +290,15 @@ impl<'tcx> TypeVariableTable<'tcx> {
         self.sub_relations.commit(sub_snapshot);
     }
 
-    /// Returns a map `{V1 -> V2}`, where the keys `{V1}` are
-    /// ty-variables created during the snapshot, and the values
-    /// `{V2}` are the root variables that they were unified with,
-    /// along with their origin.
-    pub fn types_created_since_snapshot(&mut self, s: &Snapshot<'tcx>) -> TypeVariableMap {
-        let actions_since_snapshot = self.values.actions_since_snapshot(&s.snapshot);
-
-        actions_since_snapshot
-            .iter()
-            .filter_map(|action| match action {
-                &sv::UndoLog::NewElem(index) => Some(ty::TyVid { index: index as u32 }),
-                _ => None,
-            })
-            .map(|vid| {
-                let origin = self.values.get(vid.index as usize).origin.clone();
-                (vid, origin)
-            })
-            .collect()
+    /// Returns a range of the type variables created during the snapshot.
+    pub fn vars_since_snapshot(
+        &mut self,
+        s: &Snapshot<'tcx>,
+    ) -> (Range<TyVid>, Vec<TypeVariableOrigin>) {
+        let range = self.eq_relations.vars_since_snapshot(&s.eq_snapshot);
+        (range.start.vid..range.end.vid, (range.start.vid.index..range.end.vid.index).map(|index| {
+            self.values.get(index as usize).origin.clone()
+        }).collect())
     }
 
     /// Finds the set of type variables that existed *before* `s`
diff --git a/src/librustc/lib.rs b/src/librustc/lib.rs
index 4b2fda3b02f..e905c368851 100644
--- a/src/librustc/lib.rs
+++ b/src/librustc/lib.rs
@@ -44,6 +44,7 @@
 #![feature(non_exhaustive)]
 #![feature(proc_macro_internals)]
 #![feature(optin_builtin_traits)]
+#![feature(range_is_empty)]
 #![feature(refcell_replace_swap)]
 #![feature(rustc_diagnostic_macros)]
 #![feature(rustc_attrs)]
diff --git a/src/librustc_data_structures/Cargo.toml b/src/librustc_data_structures/Cargo.toml
index 6002bf69b70..63e44d82a28 100644
--- a/src/librustc_data_structures/Cargo.toml
+++ b/src/librustc_data_structures/Cargo.toml
@@ -10,7 +10,7 @@ path = "lib.rs"
 crate-type = ["dylib"]
 
 [dependencies]
-ena = "0.11"
+ena = "0.13"
 log = "0.4"
 jobserver_crate = { version = "0.1", package = "jobserver" }
 lazy_static = "1"
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index b11bd9c2408..ec4fc2a3bfb 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -92,7 +92,7 @@ use rustc::hir::intravisit::{self, Visitor, NestedVisitorMap};
 use rustc::hir::itemlikevisit::ItemLikeVisitor;
 use crate::middle::lang_items;
 use crate::namespace::Namespace;
-use rustc::infer::{self, InferCtxt, InferOk, InferResult, RegionVariableOrigin};
+use rustc::infer::{self, InferCtxt, InferOk, InferResult};
 use rustc::infer::canonical::{Canonical, OriginalQueryValues, QueryResponse};
 use rustc_data_structures::indexed_vec::Idx;
 use rustc_data_structures::sync::Lrc;
@@ -3097,8 +3097,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         _ => None
                     }
                 });
-                opt_ty.unwrap_or_else(
-                    || tcx.mk_int_var(self.next_int_var_id()))
+                opt_ty.unwrap_or_else(|| self.next_int_var())
             }
             ast::LitKind::Float(_, t) => tcx.mk_mach_float(t),
             ast::LitKind::FloatUnsuffixed(_) => {
@@ -3108,8 +3107,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
                         _ => None
                     }
                 });
-                opt_ty.unwrap_or_else(
-                    || tcx.mk_float_var(self.next_float_var_id()))
+                opt_ty.unwrap_or_else(|| self.next_float_var())
             }
             ast::LitKind::Bool(_) => tcx.types.bool,
             ast::LitKind::Err(_) => tcx.types.err,
@@ -3231,7 +3229,7 @@ impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
             Some(ret) => ret,
             None => return Vec::new()
         };
-        let expect_args = self.fudge_regions_if_ok(&RegionVariableOrigin::Coercion(call_span), || {
+        let expect_args = self.fudge_inference_if_ok(|| {
             // Attempt to apply a subtyping relationship between the formal
             // return type (likely containing type variables if the function
             // is polymorphic) and the expected return type.