]> git.proxmox.com Git - rustc.git/blobdiff - src/librustc/infer/mod.rs
New upstream version 1.19.0+dfsg1
[rustc.git] / src / librustc / infer / mod.rs
index 4d8b31a33cdef59f12344fe95e94a4da1ce78376..f5869b8a20fab7881529092b132d00fbf5a5d26a 100644 (file)
@@ -20,7 +20,8 @@ pub use self::region_inference::{GenericKind, VerifyBound};
 
 use hir::def_id::DefId;
 use hir;
-use middle::free_region::FreeRegionMap;
+use middle::free_region::{FreeRegionMap, RegionRelations};
+use middle::region::RegionMaps;
 use middle::mem_categorization as mc;
 use middle::mem_categorization::McResult;
 use middle::lang_items;
@@ -30,7 +31,7 @@ use ty::{TyVid, IntVid, FloatVid};
 use ty::{self, Ty, TyCtxt};
 use ty::error::{ExpectedFound, TypeError, UnconstrainedNumeric};
 use ty::fold::{TypeFoldable, TypeFolder, TypeVisitor};
-use ty::relate::{Relate, RelateResult, TypeRelation};
+use ty::relate::RelateResult;
 use traits::{self, ObligationCause, PredicateObligations, Reveal};
 use rustc_data_structures::unify::{self, UnificationTable};
 use std::cell::{Cell, RefCell, Ref, RefMut};
@@ -48,6 +49,7 @@ use self::region_inference::{RegionVarBindings, RegionSnapshot};
 use self::type_variable::TypeVariableOrigin;
 use self::unify_key::ToType;
 
+pub mod at;
 mod combine;
 mod equate;
 pub mod error_reporting;
@@ -160,8 +162,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // For region variables.
     region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
 
-    pub parameter_environment: ty::ParameterEnvironment<'gcx>,
-
     /// 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>,
@@ -173,11 +173,6 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // avoid reporting the same error twice.
     pub reported_trait_errors: RefCell<FxHashSet<traits::TraitErrorKey<'tcx>>>,
 
-    // Sadly, the behavior of projection varies a bit depending on the
-    // stage of compilation. The specifics are given in the
-    // documentation for `Reveal`.
-    projection_mode: Reveal,
-
     // When an error occurs, we want to avoid reporting "derived"
     // errors that are due to this original failure. Normally, we
     // handle this with the `err_count_on_creation` count, which
@@ -205,7 +200,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
 
 /// A map returned by `skolemize_late_bound_regions()` indicating the skolemized
 /// region that each late-bound region was replaced with.
-pub type SkolemizationMap<'tcx> = FxHashMap<ty::BoundRegion, &'tcx ty::Region>;
+pub type SkolemizationMap<'tcx> = FxHashMap<ty::BoundRegion, ty::Region<'tcx>>;
 
 /// See `error_reporting` module for more details
 #[derive(Clone, Debug)]
@@ -404,55 +399,39 @@ impl fmt::Display for FixupError {
 pub trait InferEnv<'a, 'tcx> {
     fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
-                    Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>);
+                    Option<ty::TypeckTables<'tcx>>);
 }
 
 impl<'a, 'tcx> InferEnv<'a, 'tcx> for () {
     fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
-                    Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
-        (None, None, None)
-    }
-}
-
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::ParameterEnvironment<'tcx> {
-    fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
-                -> (Option<&'a ty::TypeckTables<'tcx>>,
-                    Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
-        (None, None, Some(self))
+                    Option<ty::TypeckTables<'tcx>>) {
+        (None, None)
     }
 }
 
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for (&'a ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for &'a ty::TypeckTables<'tcx> {
     fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
-                    Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
-        (Some(self.0), None, Some(self.1))
+                    Option<ty::TypeckTables<'tcx>>) {
+        (Some(self), None)
     }
 }
 
-impl<'a, 'tcx> InferEnv<'a, 'tcx> for (ty::TypeckTables<'tcx>, ty::ParameterEnvironment<'tcx>) {
+impl<'a, 'tcx> InferEnv<'a, 'tcx> for ty::TypeckTables<'tcx> {
     fn to_parts(self, _: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
-                    Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
-        (None, Some(self.0), Some(self.1))
+                    Option<ty::TypeckTables<'tcx>>) {
+        (None, Some(self))
     }
 }
 
 impl<'a, 'tcx> InferEnv<'a, 'tcx> for hir::BodyId {
     fn to_parts(self, tcx: TyCtxt<'a, 'tcx, 'tcx>)
                 -> (Option<&'a ty::TypeckTables<'tcx>>,
-                    Option<ty::TypeckTables<'tcx>>,
-                    Option<ty::ParameterEnvironment<'tcx>>) {
-        let item_id = tcx.hir.body_owner(self);
-        (Some(tcx.item_tables(tcx.hir.local_def_id(item_id))),
-         None,
-         Some(ty::ParameterEnvironment::for_item(tcx, item_id)))
+                    Option<ty::TypeckTables<'tcx>>) {
+        let def_id = tcx.hir.body_owner_def_id(self);
+        (Some(tcx.typeck_tables_of(def_id)), None)
     }
 }
 
@@ -464,23 +443,16 @@ pub struct InferCtxtBuilder<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     arena: DroplessArena,
     fresh_tables: Option<RefCell<ty::TypeckTables<'tcx>>>,
     tables: Option<&'a ty::TypeckTables<'gcx>>,
-    param_env: Option<ty::ParameterEnvironment<'gcx>>,
-    projection_mode: Reveal,
 }
 
 impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
-    pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self,
-                                             env: E,
-                                             projection_mode: Reveal)
-                                             -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
-        let (tables, fresh_tables, param_env) = env.to_parts(self);
+    pub fn infer_ctxt<E: InferEnv<'a, 'gcx>>(self, env: E) -> InferCtxtBuilder<'a, 'gcx, 'tcx> {
+        let (tables, fresh_tables) = env.to_parts(self);
         InferCtxtBuilder {
             global_tcx: self,
             arena: DroplessArena::new(),
             fresh_tables: fresh_tables.map(RefCell::new),
             tables: tables,
-            param_env: param_env,
-            projection_mode: projection_mode,
         }
     }
 
@@ -489,7 +461,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
     /// If any inference functionality is used, ICEs will occur.
     pub fn borrowck_fake_infer_ctxt(self, body: hir::BodyId)
                                     -> InferCtxt<'a, 'gcx, 'gcx> {
-        let (tables, _, param_env) = body.to_parts(self);
+        let (tables, _) = body.to_parts(self);
         InferCtxt {
             tcx: self,
             tables: InferTables::Interned(tables.unwrap()),
@@ -497,12 +469,10 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'gcx> {
             int_unification_table: RefCell::new(UnificationTable::new()),
             float_unification_table: RefCell::new(UnificationTable::new()),
             region_vars: RegionVarBindings::new(self),
-            parameter_environment: param_env.unwrap(),
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             projection_cache: RefCell::new(traits::ProjectionCache::new()),
             reported_trait_errors: RefCell::new(FxHashSet()),
-            projection_mode: Reveal::UserFacing,
             tainted_by_errors_flag: Cell::new(false),
             err_count_on_creation: self.sess.err_count(),
             in_snapshot: Cell::new(false),
@@ -519,15 +489,10 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
             ref arena,
             ref fresh_tables,
             tables,
-            ref mut param_env,
-            projection_mode,
         } = *self;
         let tables = tables.map(InferTables::Interned).unwrap_or_else(|| {
             fresh_tables.as_ref().map_or(InferTables::Missing, InferTables::InProgress)
         });
-        let param_env = param_env.take().unwrap_or_else(|| {
-            global_tcx.empty_parameter_environment()
-        });
         global_tcx.enter_local(arena, |tcx| f(InferCtxt {
             tcx: tcx,
             tables: tables,
@@ -536,11 +501,9 @@ impl<'a, 'gcx, 'tcx> InferCtxtBuilder<'a, 'gcx, 'tcx> {
             int_unification_table: RefCell::new(UnificationTable::new()),
             float_unification_table: RefCell::new(UnificationTable::new()),
             region_vars: RegionVarBindings::new(tcx),
-            parameter_environment: param_env,
             selection_cache: traits::SelectionCache::new(),
             evaluation_cache: traits::EvaluationCache::new(),
             reported_trait_errors: RefCell::new(FxHashSet()),
-            projection_mode: projection_mode,
             tainted_by_errors_flag: Cell::new(false),
             err_count_on_creation: tcx.sess.err_count(),
             in_snapshot: Cell::new(false),
@@ -565,19 +528,23 @@ impl<'tcx, T> InferOk<'tcx, T> {
 }
 
 #[must_use = "once you start a snapshot, you should always consume it"]
-pub struct CombinedSnapshot {
+pub struct CombinedSnapshot<'a, 'tcx:'a> {
     projection_cache_snapshot: traits::ProjectionCacheSnapshot,
     type_snapshot: type_variable::Snapshot,
     int_snapshot: unify::Snapshot<ty::IntVid>,
     float_snapshot: unify::Snapshot<ty::FloatVid>,
     region_vars_snapshot: RegionSnapshot,
     was_in_snapshot: bool,
+    _in_progress_tables: Option<Ref<'a, ty::TypeckTables<'tcx>>>,
 }
 
 /// Helper trait for shortening the lifetimes inside a
 /// value for post-type-checking normalization.
 pub trait TransNormalize<'gcx>: TypeFoldable<'gcx> {
-    fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self;
+    fn trans_normalize<'a, 'tcx>(&self,
+                                 infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                                 param_env: ty::ParamEnv<'tcx>)
+                                 -> Self;
 }
 
 macro_rules! items { ($($item:item)+) => ($($item)+) }
@@ -585,9 +552,10 @@ macro_rules! impl_trans_normalize {
     ($lt_gcx:tt, $($ty:ty),+) => {
         items!($(impl<$lt_gcx> TransNormalize<$lt_gcx> for $ty {
             fn trans_normalize<'a, 'tcx>(&self,
-                                         infcx: &InferCtxt<'a, $lt_gcx, 'tcx>)
+                                         infcx: &InferCtxt<'a, $lt_gcx, 'tcx>,
+                                         param_env: ty::ParamEnv<'tcx>)
                                          -> Self {
-                infcx.normalize_projections_in(self)
+                infcx.normalize_projections_in(param_env, self)
             }
         })+);
     }
@@ -604,13 +572,16 @@ impl_trans_normalize!('gcx,
 );
 
 impl<'gcx> TransNormalize<'gcx> for LvalueTy<'gcx> {
-    fn trans_normalize<'a, 'tcx>(&self, infcx: &InferCtxt<'a, 'gcx, 'tcx>) -> Self {
+    fn trans_normalize<'a, 'tcx>(&self,
+                                 infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                                 param_env: ty::ParamEnv<'tcx>)
+                                 -> Self {
         match *self {
-            LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx) },
+            LvalueTy::Ty { ty } => LvalueTy::Ty { ty: ty.trans_normalize(infcx, param_env) },
             LvalueTy::Downcast { adt_def, substs, variant_index } => {
                 LvalueTy::Downcast {
                     adt_def: adt_def,
-                    substs: substs.trans_normalize(infcx),
+                    substs: substs.trans_normalize(infcx, param_env),
                     variant_index: variant_index
                 }
             }
@@ -632,24 +603,32 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
         self.normalize_associated_type(&value)
     }
 
+    /// Fully normalizes any associated types in `value`, using an
+    /// empty environment and `Reveal::All` mode (therefore, suitable
+    /// only for monomorphized code during trans, basically).
     pub fn normalize_associated_type<T>(self, value: &T) -> T
         where T: TransNormalize<'tcx>
     {
         debug!("normalize_associated_type(t={:?})", value);
 
+        let param_env = ty::ParamEnv::empty(Reveal::All);
         let value = self.erase_regions(value);
 
         if !value.has_projection_types() {
             return value;
         }
 
-        self.infer_ctxt((), Reveal::All).enter(|infcx| {
-            value.trans_normalize(&infcx)
+        self.infer_ctxt(()).enter(|infcx| {
+            value.trans_normalize(&infcx, param_env)
         })
     }
 
+    /// Does a best-effort to normalize any associated types in
+    /// `value`; this includes revealing specializable types, so this
+    /// should be not be used during type-checking, but only during
+    /// optimization and code generation.
     pub fn normalize_associated_type_in_env<T>(
-        self, value: &T, env: &'a ty::ParameterEnvironment<'tcx>
+        self, value: &T, env: ty::ParamEnv<'tcx>
     ) -> T
         where T: TransNormalize<'tcx>
     {
@@ -661,20 +640,20 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
             return value;
         }
 
-        self.infer_ctxt(env.clone(), Reveal::All).enter(|infcx| {
-            value.trans_normalize(&infcx)
+        self.infer_ctxt(()).enter(|infcx| {
+            value.trans_normalize(&infcx, env.reveal_all())
        })
     }
 }
 
 impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
-    fn normalize_projections_in<T>(&self, value: &T) -> T::Lifted
+    fn normalize_projections_in<T>(&self, param_env: ty::ParamEnv<'tcx>, value: &T) -> T::Lifted
         where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
     {
         let mut selcx = traits::SelectionContext::new(self);
         let cause = traits::ObligationCause::dummy();
         let traits::Normalized { value: result, obligations } =
-            traits::normalize(&mut selcx, cause, value);
+            traits::normalize(&mut selcx, param_env, cause, value);
 
         debug!("normalize_projections_in: result={:?} obligations={:?}",
                 result, obligations);
@@ -728,10 +707,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         }
     }
 
-    pub fn projection_mode(&self) -> Reveal {
-        self.projection_mode
-    }
-
     pub fn is_in_snapshot(&self) -> bool {
         self.in_snapshot.get()
     }
@@ -817,52 +792,17 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         return variables;
     }
 
-    fn combine_fields(&'a self, trace: TypeTrace<'tcx>)
+    fn combine_fields(&'a self, trace: TypeTrace<'tcx>, param_env: ty::ParamEnv<'tcx>)
                       -> CombineFields<'a, 'gcx, 'tcx> {
         CombineFields {
             infcx: self,
             trace: trace,
             cause: None,
+            param_env,
             obligations: PredicateObligations::new(),
         }
     }
 
-    pub fn equate<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-        -> InferResult<'tcx, T>
-        where T: Relate<'tcx>
-    {
-        let mut fields = self.combine_fields(trace);
-        let result = fields.equate(a_is_expected).relate(a, b);
-        result.map(move |t| InferOk { value: t, obligations: fields.obligations })
-    }
-
-    pub fn sub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-        -> InferResult<'tcx, T>
-        where T: Relate<'tcx>
-    {
-        let mut fields = self.combine_fields(trace);
-        let result = fields.sub(a_is_expected).relate(a, b);
-        result.map(move |t| InferOk { value: t, obligations: fields.obligations })
-    }
-
-    pub fn lub<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-        -> InferResult<'tcx, T>
-        where T: Relate<'tcx>
-    {
-        let mut fields = self.combine_fields(trace);
-        let result = fields.lub(a_is_expected).relate(a, b);
-        result.map(move |t| InferOk { value: t, obligations: fields.obligations })
-    }
-
-    pub fn glb<T>(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>, a: &T, b: &T)
-        -> InferResult<'tcx, T>
-        where T: Relate<'tcx>
-    {
-        let mut fields = self.combine_fields(trace);
-        let result = fields.glb(a_is_expected).relate(a, b);
-        result.map(move |t| InferOk { value: t, obligations: fields.obligations })
-    }
-
     // Clear the "currently in a snapshot" flag, invoke the closure,
     // then restore the flag to its original value. This flag is a
     // debugging measure designed to detect cases where we start a
@@ -889,7 +829,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         result
     }
 
-    fn start_snapshot(&self) -> CombinedSnapshot {
+    fn start_snapshot<'b>(&'b self) -> CombinedSnapshot<'b, 'tcx> {
         debug!("start_snapshot()");
 
         let in_snapshot = self.in_snapshot.get();
@@ -902,6 +842,12 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             float_snapshot: self.float_unification_table.borrow_mut().snapshot(),
             region_vars_snapshot: self.region_vars.start_snapshot(),
             was_in_snapshot: in_snapshot,
+            // Borrow tables "in progress" (i.e. during typeck)
+            // to ban writes from within a snapshot to them.
+            _in_progress_tables: match self.tables {
+                InferTables::InProgress(ref tables) => tables.try_borrow().ok(),
+                _ => None
+            }
         }
     }
 
@@ -912,7 +858,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                int_snapshot,
                                float_snapshot,
                                region_vars_snapshot,
-                               was_in_snapshot } = snapshot;
+                               was_in_snapshot,
+                               _in_progress_tables } = snapshot;
 
         self.in_snapshot.set(was_in_snapshot);
 
@@ -939,7 +886,8 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                                int_snapshot,
                                float_snapshot,
                                region_vars_snapshot,
-                               was_in_snapshot } = snapshot;
+                               was_in_snapshot,
+                               _in_progress_tables } = snapshot;
 
         self.in_snapshot.set(was_in_snapshot);
 
@@ -1008,113 +956,55 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn add_given(&self,
-                     sub: ty::FreeRegion,
+                     sub: ty::Region<'tcx>,
                      sup: ty::RegionVid)
     {
         self.region_vars.add_given(sub, sup);
     }
 
-    pub fn sub_types(&self,
-                     a_is_expected: bool,
-                     cause: &ObligationCause<'tcx>,
-                     a: Ty<'tcx>,
-                     b: Ty<'tcx>)
-        -> InferResult<'tcx, ()>
-    {
-        debug!("sub_types({:?} <: {:?})", a, b);
-        self.commit_if_ok(|_| {
-            let trace = TypeTrace::types(cause, a_is_expected, a, b);
-            self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
-        })
-    }
-
-    pub fn can_sub_types(&self,
-                         a: Ty<'tcx>,
-                         b: Ty<'tcx>)
-                         -> UnitResult<'tcx>
+    pub fn can_sub<T>(&self,
+                      param_env: ty::ParamEnv<'tcx>,
+                      a: T,
+                      b: T)
+                      -> UnitResult<'tcx>
+        where T: at::ToTrace<'tcx>
     {
+        let origin = &ObligationCause::dummy();
         self.probe(|_| {
-            let origin = &ObligationCause::dummy();
-            let trace = TypeTrace::types(origin, true, a, b);
-            self.sub(true, trace, &a, &b).map(|InferOk { obligations: _, .. }| {
+            self.at(origin, param_env).sub(a, b).map(|InferOk { obligations: _, .. }| {
                 // Ignore obligations, since we are unrolling
                 // everything anyway.
             })
         })
     }
 
-    pub fn eq_types(&self,
-                    a_is_expected: bool,
-                    cause: &ObligationCause<'tcx>,
-                    a: Ty<'tcx>,
-                    b: Ty<'tcx>)
-        -> InferResult<'tcx, ()>
+    pub fn can_eq<T>(&self,
+                      param_env: ty::ParamEnv<'tcx>,
+                      a: T,
+                      b: T)
+                      -> UnitResult<'tcx>
+        where T: at::ToTrace<'tcx>
     {
-        self.commit_if_ok(|_| {
-            let trace = TypeTrace::types(cause, a_is_expected, a, b);
-            self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
-        })
-    }
-
-    pub fn eq_trait_refs(&self,
-                          a_is_expected: bool,
-                          cause: &ObligationCause<'tcx>,
-                          a: ty::TraitRef<'tcx>,
-                          b: ty::TraitRef<'tcx>)
-        -> InferResult<'tcx, ()>
-    {
-        debug!("eq_trait_refs({:?} = {:?})", a, b);
-        self.commit_if_ok(|_| {
-            let trace = TypeTrace {
-                cause: cause.clone(),
-                values: TraitRefs(ExpectedFound::new(a_is_expected, a, b))
-            };
-            self.equate(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
-        })
-    }
-
-    pub fn eq_impl_headers(&self,
-                           a_is_expected: bool,
-                           cause: &ObligationCause<'tcx>,
-                           a: &ty::ImplHeader<'tcx>,
-                           b: &ty::ImplHeader<'tcx>)
-                           -> InferResult<'tcx, ()>
-    {
-        debug!("eq_impl_header({:?} = {:?})", a, b);
-        match (a.trait_ref, b.trait_ref) {
-            (Some(a_ref), Some(b_ref)) => self.eq_trait_refs(a_is_expected, cause, a_ref, b_ref),
-            (None, None) => self.eq_types(a_is_expected, cause, a.self_ty, b.self_ty),
-            _ => bug!("mk_eq_impl_headers given mismatched impl kinds"),
-        }
-    }
-
-    pub fn sub_poly_trait_refs(&self,
-                               a_is_expected: bool,
-                               cause: ObligationCause<'tcx>,
-                               a: ty::PolyTraitRef<'tcx>,
-                               b: ty::PolyTraitRef<'tcx>)
-        -> InferResult<'tcx, ()>
-    {
-        debug!("sub_poly_trait_refs({:?} <: {:?})", a, b);
-        self.commit_if_ok(|_| {
-            let trace = TypeTrace {
-                cause: cause,
-                values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b))
-            };
-            self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
+        let origin = &ObligationCause::dummy();
+        self.probe(|_| {
+            self.at(origin, param_env).eq(a, b).map(|InferOk { obligations: _, .. }| {
+                // Ignore obligations, since we are unrolling
+                // everything anyway.
+            })
         })
     }
 
     pub fn sub_regions(&self,
                        origin: SubregionOrigin<'tcx>,
-                       a: &'tcx ty::Region,
-                       b: &'tcx ty::Region) {
+                       a: ty::Region<'tcx>,
+                       b: ty::Region<'tcx>) {
         debug!("sub_regions({:?} <: {:?})", a, b);
         self.region_vars.make_subregion(origin, a, b);
     }
 
     pub fn equality_predicate(&self,
                               cause: &ObligationCause<'tcx>,
+                              param_env: ty::ParamEnv<'tcx>,
                               predicate: &ty::PolyEquatePredicate<'tcx>)
         -> InferResult<'tcx, ()>
     {
@@ -1122,7 +1012,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
             let (ty::EquatePredicate(a, b), skol_map) =
                 self.skolemize_late_bound_regions(predicate, snapshot);
             let cause_span = cause.span;
-            let eqty_ok = self.eq_types(false, cause, a, b)?;
+            let eqty_ok = self.at(cause, param_env).eq(b, a)?;
             self.leak_check(false, cause_span, &skol_map, snapshot)?;
             self.pop_skolemized(skol_map, snapshot);
             Ok(eqty_ok.unit())
@@ -1131,6 +1021,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
 
     pub fn subtype_predicate(&self,
                              cause: &ObligationCause<'tcx>,
+                             param_env: ty::ParamEnv<'tcx>,
                              predicate: &ty::PolySubtypePredicate<'tcx>)
         -> Option<InferResult<'tcx, ()>>
     {
@@ -1159,7 +1050,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 self.skolemize_late_bound_regions(predicate, snapshot);
 
             let cause_span = cause.span;
-            let ok = self.sub_types(a_is_expected, cause, a, b)?;
+            let ok = self.at(cause, param_env).sub_exp(a_is_expected, a, b)?;
             self.leak_check(false, cause_span, &skol_map, snapshot)?;
             self.pop_skolemized(skol_map, snapshot);
             Ok(ok.unit())
@@ -1210,7 +1101,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn next_region_var(&self, origin: RegionVariableOrigin)
-                           -> &'tcx ty::Region {
+                           -> ty::Region<'tcx> {
         self.tcx.mk_region(ty::ReVar(self.region_vars.new_region_var(origin)))
     }
 
@@ -1219,7 +1110,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn region_var_for_def(&self,
                               span: Span,
                               def: &ty::RegionParameterDef)
-                              -> &'tcx ty::Region {
+                              -> ty::Region<'tcx> {
         self.next_region_var(EarlyBoundRegion(span, def.name, def.issue_32330))
     }
 
@@ -1237,7 +1128,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                             substs: &[Kind<'tcx>])
                             -> Ty<'tcx> {
         let default = if def.has_default {
-            let default = self.tcx.item_type(def.def_id);
+            let default = self.tcx.type_of(def.def_id);
             Some(type_variable::Default {
                 ty: default.subst_spanned(self.tcx, substs, Some(span)),
                 origin_span: span,
@@ -1270,7 +1161,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         })
     }
 
-    pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> &'tcx ty::Region {
+    pub fn fresh_bound_region(&self, debruijn: ty::DebruijnIndex) -> ty::Region<'tcx> {
         self.region_vars.new_bound(debruijn)
     }
 
@@ -1322,9 +1213,14 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn resolve_regions_and_report_errors(&self,
-                                             free_regions: &FreeRegionMap,
-                                             subject_node_id: ast::NodeId) {
-        let errors = self.region_vars.resolve_regions(free_regions, subject_node_id);
+                                             region_context: DefId,
+                                             region_map: &RegionMaps,
+                                             free_regions: &FreeRegionMap<'tcx>) {
+        let region_rels = RegionRelations::new(self.tcx,
+                                               region_context,
+                                               region_map,
+                                               free_regions);
+        let errors = self.region_vars.resolve_regions(&region_rels);
         if !self.is_tainted_by_errors() {
             // As a heuristic, just skip reporting region errors
             // altogether if other errors have been reported while
@@ -1531,7 +1427,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         span: Span,
         lbrct: LateBoundRegionConversionTime,
         value: &ty::Binder<T>)
-        -> (T, FxHashMap<ty::BoundRegion, &'tcx ty::Region>)
+        -> (T, FxHashMap<ty::BoundRegion, ty::Region<'tcx>>)
         where T : TypeFoldable<'tcx>
     {
         self.tcx.replace_late_bound_regions(
@@ -1556,6 +1452,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     /// details.
     pub fn match_poly_projection_predicate(&self,
                                            cause: ObligationCause<'tcx>,
+                                           param_env: ty::ParamEnv<'tcx>,
                                            match_a: ty::PolyProjectionPredicate<'tcx>,
                                            match_b: ty::TraitRef<'tcx>)
                                            -> InferResult<'tcx, HrMatchResult<Ty<'tcx>>>
@@ -1568,7 +1465,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         };
 
         let match_pair = match_a.map_bound(|p| (p.projection_ty.trait_ref, p.ty));
-        let mut combine = self.combine_fields(trace);
+        let mut combine = self.combine_fields(trace, param_env);
         let result = combine.higher_ranked_match(span, &match_pair, &match_b, true)?;
         Ok(InferOk { value: result, obligations: combine.obligations })
     }
@@ -1577,7 +1474,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
     pub fn verify_generic_bound(&self,
                                 origin: SubregionOrigin<'tcx>,
                                 kind: GenericKind<'tcx>,
-                                a: &'tcx ty::Region,
+                                a: ty::Region<'tcx>,
                                 bound: VerifyBound<'tcx>) {
         debug!("verify_generic_bound({:?}, {:?} <: {:?})",
                kind,
@@ -1587,27 +1484,6 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.region_vars.verify_generic_bound(origin, kind, a, bound);
     }
 
-    pub fn can_equate<T>(&self, a: &T, b: &T) -> UnitResult<'tcx>
-        where T: Relate<'tcx> + fmt::Debug
-    {
-        debug!("can_equate({:?}, {:?})", a, b);
-        self.probe(|_| {
-            // Gin up a dummy trace, since this won't be committed
-            // anyhow. We should make this typetrace stuff more
-            // generic so we don't have to do anything quite this
-            // terrible.
-            let trace = TypeTrace::dummy(self.tcx);
-            self.equate(true, trace, a, b).map(|InferOk { obligations: _, .. }| {
-                // We can intentionally ignore obligations here, since
-                // this is part of a simple test for general
-                // "equatability". However, it's not entirely clear
-                // that we *ought* to be, perhaps a better thing would
-                // be to use a mini-fulfillment context or something
-                // like that.
-            })
-        })
-    }
-
     pub fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
         let ty = self.node_type(id);
         self.resolve_type_vars_or_error(&ty)
@@ -1618,9 +1494,13 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         self.resolve_type_vars_or_error(&ty)
     }
 
-    pub fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
+    pub fn type_moves_by_default(&self,
+                                 param_env: ty::ParamEnv<'tcx>,
+                                 ty: Ty<'tcx>,
+                                 span: Span)
+                                 -> bool {
         let ty = self.resolve_type_vars_if_possible(&ty);
-        if let Some(ty) = self.tcx.lift_to_global(&ty) {
+        if let Some((param_env, ty)) = self.tcx.lift_to_global(&(param_env, ty)) {
             // Even if the type may have no inference variables, during
             // type-checking closure types are in local tables only.
             let local_closures = match self.tables {
@@ -1628,7 +1508,7 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
                 _ => false
             };
             if !local_closures {
-                return ty.moves_by_default(self.tcx.global_tcx(), self.param_env(), span);
+                return ty.moves_by_default(self.tcx.global_tcx(), param_env, span);
             }
         }
 
@@ -1638,47 +1518,24 @@ impl<'a, 'gcx, 'tcx> InferCtxt<'a, 'gcx, 'tcx> {
         // rightly refuses to work with inference variables, but
         // moves_by_default has a cache, which we want to use in other
         // cases.
-        !traits::type_known_to_meet_bound(self, ty, copy_def_id, span)
-    }
-
-    pub fn node_method_ty(&self, method_call: ty::MethodCall)
-                          -> Option<Ty<'tcx>> {
-        self.tables
-            .borrow()
-            .method_map
-            .get(&method_call)
-            .map(|method| method.ty)
-            .map(|ty| self.resolve_type_vars_if_possible(&ty))
-    }
-
-    pub fn node_method_id(&self, method_call: ty::MethodCall)
-                          -> Option<DefId> {
-        self.tables
-            .borrow()
-            .method_map
-            .get(&method_call)
-            .map(|method| method.def_id)
-    }
-
-    pub fn is_method_call(&self, id: ast::NodeId) -> bool {
-        self.tables.borrow().method_map.contains_key(&ty::MethodCall::expr(id))
+        !traits::type_known_to_meet_bound(self, param_env, ty, copy_def_id, span)
     }
 
     pub fn upvar_capture(&self, upvar_id: ty::UpvarId) -> Option<ty::UpvarCapture<'tcx>> {
         self.tables.borrow().upvar_capture_map.get(&upvar_id).cloned()
     }
 
-    pub fn param_env(&self) -> &ty::ParameterEnvironment<'gcx> {
-        &self.parameter_environment
-    }
-
     pub fn closure_kind(&self,
                         def_id: DefId)
                         -> Option<ty::ClosureKind>
     {
         if let InferTables::InProgress(tables) = self.tables {
             if let Some(id) = self.tcx.hir.as_local_node_id(def_id) {
-                return tables.borrow().closure_kinds.get(&id).cloned();
+                return tables.borrow()
+                             .closure_kinds
+                             .get(&id)
+                             .cloned()
+                             .map(|(kind, _)| kind);
             }
         }