about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-03-17 00:15:31 +0200
committerEduard Burtescu <edy.burt@gmail.com>2016-05-11 04:14:58 +0300
commitf8ea24edc8b663c5acbe252936aa375f1d3a944e (patch)
tree247db5a8139cd4165a1704635e6d0d1f98713d6c /src
parentd7ee56e862071c3cea4c5fb7cf12444591e0b3f2 (diff)
downloadrust-f8ea24edc8b663c5acbe252936aa375f1d3a944e.tar.gz
rust-f8ea24edc8b663c5acbe252936aa375f1d3a944e.zip
rustc: Avoid free functions taking &TyCtxt and &InferCtxt.
Diffstat (limited to 'src')
-rw-r--r--src/librustc/infer/bivariate.rs4
-rw-r--r--src/librustc/infer/combine.rs82
-rw-r--r--src/librustc/infer/equate.rs4
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs83
-rw-r--r--src/librustc/infer/lattice.rs3
-rw-r--r--src/librustc/infer/mod.rs269
-rw-r--r--src/librustc/infer/sub.rs4
-rw-r--r--src/librustc/middle/astconv_util.rs43
-rw-r--r--src/librustc/middle/free_region.rs5
-rw-r--r--src/librustc/middle/stability.rs30
-rw-r--r--src/librustc/traits/coherence.rs11
-rw-r--r--src/librustc/traits/error_reporting.rs425
-rw-r--r--src/librustc/traits/fulfill.rs9
-rw-r--r--src/librustc/traits/mod.rs24
-rw-r--r--src/librustc/traits/object_safety.rs128
-rw-r--r--src/librustc/traits/project.rs27
-rw-r--r--src/librustc/traits/select.rs40
-rw-r--r--src/librustc/traits/specialize/mod.rs13
-rw-r--r--src/librustc/traits/util.rs84
-rw-r--r--src/librustc/ty/layout.rs4
-rw-r--r--src/librustc/ty/outlives.rs27
-rw-r--r--src/librustc/ty/sty.rs5
-rw-r--r--src/librustc/ty/wf.rs8
-rw-r--r--src/librustc_const_eval/eval.rs13
-rw-r--r--src/librustc_driver/test.rs7
-rw-r--r--src/librustc_metadata/encoder.rs45
-rw-r--r--src/librustc_mir/mir_map.rs8
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs6
-rw-r--r--src/librustc_mir/transform/type_check.rs24
-rw-r--r--src/librustc_trans/callee.rs3
-rw-r--r--src/librustc_trans/common.rs8
-rw-r--r--src/librustc_trans/meth.rs2
-rw-r--r--src/librustc_typeck/astconv.rs31
-rw-r--r--src/librustc_typeck/check/coercion.rs14
-rw-r--r--src/librustc_typeck/check/compare_method.rs11
-rw-r--r--src/librustc_typeck/check/dropck.rs7
-rw-r--r--src/librustc_typeck/check/method/confirm.rs15
-rw-r--r--src/librustc_typeck/check/mod.rs97
-rw-r--r--src/librustc_typeck/check/regionck.rs30
-rw-r--r--src/librustc_typeck/check/writeback.rs12
-rw-r--r--src/librustc_typeck/coherence/mod.rs63
-rw-r--r--src/librustc_typeck/coherence/overlap.rs2
-rw-r--r--src/librustc_typeck/lib.rs4
-rw-r--r--src/librustdoc/clean/inline.rs21
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/librustdoc/visit_ast.rs5
46 files changed, 765 insertions, 1003 deletions
diff --git a/src/librustc/infer/bivariate.rs b/src/librustc/infer/bivariate.rs
index a9ea395e6b3..156d8e8c95f 100644
--- a/src/librustc/infer/bivariate.rs
+++ b/src/librustc/infer/bivariate.rs
@@ -25,7 +25,7 @@
 //! In particular, it might be enough to say (A,B) are bivariant for
 //! all (A,B).
 
-use super::combine::{self, CombineFields};
+use super::combine::CombineFields;
 use super::type_variable::{BiTo};
 
 use ty::{self, Ty, TyCtxt};
@@ -96,7 +96,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
             }
 
             _ => {
-                combine::super_combine_tys(self.fields.infcx, self, a, b)
+                self.fields.infcx.super_combine_tys(self, a, b)
             }
         }
     }
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index 2a27da06612..0812d8d0de4 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -60,11 +60,12 @@ pub struct CombineFields<'a, 'tcx: 'a> {
     pub obligations: PredicateObligations<'tcx>,
 }
 
-pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
-                                       relation: &mut R,
-                                       a: Ty<'tcx>,
-                                       b: Ty<'tcx>)
-                                       -> RelateResult<'tcx, Ty<'tcx>>
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+pub fn super_combine_tys<R>(&self,
+                            relation: &mut R,
+                            a: Ty<'tcx>,
+                            b: Ty<'tcx>)
+                            -> RelateResult<'tcx, Ty<'tcx>>
     where R: TypeRelation<'a,'tcx>
 {
     let a_is_expected = relation.a_is_expected();
@@ -72,38 +73,38 @@ pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
     match (&a.sty, &b.sty) {
         // Relate integral variables to other types
         (&ty::TyInfer(ty::IntVar(a_id)), &ty::TyInfer(ty::IntVar(b_id))) => {
-            infcx.int_unification_table
-                 .borrow_mut()
-                 .unify_var_var(a_id, b_id)
-                 .map_err(|e| int_unification_error(a_is_expected, e))?;
+            self.int_unification_table
+                .borrow_mut()
+                .unify_var_var(a_id, b_id)
+                .map_err(|e| int_unification_error(a_is_expected, e))?;
             Ok(a)
         }
         (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyInt(v)) => {
-            unify_integral_variable(infcx, a_is_expected, v_id, IntType(v))
+            self.unify_integral_variable(a_is_expected, v_id, IntType(v))
         }
         (&ty::TyInt(v), &ty::TyInfer(ty::IntVar(v_id))) => {
-            unify_integral_variable(infcx, !a_is_expected, v_id, IntType(v))
+            self.unify_integral_variable(!a_is_expected, v_id, IntType(v))
         }
         (&ty::TyInfer(ty::IntVar(v_id)), &ty::TyUint(v)) => {
-            unify_integral_variable(infcx, a_is_expected, v_id, UintType(v))
+            self.unify_integral_variable(a_is_expected, v_id, UintType(v))
         }
         (&ty::TyUint(v), &ty::TyInfer(ty::IntVar(v_id))) => {
-            unify_integral_variable(infcx, !a_is_expected, v_id, UintType(v))
+            self.unify_integral_variable(!a_is_expected, v_id, UintType(v))
         }
 
         // Relate floating-point variables to other types
         (&ty::TyInfer(ty::FloatVar(a_id)), &ty::TyInfer(ty::FloatVar(b_id))) => {
-            infcx.float_unification_table
-                 .borrow_mut()
-                 .unify_var_var(a_id, b_id)
-                 .map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
+            self.float_unification_table
+                .borrow_mut()
+                .unify_var_var(a_id, b_id)
+                .map_err(|e| float_unification_error(relation.a_is_expected(), e))?;
             Ok(a)
         }
         (&ty::TyInfer(ty::FloatVar(v_id)), &ty::TyFloat(v)) => {
-            unify_float_variable(infcx, a_is_expected, v_id, v)
+            self.unify_float_variable(a_is_expected, v_id, v)
         }
         (&ty::TyFloat(v), &ty::TyInfer(ty::FloatVar(v_id))) => {
-            unify_float_variable(infcx, !a_is_expected, v_id, v)
+            self.unify_float_variable(!a_is_expected, v_id, v)
         }
 
         // All other cases of inference are errors
@@ -119,33 +120,34 @@ pub fn super_combine_tys<'a,'tcx:'a,R>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
-fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                                    vid_is_expected: bool,
-                                    vid: ty::IntVid,
-                                    val: ty::IntVarValue)
-                                    -> RelateResult<'tcx, Ty<'tcx>>
+fn unify_integral_variable(&self,
+                           vid_is_expected: bool,
+                           vid: ty::IntVid,
+                           val: ty::IntVarValue)
+                           -> RelateResult<'tcx, Ty<'tcx>>
 {
-    infcx.int_unification_table
-         .borrow_mut()
-         .unify_var_value(vid, val)
-         .map_err(|e| int_unification_error(vid_is_expected, e))?;
+    self.int_unification_table
+        .borrow_mut()
+        .unify_var_value(vid, val)
+        .map_err(|e| int_unification_error(vid_is_expected, e))?;
     match val {
-        IntType(v) => Ok(infcx.tcx.mk_mach_int(v)),
-        UintType(v) => Ok(infcx.tcx.mk_mach_uint(v)),
+        IntType(v) => Ok(self.tcx.mk_mach_int(v)),
+        UintType(v) => Ok(self.tcx.mk_mach_uint(v)),
     }
 }
 
-fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                                 vid_is_expected: bool,
-                                 vid: ty::FloatVid,
-                                 val: ast::FloatTy)
-                                 -> RelateResult<'tcx, Ty<'tcx>>
+fn unify_float_variable(&self,
+                        vid_is_expected: bool,
+                        vid: ty::FloatVid,
+                        val: ast::FloatTy)
+                        -> RelateResult<'tcx, Ty<'tcx>>
 {
-    infcx.float_unification_table
-         .borrow_mut()
-         .unify_var_value(vid, val)
-         .map_err(|e| float_unification_error(vid_is_expected, e))?;
-    Ok(infcx.tcx.mk_mach_float(val))
+    self.float_unification_table
+        .borrow_mut()
+        .unify_var_value(vid, val)
+        .map_err(|e| float_unification_error(vid_is_expected, e))?;
+    Ok(self.tcx.mk_mach_float(val))
+}
 }
 
 impl<'a, 'tcx> CombineFields<'a, 'tcx> {
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index 5540046c9e3..d6a66f74c2d 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::combine::{self, CombineFields};
+use super::combine::CombineFields;
 use super::higher_ranked::HigherRankedRelations;
 use super::{Subtype};
 use super::type_variable::{EqTo};
@@ -74,7 +74,7 @@ impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
             }
 
             _ => {
-                combine::super_combine_tys(self.fields.infcx, self, a, b)?;
+                self.fields.infcx.super_combine_tys(self, a, b)?;
                 Ok(a)
             }
         }
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index d89ef8ef6c3..8572eee5ccc 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -31,14 +31,6 @@ pub trait HigherRankedRelations<'a,'tcx> {
         where T: Relate<'a,'tcx>;
 }
 
-trait InferCtxtExt {
-    fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec<ty::Region>;
-
-    fn region_vars_confined_to_snapshot(&self,
-                                        snapshot: &CombinedSnapshot)
-                                        -> Vec<ty::RegionVid>;
-}
-
 impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
     fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
                             -> RelateResult<'tcx, Binder<T>>
@@ -79,23 +71,9 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
 
             // Presuming type comparison succeeds, we need to check
             // that the skolemized regions do not "leak".
-            match leak_check(self.infcx, &skol_map, snapshot) {
-                Ok(()) => { }
-                Err((skol_br, tainted_region)) => {
-                    if self.a_is_expected {
-                        debug!("Not as polymorphic!");
-                        return Err(TypeError::RegionsInsufficientlyPolymorphic(skol_br,
-                                                                               tainted_region));
-                    } else {
-                        debug!("Overly polymorphic!");
-                        return Err(TypeError::RegionsOverlyPolymorphic(skol_br,
-                                                                       tainted_region));
-                    }
-                }
-            }
+            self.infcx.leak_check(!self.a_is_expected, &skol_map, snapshot)?;
 
-            debug!("higher_ranked_sub: OK result={:?}",
-                   result);
+            debug!("higher_ranked_sub: OK result={:?}", result);
 
             Ok(ty::Binder(result))
         });
@@ -371,7 +349,7 @@ fn fold_regions_in<'tcx, T, F>(tcx: &TyCtxt<'tcx>,
     })
 }
 
-impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
+impl<'a,'tcx> InferCtxt<'a,'tcx> {
     fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec<ty::Region> {
         self.region_vars.tainted(&snapshot.region_vars_snapshot, r)
     }
@@ -452,12 +430,11 @@ impl<'a,'tcx> InferCtxtExt for InferCtxt<'a,'tcx> {
 
         region_vars
     }
-}
 
-pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
-                                               binder: &ty::Binder<T>,
-                                               snapshot: &CombinedSnapshot)
-                                               -> (T, SkolemizationMap)
+pub fn skolemize_late_bound_regions<T>(&self,
+                                       binder: &ty::Binder<T>,
+                                       snapshot: &CombinedSnapshot)
+                                       -> (T, SkolemizationMap)
     where T : TypeFoldable<'tcx>
 {
     /*!
@@ -468,8 +445,8 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
      * details.
      */
 
-    let (result, map) = infcx.tcx.replace_late_bound_regions(binder, |br| {
-        infcx.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot)
+    let (result, map) = self.tcx.replace_late_bound_regions(binder, |br| {
+        self.region_vars.new_skolemized(br, &snapshot.region_vars_snapshot)
     });
 
     debug!("skolemize_bound_regions(binder={:?}, result={:?}, map={:?})",
@@ -480,10 +457,11 @@ pub fn skolemize_late_bound_regions<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
     (result, map)
 }
 
-pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                           skol_map: &SkolemizationMap,
-                           snapshot: &CombinedSnapshot)
-                           -> Result<(),(ty::BoundRegion,ty::Region)>
+pub fn leak_check(&self,
+                  overly_polymorphic: bool,
+                  skol_map: &SkolemizationMap,
+                  snapshot: &CombinedSnapshot)
+                  -> RelateResult<'tcx, ()>
 {
     /*!
      * Searches the region constriants created since `snapshot` was started
@@ -496,9 +474,9 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
     debug!("leak_check: skol_map={:?}",
            skol_map);
 
-    let new_vars = infcx.region_vars_confined_to_snapshot(snapshot);
+    let new_vars = self.region_vars_confined_to_snapshot(snapshot);
     for (&skol_br, &skol) in skol_map {
-        let tainted = infcx.tainted_regions(snapshot, skol);
+        let tainted = self.tainted_regions(snapshot, skol);
         for &tainted_region in &tainted {
             // Each skolemized should only be relatable to itself
             // or new variables:
@@ -516,8 +494,15 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                    skol_br,
                    tainted_region);
 
-            // A is not as polymorphic as B:
-            return Err((skol_br, tainted_region));
+            if overly_polymorphic {
+                debug!("Overly polymorphic!");
+                return Err(TypeError::RegionsOverlyPolymorphic(skol_br,
+                                                               tainted_region));
+            } else {
+                debug!("Not as polymorphic!");
+                return Err(TypeError::RegionsInsufficientlyPolymorphic(skol_br,
+                                                                       tainted_region));
+            }
         }
     }
     Ok(())
@@ -551,14 +536,13 @@ pub fn leak_check<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
 /// replace `'0` with a late-bound region `'a`.  The depth is matched
 /// to the depth of the predicate, in this case 1, so that the final
 /// predicate is `for<'a> &'a int : Clone`.
-pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
-                             skol_map: SkolemizationMap,
-                             snapshot: &CombinedSnapshot,
-                             value: &T)
-                             -> T
+pub fn plug_leaks<T>(&self,
+                     skol_map: SkolemizationMap,
+                     snapshot: &CombinedSnapshot,
+                     value: &T) -> T
     where T : TypeFoldable<'tcx>
 {
-    debug_assert!(leak_check(infcx, &skol_map, snapshot).is_ok());
+    debug_assert!(self.leak_check(false, &skol_map, snapshot).is_ok());
 
     debug!("plug_leaks(skol_map={:?}, value={:?})",
            skol_map,
@@ -572,7 +556,7 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
         skol_map
         .into_iter()
         .flat_map(|(skol_br, skol)| {
-            infcx.tainted_regions(snapshot, skol)
+            self.tainted_regions(snapshot, skol)
                 .into_iter()
                 .map(move |tainted_region| (tainted_region, skol_br))
         })
@@ -583,14 +567,14 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
 
     // Remove any instantiated type variables from `value`; those can hide
     // references to regions from the `fold_regions` code below.
-    let value = infcx.resolve_type_vars_if_possible(value);
+    let value = self.resolve_type_vars_if_possible(value);
 
     // Map any skolemization byproducts back to a late-bound
     // region. Put that late-bound region at whatever the outermost
     // binder is that we encountered in `value`. The caller is
     // responsible for ensuring that (a) `value` contains at least one
     // binder and (b) that binder is the one we want to use.
-    let result = infcx.tcx.fold_regions(&value, &mut false, |r, current_depth| {
+    let result = self.tcx.fold_regions(&value, &mut false, |r, current_depth| {
         match inv_skol_map.get(&r) {
             None => r,
             Some(br) => {
@@ -612,3 +596,4 @@ pub fn plug_leaks<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
 
     result
 }
+}
diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs
index 17ad32e742e..94d261f9df3 100644
--- a/src/librustc/infer/lattice.rs
+++ b/src/librustc/infer/lattice.rs
@@ -29,7 +29,6 @@
 //! over a `LatticeValue`, which is a value defined with respect to
 //! a lattice.
 
-use super::combine;
 use super::InferCtxt;
 
 use ty::TyVar;
@@ -78,7 +77,7 @@ pub fn super_lattice_tys<'a,'tcx,L:LatticeDir<'a,'tcx>>(this: &mut L,
         }
 
         _ => {
-            combine::super_combine_tys(this.infcx(), this, a, b)
+            infcx.super_combine_tys(this, a, b)
         }
     }
 }
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 407278c283f..c876f6adae5 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -366,19 +366,21 @@ pub enum FixupError {
     UnresolvedTy(TyVid)
 }
 
-pub fn fixup_err_to_string(f: FixupError) -> String {
-    use self::FixupError::*;
-
-    match f {
-      UnresolvedIntTy(_) => {
-          "cannot determine the type of this integer; add a suffix to \
-           specify the type explicitly".to_string()
-      }
-      UnresolvedFloatTy(_) => {
-          "cannot determine the type of this number; add a suffix to specify \
-           the type explicitly".to_string()
-      }
-      UnresolvedTy(_) => "unconstrained type".to_string(),
+impl fmt::Display for FixupError {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        use self::FixupError::*;
+
+        match *self {
+            UnresolvedIntTy(_) => {
+                write!(f, "cannot determine the type of this integer; \
+                           add a suffix to specify the type explicitly")
+            }
+            UnresolvedFloatTy(_) => {
+                write!(f, "cannot determine the type of this number; \
+                           add a suffix to specify the type explicitly")
+            }
+            UnresolvedTy(_) => write!(f, "unconstrained type")
+        }
     }
 }
 
@@ -414,103 +416,19 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 }
 
-pub fn mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
-                          a_is_expected: bool,
-                          origin: TypeOrigin,
-                          a: Ty<'tcx>,
-                          b: Ty<'tcx>)
-    -> InferResult<'tcx, ()>
-{
-    debug!("mk_subty({:?} <: {:?})", a, b);
-    cx.sub_types(a_is_expected, origin, a, b)
-}
-
-pub fn can_mk_subty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>)
-    -> UnitResult<'tcx>
-{
-    debug!("can_mk_subty({:?} <: {:?})", a, b);
-    cx.probe(|_| {
-        let trace = TypeTrace {
-            origin: TypeOrigin::Misc(codemap::DUMMY_SP),
-            values: Types(expected_found(true, a, b))
-        };
-        cx.sub(true, trace, &a, &b).map(|_| ())
-    })
-}
-
-pub fn can_mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>, a: Ty<'tcx>, b: Ty<'tcx>)
-    -> UnitResult<'tcx>
-{
-    cx.can_equate(&a, &b)
-}
-
-pub fn mk_subr<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
-                         origin: SubregionOrigin<'tcx>,
-                         a: ty::Region,
-                         b: ty::Region) {
-    debug!("mk_subr({:?} <: {:?})", a, b);
-    let snapshot = cx.region_vars.start_snapshot();
-    cx.region_vars.make_subregion(origin, a, b);
-    cx.region_vars.commit(snapshot);
-}
-
-pub fn mk_eqty<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
-                         a_is_expected: bool,
-                         origin: TypeOrigin,
-                         a: Ty<'tcx>,
-                         b: Ty<'tcx>)
-    -> InferResult<'tcx, ()>
-{
-    debug!("mk_eqty({:?} <: {:?})", a, b);
-    cx.eq_types(a_is_expected, origin, a, b)
-}
-
-pub fn mk_eq_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
-                                  a_is_expected: bool,
-                                  origin: TypeOrigin,
-                                  a: ty::TraitRef<'tcx>,
-                                  b: ty::TraitRef<'tcx>)
-    -> InferResult<'tcx, ()>
-{
-    debug!("mk_eq_trait_refs({:?} = {:?})", a, b);
-    cx.eq_trait_refs(a_is_expected, origin, a, b)
-}
-
-pub fn mk_sub_poly_trait_refs<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
-                                        a_is_expected: bool,
-                                        origin: TypeOrigin,
-                                        a: ty::PolyTraitRef<'tcx>,
-                                        b: ty::PolyTraitRef<'tcx>)
-    -> InferResult<'tcx, ()>
-{
-    debug!("mk_sub_poly_trait_refs({:?} <: {:?})", a, b);
-    cx.sub_poly_trait_refs(a_is_expected, origin, a, b)
-}
-
-pub fn mk_eq_impl_headers<'a, 'tcx>(cx: &InferCtxt<'a, 'tcx>,
-                                    a_is_expected: bool,
-                                    origin: TypeOrigin,
-                                    a: &ty::ImplHeader<'tcx>,
-                                    b: &ty::ImplHeader<'tcx>)
-    -> InferResult<'tcx, ()>
-{
-    debug!("mk_eq_impl_header({:?} = {:?})", a, b);
-    match (a.trait_ref, b.trait_ref) {
-        (Some(a_ref), Some(b_ref)) => mk_eq_trait_refs(cx, a_is_expected, origin, a_ref, b_ref),
-        (None, None) => mk_eqty(cx, a_is_expected, origin, a.self_ty, b.self_ty),
-        _ => bug!("mk_eq_impl_headers given mismatched impl kinds"),
+impl<T> ExpectedFound<T> {
+    fn new(a_is_expected: bool, a: T, b: T) -> Self {
+        if a_is_expected {
+            ExpectedFound {expected: a, found: b}
+        } else {
+            ExpectedFound {expected: b, found: a}
+        }
     }
 }
 
-fn expected_found<T>(a_is_expected: bool,
-                     a: T,
-                     b: T)
-                     -> ExpectedFound<T>
-{
-    if a_is_expected {
-        ExpectedFound {expected: a, found: b}
-    } else {
-        ExpectedFound {expected: b, found: a}
+impl<'tcx, T> InferOk<'tcx, T> {
+    fn unit(self) -> InferOk<'tcx, ()> {
+        InferOk { value: (), obligations: self.obligations }
     }
 }
 
@@ -551,18 +469,19 @@ impl<'tcx> TyCtxt<'tcx> {
             fulfill_cx.register_predicate_obligation(&infcx, obligation);
         }
 
-        drain_fulfillment_cx_or_panic(DUMMY_SP, &infcx, &mut fulfill_cx, &result)
+        infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
     }
 }
 
-pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
-                                                infcx: &InferCtxt<'a,'tcx>,
-                                                fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
-                                                result: &T)
-                                                -> T
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+pub fn drain_fulfillment_cx_or_panic<T>(&self,
+                                        span: Span,
+                                        fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+                                        result: &T)
+                                        -> T
     where T : TypeFoldable<'tcx>
 {
-    match drain_fulfillment_cx(infcx, fulfill_cx, result) {
+    match self.drain_fulfillment_cx(fulfill_cx, result) {
         Ok(v) => v,
         Err(errors) => {
             span_bug!(
@@ -580,10 +499,10 @@ pub fn drain_fulfillment_cx_or_panic<'a,'tcx,T>(span: Span,
 /// inference variables that appear in `result` to be unified, and
 /// hence we need to process those obligations to get the complete
 /// picture of the type.
-pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
-                                       fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
-                                       result: &T)
-                                       -> Result<T,Vec<traits::FulfillmentError<'tcx>>>
+pub fn drain_fulfillment_cx<T>(&self,
+                               fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
+                               result: &T)
+                               -> Result<T,Vec<traits::FulfillmentError<'tcx>>>
     where T : TypeFoldable<'tcx>
 {
     debug!("drain_fulfillment_cx(result={:?})",
@@ -592,24 +511,12 @@ pub fn drain_fulfillment_cx<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
     // In principle, we only need to do this so long as `result`
     // contains unbound type parameters. It could be a slight
     // optimization to stop iterating early.
-    match fulfill_cx.select_all_or_error(infcx) {
-        Ok(()) => { }
-        Err(errors) => {
-            return Err(errors);
-        }
-    }
-
-    let result = infcx.resolve_type_vars_if_possible(result);
-    Ok(infcx.tcx.erase_regions(&result))
-}
+    fulfill_cx.select_all_or_error(self)?;
 
-impl<'tcx, T> InferOk<'tcx, T> {
-    fn unit(self) -> InferOk<'tcx, ()> {
-        InferOk { value: (), obligations: self.obligations }
-    }
+    let result = self.resolve_type_vars_if_possible(result);
+    Ok(self.tcx.erase_regions(&result))
 }
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     pub fn projection_mode(&self) -> ProjectionMode {
         self.projection_mode
     }
@@ -896,6 +803,18 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         })
     }
 
+    pub fn can_sub_types(&self,
+                         a: Ty<'tcx>,
+                         b: Ty<'tcx>)
+                         -> UnitResult<'tcx>
+    {
+        self.probe(|_| {
+            let origin = TypeOrigin::Misc(codemap::DUMMY_SP);
+            let trace = TypeTrace::types(origin, true, a, b);
+            self.sub(true, trace, &a, &b).map(|_| ())
+        })
+    }
+
     pub fn eq_types(&self,
                     a_is_expected: bool,
                     origin: TypeOrigin,
@@ -916,18 +835,31 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                           b: ty::TraitRef<'tcx>)
         -> InferResult<'tcx, ()>
     {
-        debug!("eq_trait_refs({:?} <: {:?})",
-               a,
-               b);
+        debug!("eq_trait_refs({:?} = {:?})", a, b);
         self.commit_if_ok(|_| {
             let trace = TypeTrace {
                 origin: origin,
-                values: TraitRefs(expected_found(a_is_expected, a.clone(), b.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,
+                           origin: TypeOrigin,
+                           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, origin, a_ref, b_ref),
+            (None, None) => self.eq_types(a_is_expected, origin, 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,
                                origin: TypeOrigin,
@@ -935,52 +867,22 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
                                b: ty::PolyTraitRef<'tcx>)
         -> InferResult<'tcx, ()>
     {
-        debug!("sub_poly_trait_refs({:?} <: {:?})",
-               a,
-               b);
+        debug!("sub_poly_trait_refs({:?} <: {:?})", a, b);
         self.commit_if_ok(|_| {
             let trace = TypeTrace {
                 origin: origin,
-                values: PolyTraitRefs(expected_found(a_is_expected, a.clone(), b.clone()))
+                values: PolyTraitRefs(ExpectedFound::new(a_is_expected, a, b))
             };
             self.sub(a_is_expected, trace, &a, &b).map(|ok| ok.unit())
         })
     }
 
-    pub fn skolemize_late_bound_regions<T>(&self,
-                                           value: &ty::Binder<T>,
-                                           snapshot: &CombinedSnapshot)
-                                           -> (T, SkolemizationMap)
-        where T : TypeFoldable<'tcx>
-    {
-        /*! See `higher_ranked::skolemize_late_bound_regions` */
-
-        higher_ranked::skolemize_late_bound_regions(self, value, snapshot)
-    }
-
-    pub fn leak_check(&self,
-                      skol_map: &SkolemizationMap,
-                      snapshot: &CombinedSnapshot)
-                      -> UnitResult<'tcx>
-    {
-        /*! See `higher_ranked::leak_check` */
-
-        match higher_ranked::leak_check(self, skol_map, snapshot) {
-            Ok(()) => Ok(()),
-            Err((br, r)) => Err(TypeError::RegionsInsufficientlyPolymorphic(br, r))
-        }
-    }
-
-    pub fn plug_leaks<T>(&self,
-                         skol_map: SkolemizationMap,
-                         snapshot: &CombinedSnapshot,
-                         value: &T)
-                         -> T
-        where T : TypeFoldable<'tcx>
-    {
-        /*! See `higher_ranked::plug_leaks` */
-
-        higher_ranked::plug_leaks(self, skol_map, snapshot, value)
+    pub fn sub_regions(&self,
+                       origin: SubregionOrigin<'tcx>,
+                       a: ty::Region,
+                       b: ty::Region) {
+        debug!("sub_regions({:?} <: {:?})", a, b);
+        self.region_vars.make_subregion(origin, a, b);
     }
 
     pub fn equality_predicate(&self,
@@ -992,8 +894,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             let (ty::EquatePredicate(a, b), skol_map) =
                 self.skolemize_late_bound_regions(predicate, snapshot);
             let origin = TypeOrigin::EquatePredicate(span);
-            let eqty_ok = mk_eqty(self, false, origin, a, b)?;
-            self.leak_check(&skol_map, snapshot).map(|_| eqty_ok.unit())
+            let eqty_ok = self.eq_types(false, origin, a, b)?;
+            self.leak_check(false, &skol_map, snapshot).map(|_| eqty_ok.unit())
         })
     }
 
@@ -1006,8 +908,8 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             let (ty::OutlivesPredicate(r_a, r_b), skol_map) =
                 self.skolemize_late_bound_regions(predicate, snapshot);
             let origin = RelateRegionParamBound(span);
-            let () = mk_subr(self, origin, r_b, r_a); // `b : a` ==> `a <= b`
-            self.leak_check(&skol_map, snapshot)
+            self.sub_regions(origin, r_b, r_a); // `b : a` ==> `a <= b`
+            self.leak_check(false, &skol_map, snapshot)
         })
     }
 
@@ -1509,12 +1411,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
             // anyhow. We should make this typetrace stuff more
             // generic so we don't have to do anything quite this
             // terrible.
-            let e = self.tcx.types.err;
-            let trace = TypeTrace {
-                origin: TypeOrigin::Misc(codemap::DUMMY_SP),
-                values: Types(expected_found(true, e, e))
-            };
-            self.equate(true, trace, a, b)
+            self.equate(true, TypeTrace::dummy(self.tcx), a, b)
         }).map(|_| ())
     }
 
@@ -1638,7 +1535,7 @@ impl<'tcx> TypeTrace<'tcx> {
                  -> TypeTrace<'tcx> {
         TypeTrace {
             origin: origin,
-            values: Types(expected_found(a_is_expected, a, b))
+            values: Types(ExpectedFound::new(a_is_expected, a, b))
         }
     }
 
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index 71e1efe220f..a85ae46e662 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -8,7 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use super::combine::{self, CombineFields};
+use super::combine::CombineFields;
 use super::higher_ranked::HigherRankedRelations;
 use super::SubregionOrigin;
 use super::type_variable::{SubtypeOf, SupertypeOf};
@@ -96,7 +96,7 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
             }
 
             _ => {
-                combine::super_combine_tys(self.fields.infcx, self, a, b)?;
+                self.fields.infcx.super_combine_tys(self, a, b)?;
                 Ok(a)
             }
         }
diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs
index 2a27732b953..f9a9a451d45 100644
--- a/src/librustc/middle/astconv_util.rs
+++ b/src/librustc/middle/astconv_util.rs
@@ -20,59 +20,59 @@ use ty::{Ty, TyCtxt};
 use syntax::codemap::Span;
 use hir as ast;
 
-pub fn prohibit_type_params(tcx: &TyCtxt, segments: &[ast::PathSegment]) {
+impl<'tcx> TyCtxt<'tcx> {
+pub fn prohibit_type_params(&self, segments: &[ast::PathSegment]) {
     for segment in segments {
         for typ in segment.parameters.types() {
-            span_err!(tcx.sess, typ.span, E0109,
+            span_err!(self.sess, typ.span, E0109,
                       "type parameters are not allowed on this type");
             break;
         }
         for lifetime in segment.parameters.lifetimes() {
-            span_err!(tcx.sess, lifetime.span, E0110,
+            span_err!(self.sess, lifetime.span, E0110,
                       "lifetime parameters are not allowed on this type");
             break;
         }
         for binding in segment.parameters.bindings() {
-            prohibit_projection(tcx, binding.span);
+            self.prohibit_projection(binding.span);
             break;
         }
     }
 }
 
-pub fn prohibit_projection(tcx: &TyCtxt, span: Span)
+pub fn prohibit_projection(&self, span: Span)
 {
-    span_err!(tcx.sess, span, E0229,
+    span_err!(self.sess, span, E0229,
               "associated type bindings are not allowed here");
 }
 
-pub fn prim_ty_to_ty<'tcx>(tcx: &TyCtxt<'tcx>,
-                           segments: &[ast::PathSegment],
-                           nty: ast::PrimTy)
-                           -> Ty<'tcx> {
-    prohibit_type_params(tcx, segments);
+pub fn prim_ty_to_ty(&self,
+                     segments: &[ast::PathSegment],
+                     nty: ast::PrimTy)
+                     -> Ty<'tcx> {
+    self.prohibit_type_params(segments);
     match nty {
-        ast::TyBool => tcx.types.bool,
-        ast::TyChar => tcx.types.char,
-        ast::TyInt(it) => tcx.mk_mach_int(it),
-        ast::TyUint(uit) => tcx.mk_mach_uint(uit),
-        ast::TyFloat(ft) => tcx.mk_mach_float(ft),
-        ast::TyStr => tcx.mk_str()
+        ast::TyBool => self.types.bool,
+        ast::TyChar => self.types.char,
+        ast::TyInt(it) => self.mk_mach_int(it),
+        ast::TyUint(uit) => self.mk_mach_uint(uit),
+        ast::TyFloat(ft) => self.mk_mach_float(ft),
+        ast::TyStr => self.mk_str()
     }
 }
 
 /// If a type in the AST is a primitive type, return the ty::Ty corresponding
 /// to it.
-pub fn ast_ty_to_prim_ty<'tcx>(tcx: &TyCtxt<'tcx>, ast_ty: &ast::Ty)
-                               -> Option<Ty<'tcx>> {
+pub fn ast_ty_to_prim_ty(&self, ast_ty: &ast::Ty) -> Option<Ty<'tcx>> {
     if let ast::TyPath(None, ref path) = ast_ty.node {
-        let def = match tcx.def_map.borrow().get(&ast_ty.id) {
+        let def = match self.def_map.borrow().get(&ast_ty.id) {
             None => {
                 span_bug!(ast_ty.span, "unbound path {:?}", path)
             }
             Some(d) => d.full_def()
         };
         if let Def::PrimTy(nty) = def {
-            Some(prim_ty_to_ty(tcx, &path.segments, nty))
+            Some(self.prim_ty_to_ty(&path.segments, nty))
         } else {
             None
         }
@@ -80,3 +80,4 @@ pub fn ast_ty_to_prim_ty<'tcx>(tcx: &TyCtxt<'tcx>, ast_ty: &ast::Ty)
         None
     }
 }
+}
diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs
index 758fb7a81fd..ccd927a3289 100644
--- a/src/librustc/middle/free_region.rs
+++ b/src/librustc/middle/free_region.rs
@@ -48,9 +48,8 @@ impl FreeRegionMap {
         }
     }
 
-    pub fn relate_free_regions_from_predicates<'tcx>(&mut self,
-                                                     _tcx: &TyCtxt<'tcx>,
-                                                     predicates: &[ty::Predicate<'tcx>]) {
+    pub fn relate_free_regions_from_predicates(&mut self,
+                                               predicates: &[ty::Predicate]) {
         debug!("relate_free_regions_from_predicates(predicates={:?})", predicates);
         for predicate in predicates {
             match *predicate {
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 5962142ca4a..f596f3b4a50 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -625,9 +625,9 @@ fn maybe_do_stability_check(tcx: &TyCtxt, id: DefId, span: Span,
         return;
     }
     let (stability, deprecation) = if is_staged_api(tcx, id) {
-        (lookup_stability(tcx, id), None)
+        (tcx.lookup_stability(id), None)
     } else {
-        (None, lookup_deprecation(tcx, id))
+        (None, tcx.lookup_deprecation(id))
     };
     debug!("maybe_do_stability_check: \
             inspecting id={:?} span={:?} of stability={:?}", id, span, stability);
@@ -651,45 +651,47 @@ fn is_staged_api(tcx: &TyCtxt, id: DefId) -> bool {
     }
 }
 
+impl<'tcx> TyCtxt<'tcx> {
 /// Lookup the stability for a node, loading external crate
 /// metadata as necessary.
-pub fn lookup_stability<'tcx>(tcx: &TyCtxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
-    if let Some(st) = tcx.stability.borrow().stab_map.get(&id) {
+pub fn lookup_stability(&self, id: DefId) -> Option<&'tcx Stability> {
+    if let Some(st) = self.stability.borrow().stab_map.get(&id) {
         return *st;
     }
 
-    let st = lookup_stability_uncached(tcx, id);
-    tcx.stability.borrow_mut().stab_map.insert(id, st);
+    let st = self.lookup_stability_uncached(id);
+    self.stability.borrow_mut().stab_map.insert(id, st);
     st
 }
 
-pub fn lookup_deprecation<'tcx>(tcx: &TyCtxt<'tcx>, id: DefId) -> Option<Deprecation> {
-    if let Some(depr) = tcx.stability.borrow().depr_map.get(&id) {
+pub fn lookup_deprecation(&self, id: DefId) -> Option<Deprecation> {
+    if let Some(depr) = self.stability.borrow().depr_map.get(&id) {
         return depr.clone();
     }
 
-    let depr = lookup_deprecation_uncached(tcx, id);
-    tcx.stability.borrow_mut().depr_map.insert(id, depr.clone());
+    let depr = self.lookup_deprecation_uncached(id);
+    self.stability.borrow_mut().depr_map.insert(id, depr.clone());
     depr
 }
 
-fn lookup_stability_uncached<'tcx>(tcx: &TyCtxt<'tcx>, id: DefId) -> Option<&'tcx Stability> {
+fn lookup_stability_uncached(&self, id: DefId) -> Option<&'tcx Stability> {
     debug!("lookup(id={:?})", id);
     if id.is_local() {
         None // The stability cache is filled partially lazily
     } else {
-        tcx.sess.cstore.stability(id).map(|st| tcx.intern_stability(st))
+        self.sess.cstore.stability(id).map(|st| self.intern_stability(st))
     }
 }
 
-fn lookup_deprecation_uncached<'tcx>(tcx: &TyCtxt<'tcx>, id: DefId) -> Option<Deprecation> {
+fn lookup_deprecation_uncached(&self, id: DefId) -> Option<Deprecation> {
     debug!("lookup(id={:?})", id);
     if id.is_local() {
         None // The stability cache is filled partially lazily
     } else {
-        tcx.sess.cstore.deprecation(id)
+        self.sess.cstore.deprecation(id)
     }
 }
+}
 
 /// Given the list of enabled features that were not language features (i.e. that
 /// were expected to be library features), and the list of features used from
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 6710d2a653c..ca2224d7884 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -16,7 +16,7 @@ use middle::cstore::LOCAL_CRATE;
 use hir::def_id::DefId;
 use ty::subst::TypeSpace;
 use ty::{self, Ty, TyCtxt};
-use infer::{self, InferCtxt, TypeOrigin};
+use infer::{InferCtxt, TypeOrigin};
 use syntax::codemap::DUMMY_SP;
 
 #[derive(Copy, Clone)]
@@ -57,11 +57,10 @@ fn overlap<'cx, 'tcx>(selcx: &mut SelectionContext<'cx, 'tcx>,
     debug!("overlap: b_impl_header={:?}", b_impl_header);
 
     // Do `a` and `b` unify? If not, no overlap.
-    if let Err(_) = infer::mk_eq_impl_headers(selcx.infcx(),
-                                              true,
-                                              TypeOrigin::Misc(DUMMY_SP),
-                                              &a_impl_header,
-                                              &b_impl_header) {
+    if let Err(_) = selcx.infcx().eq_impl_headers(true,
+                                                  TypeOrigin::Misc(DUMMY_SP),
+                                                  &a_impl_header,
+                                                  &b_impl_header) {
         return None;
     }
 
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index b89ce2ce3b2..fb030288a72 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -22,7 +22,6 @@ use super::{
     SelectionError,
     ObjectSafetyViolation,
     MethodViolationCode,
-    object_safety_violations,
 };
 
 use fmt_macros::{Parser, Piece, Position};
@@ -61,56 +60,55 @@ impl<'tcx> TraitErrorKey<'tcx> {
     }
 }
 
-pub fn report_fulfillment_errors<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                           errors: &Vec<FulfillmentError<'tcx>>) {
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
     for error in errors {
-        report_fulfillment_error(infcx, error, None);
+        self.report_fulfillment_error(error, None);
     }
 }
 
-pub fn report_fulfillment_errors_as_warnings<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                                       errors: &Vec<FulfillmentError<'tcx>>,
-                                                       node_id: ast::NodeId)
-{
+pub fn report_fulfillment_errors_as_warnings(&self,
+                                             errors: &Vec<FulfillmentError<'tcx>>,
+                                             node_id: ast::NodeId) {
     for error in errors {
-        report_fulfillment_error(infcx, error, Some(node_id));
+        self.report_fulfillment_error(error, Some(node_id));
     }
 }
 
-fn report_fulfillment_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                      error: &FulfillmentError<'tcx>,
-                                      warning_node_id: Option<ast::NodeId>) {
-    let error_key = TraitErrorKey::from_error(infcx, error, warning_node_id);
+fn report_fulfillment_error(&self,
+                            error: &FulfillmentError<'tcx>,
+                            warning_node_id: Option<ast::NodeId>) {
+    let error_key = TraitErrorKey::from_error(self, error, warning_node_id);
     debug!("report_fulfillment_errors({:?}) - key={:?}",
            error, error_key);
-    if !infcx.reported_trait_errors.borrow_mut().insert(error_key) {
+    if !self.reported_trait_errors.borrow_mut().insert(error_key) {
         debug!("report_fulfillment_errors: skipping duplicate");
         return;
     }
     match error.code {
         FulfillmentErrorCode::CodeSelectionError(ref e) => {
-            report_selection_error(infcx, &error.obligation, e, warning_node_id);
+            self.report_selection_error(&error.obligation, e, warning_node_id);
         }
         FulfillmentErrorCode::CodeProjectionError(ref e) => {
-            report_projection_error(infcx, &error.obligation, e, warning_node_id);
+            self.report_projection_error(&error.obligation, e, warning_node_id);
         }
         FulfillmentErrorCode::CodeAmbiguity => {
-            maybe_report_ambiguity(infcx, &error.obligation);
+            self.maybe_report_ambiguity(&error.obligation);
         }
     }
 }
 
-pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                         obligation: &PredicateObligation<'tcx>,
-                                         error: &MismatchedProjectionTypes<'tcx>,
-                                         warning_node_id: Option<ast::NodeId>)
+fn report_projection_error(&self,
+                           obligation: &PredicateObligation<'tcx>,
+                           error: &MismatchedProjectionTypes<'tcx>,
+                           warning_node_id: Option<ast::NodeId>)
 {
     let predicate =
-        infcx.resolve_type_vars_if_possible(&obligation.predicate);
+        self.resolve_type_vars_if_possible(&obligation.predicate);
 
     if !predicate.references_error() {
         if let Some(warning_node_id) = warning_node_id {
-            infcx.tcx.sess.add_lint(
+            self.tcx.sess.add_lint(
                 ::lint::builtin::UNSIZED_IN_TUPLE,
                 warning_node_id,
                 obligation.cause.span,
@@ -118,26 +116,26 @@ pub fn report_projection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                         predicate,
                         error.err));
         } else {
-            let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0271,
+            let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0271,
                                            "type mismatch resolving `{}`: {}",
                                            predicate,
                                            error.err);
-            note_obligation_cause(infcx, &mut err, obligation);
+            self.note_obligation_cause(&mut err, obligation);
             err.emit();
         }
     }
 }
 
-fn on_unimplemented_note<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                   trait_ref: ty::PolyTraitRef<'tcx>,
-                                   span: Span) -> Option<String> {
+fn on_unimplemented_note(&self,
+                         trait_ref: ty::PolyTraitRef<'tcx>,
+                         span: Span) -> Option<String> {
     let trait_ref = trait_ref.skip_binder();
     let def_id = trait_ref.def_id;
     let mut report = None;
-    for item in infcx.tcx.get_attrs(def_id).iter() {
+    for item in self.tcx.get_attrs(def_id).iter() {
         if item.check_name("rustc_on_unimplemented") {
             let err_sp = item.meta().span.substitute_dummy(span);
-            let def = infcx.tcx.lookup_trait_def(def_id);
+            let def = self.tcx.lookup_trait_def(def_id);
             let trait_str = def.trait_ref.to_string();
             if let Some(ref istring) = item.value_str() {
                 let mut generic_map = def.generics.types.iter_enumerated()
@@ -157,7 +155,7 @@ fn on_unimplemented_note<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                             Position::ArgumentNamed(s) => match generic_map.get(s) {
                                 Some(val) => Some(val),
                                 None => {
-                                    span_err!(infcx.tcx.sess, err_sp, E0272,
+                                    span_err!(self.tcx.sess, err_sp, E0272,
                                                    "the #[rustc_on_unimplemented] \
                                                             attribute on \
                                                             trait definition for {} refers to \
@@ -168,7 +166,7 @@ fn on_unimplemented_note<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                 }
                             },
                             _ => {
-                                     span_err!(infcx.tcx.sess, err_sp, E0273,
+                                     span_err!(self.tcx.sess, err_sp, E0273,
                                                "the #[rustc_on_unimplemented] \
                                                         attribute on \
                                                         trait definition for {} must have named \
@@ -187,7 +185,7 @@ fn on_unimplemented_note<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                     report = Some(err);
                 }
             } else {
-                span_err!(infcx.tcx.sess, err_sp, E0274,
+                span_err!(self.tcx.sess, err_sp, E0274,
                                         "the #[rustc_on_unimplemented] attribute on \
                                                  trait definition for {} must have a value, \
                                                  eg `#[rustc_on_unimplemented = \"foo\"]`",
@@ -199,21 +197,20 @@ fn on_unimplemented_note<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     report
 }
 
-fn find_similar_impl_candidates<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
-    trait_ref: ty::PolyTraitRef<'tcx>)
-    -> Vec<ty::TraitRef<'tcx>>
+fn report_similar_impl_candidates(&self,
+                                  trait_ref: ty::PolyTraitRef<'tcx>,
+                                  err: &mut DiagnosticBuilder)
 {
-    let simp = fast_reject::simplify_type(infcx.tcx,
+    let simp = fast_reject::simplify_type(self.tcx,
                                           trait_ref.skip_binder().self_ty(),
                                           true);
     let mut impl_candidates = Vec::new();
-    let trait_def = infcx.tcx.lookup_trait_def(trait_ref.def_id());
+    let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id());
 
     match simp {
-        Some(simp) => trait_def.for_each_impl(infcx.tcx, |def_id| {
-            let imp = infcx.tcx.impl_trait_ref(def_id).unwrap();
-            let imp_simp = fast_reject::simplify_type(infcx.tcx,
+        Some(simp) => trait_def.for_each_impl(self.tcx, |def_id| {
+            let imp = self.tcx.impl_trait_ref(def_id).unwrap();
+            let imp_simp = fast_reject::simplify_type(self.tcx,
                                                       imp.self_ty(),
                                                       true);
             if let Some(imp_simp) = imp_simp {
@@ -223,17 +220,16 @@ fn find_similar_impl_candidates<'a, 'tcx>(
             }
             impl_candidates.push(imp);
         }),
-        None => trait_def.for_each_impl(infcx.tcx, |def_id| {
+        None => trait_def.for_each_impl(self.tcx, |def_id| {
             impl_candidates.push(
-                infcx.tcx.impl_trait_ref(def_id).unwrap());
+                self.tcx.impl_trait_ref(def_id).unwrap());
         })
     };
-    impl_candidates
-}
 
-fn report_similar_impl_candidates(err: &mut DiagnosticBuilder,
-                                  impl_candidates: &[ty::TraitRef])
-{
+    if impl_candidates.is_empty() {
+        return;
+    }
+
     err.help(&format!("the following implementations were found:"));
 
     let end = cmp::min(4, impl_candidates.len());
@@ -251,26 +247,25 @@ fn report_similar_impl_candidates(err: &mut DiagnosticBuilder,
 /// whose result could not be truly determined and thus we can't say
 /// if the program type checks or not -- and they are unusual
 /// occurrences in any case.
-pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
-                                          obligation: &Obligation<'tcx, T>,
-                                          suggest_increasing_limit: bool)
-                                          -> !
+pub fn report_overflow_error<T>(&self,
+                                obligation: &Obligation<'tcx, T>,
+                                suggest_increasing_limit: bool) -> !
     where T: fmt::Display + TypeFoldable<'tcx>
 {
     let predicate =
-        infcx.resolve_type_vars_if_possible(&obligation.predicate);
-    let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0275,
+        self.resolve_type_vars_if_possible(&obligation.predicate);
+    let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0275,
                                    "overflow evaluating the requirement `{}`",
                                    predicate);
 
     if suggest_increasing_limit {
-        suggest_new_overflow_limit(infcx.tcx, &mut err);
+        self.suggest_new_overflow_limit(&mut err);
     }
 
-    note_obligation_cause(infcx, &mut err, obligation);
+    self.note_obligation_cause(&mut err, obligation);
 
     err.emit();
-    infcx.tcx.sess.abort_if_errors();
+    self.tcx.sess.abort_if_errors();
     bug!();
 }
 
@@ -279,33 +274,29 @@ pub fn report_overflow_error<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
 /// that we can give a more helpful error message (and, in particular,
 /// we do not suggest increasing the overflow limit, which is not
 /// going to help).
-pub fn report_overflow_error_cycle<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                             cycle: &Vec<PredicateObligation<'tcx>>)
-                                             -> !
-{
+pub fn report_overflow_error_cycle(&self, cycle: &Vec<PredicateObligation<'tcx>>) -> ! {
     assert!(cycle.len() > 1);
 
     debug!("report_overflow_error_cycle(cycle length = {})", cycle.len());
 
-    let cycle = infcx.resolve_type_vars_if_possible(cycle);
+    let cycle = self.resolve_type_vars_if_possible(cycle);
 
     debug!("report_overflow_error_cycle: cycle={:?}", cycle);
 
     assert_eq!(&cycle[0].predicate, &cycle.last().unwrap().predicate);
 
-    try_report_overflow_error_type_of_infinite_size(infcx, &cycle);
-    report_overflow_error(infcx, &cycle[0], false);
+    self.try_report_overflow_error_type_of_infinite_size(&cycle);
+    self.report_overflow_error(&cycle[0], false);
 }
 
 /// If a cycle results from evaluated whether something is Sized, that
 /// is a particular special case that always results from a struct or
 /// enum definition that lacks indirection (e.g., `struct Foo { x: Foo
 /// }`). We wish to report a targeted error for this case.
-pub fn try_report_overflow_error_type_of_infinite_size<'a, 'tcx>(
-    infcx: &InferCtxt<'a, 'tcx>,
+pub fn try_report_overflow_error_type_of_infinite_size(&self,
     cycle: &[PredicateObligation<'tcx>])
 {
-    let sized_trait = match infcx.tcx.lang_items.sized_trait() {
+    let sized_trait = match self.tcx.lang_items.sized_trait() {
         Some(v) => v,
         None => return,
     };
@@ -373,8 +364,8 @@ pub fn try_report_overflow_error_type_of_infinite_size<'a, 'tcx>(
                        .chain(struct_enum_tys.iter().cloned().take(main_index))
                        .collect();
 
-    let tcx = infcx.tcx;
-    let mut err = recursive_type_with_infinite_size_error(tcx, main_def_id);
+    let tcx = self.tcx;
+    let mut err = tcx.recursive_type_with_infinite_size_error(main_def_id);
     let len = struct_enum_tys.len();
     if len > 2 {
         err.note(&format!("type `{}` is embedded within `{}`...",
@@ -388,48 +379,38 @@ pub fn try_report_overflow_error_type_of_infinite_size<'a, 'tcx>(
                           struct_enum_tys[len-1]));
     }
     err.emit();
-    infcx.tcx.sess.abort_if_errors();
+    self.tcx.sess.abort_if_errors();
     bug!();
 }
 
-pub fn recursive_type_with_infinite_size_error<'tcx>(tcx: &TyCtxt<'tcx>,
-                                                     type_def_id: DefId)
-                                                     -> DiagnosticBuilder<'tcx>
+pub fn report_selection_error(&self,
+                              obligation: &PredicateObligation<'tcx>,
+                              error: &SelectionError<'tcx>,
+                              warning_node_id: Option<ast::NodeId>)
 {
-    assert!(type_def_id.is_local());
-    let span = tcx.map.span_if_local(type_def_id).unwrap();
-    let mut err = struct_span_err!(tcx.sess, span, E0072, "recursive type `{}` has infinite size",
-                                   tcx.item_path_str(type_def_id));
-    err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
-                       at some point to make `{}` representable",
-                      tcx.item_path_str(type_def_id)));
-    err
-}
-
-pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                        obligation: &PredicateObligation<'tcx>,
-                                        error: &SelectionError<'tcx>,
-                                        warning_node_id: Option<ast::NodeId>)
-{
-    match *error {
+    let span = obligation.cause.span;
+    let mut err = match *error {
         SelectionError::Unimplemented => {
             if let ObligationCauseCode::CompareImplMethodObligation = obligation.cause.code {
                 span_err!(
-                    infcx.tcx.sess, obligation.cause.span, E0276,
+                    self.tcx.sess, span, E0276,
                     "the requirement `{}` appears on the impl \
                      method but not on the corresponding trait method",
                     obligation.predicate);
+                return;
             } else {
                 match obligation.predicate {
                     ty::Predicate::Trait(ref trait_predicate) => {
                         let trait_predicate =
-                            infcx.resolve_type_vars_if_possible(trait_predicate);
+                            self.resolve_type_vars_if_possible(trait_predicate);
 
-                        if !infcx.tcx.sess.has_errors() || !trait_predicate.references_error() {
+                        if self.tcx.sess.has_errors() && trait_predicate.references_error() {
+                            return;
+                        } else {
                             let trait_ref = trait_predicate.to_poly_trait_ref();
 
                             if let Some(warning_node_id) = warning_node_id {
-                                infcx.tcx.sess.add_lint(
+                                self.tcx.sess.add_lint(
                                     ::lint::builtin::UNSIZED_IN_TUPLE,
                                     warning_node_id,
                                     obligation.cause.span,
@@ -439,14 +420,14 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                             }
 
                             let mut err = struct_span_err!(
-                                infcx.tcx.sess, obligation.cause.span, E0277,
+                                self.tcx.sess, span, E0277,
                                 "the trait bound `{}` is not satisfied",
                                 trait_ref.to_predicate());
 
                             // Try to report a help message
 
                             if !trait_ref.has_infer_types() &&
-                                predicate_can_apply(infcx, trait_ref)
+                                self.predicate_can_apply(trait_ref)
                             {
                                 // If a where-clause may be useful, remind the
                                 // user that they can add it.
@@ -458,8 +439,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                 err.help(&format!("consider adding a `where {}` bound",
                                     trait_ref.to_predicate()
                                     ));
-                            } else if let Some(s) = on_unimplemented_note(infcx, trait_ref,
-                                                                          obligation.cause.span) {
+                            } else if let Some(s) = self.on_unimplemented_note(trait_ref, span) {
                                 // Otherwise, if there is an on-unimplemented note,
                                 // display it.
                                 err.note(&s);
@@ -467,72 +447,55 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                 // If we can't show anything useful, try to find
                                 // similar impls.
 
-                                let impl_candidates =
-                                    find_similar_impl_candidates(infcx, trait_ref);
-                                if impl_candidates.len() > 0 {
-                                    report_similar_impl_candidates(&mut err, &impl_candidates);
-                                }
+                                self.report_similar_impl_candidates(trait_ref, &mut err);
                             }
-                            note_obligation_cause(infcx, &mut err, obligation);
-                            err.emit();
+                            err
                         }
                     },
                     ty::Predicate::Equate(ref predicate) => {
-                        let predicate = infcx.resolve_type_vars_if_possible(predicate);
-                        let err = infcx.equality_predicate(obligation.cause.span,
-                                                           &predicate).err().unwrap();
-                        let mut err = struct_span_err!(
-                            infcx.tcx.sess, obligation.cause.span, E0278,
+                        let predicate = self.resolve_type_vars_if_possible(predicate);
+                        let err = self.equality_predicate(span,
+                                                          &predicate).err().unwrap();
+                        struct_span_err!(self.tcx.sess, span, E0278,
                             "the requirement `{}` is not satisfied (`{}`)",
-                            predicate,
-                            err);
-                        note_obligation_cause(infcx, &mut err, obligation);
-                        err.emit();
+                            predicate, err)
                     }
 
                     ty::Predicate::RegionOutlives(ref predicate) => {
-                        let predicate = infcx.resolve_type_vars_if_possible(predicate);
-                        let err = infcx.region_outlives_predicate(obligation.cause.span,
-                                                                  &predicate).err().unwrap();
-                        let mut err = struct_span_err!(
-                            infcx.tcx.sess, obligation.cause.span, E0279,
+                        let predicate = self.resolve_type_vars_if_possible(predicate);
+                        let err = self.region_outlives_predicate(span,
+                                                                 &predicate).err().unwrap();
+                        struct_span_err!(self.tcx.sess, span, E0279,
                             "the requirement `{}` is not satisfied (`{}`)",
-                            predicate,
-                            err);
-                        note_obligation_cause(infcx, &mut err, obligation);
-                        err.emit();
+                            predicate, err)
                     }
 
                     ty::Predicate::Projection(..) | ty::Predicate::TypeOutlives(..) => {
                         let predicate =
-                            infcx.resolve_type_vars_if_possible(&obligation.predicate);
-                        let mut err = struct_span_err!(
-                            infcx.tcx.sess, obligation.cause.span, E0280,
+                            self.resolve_type_vars_if_possible(&obligation.predicate);
+                        struct_span_err!(self.tcx.sess, span, E0280,
                             "the requirement `{}` is not satisfied",
-                            predicate);
-                        note_obligation_cause(infcx, &mut err, obligation);
-                        err.emit();
+                            predicate)
                     }
 
                     ty::Predicate::ObjectSafe(trait_def_id) => {
-                        let violations = object_safety_violations(
-                            infcx.tcx, trait_def_id);
-                        let err = report_object_safety_error(infcx.tcx,
-                                                             obligation.cause.span,
-                                                             trait_def_id,
-                                                             warning_node_id,
-                                                             violations);
-                        if let Some(mut err) = err {
-                            note_obligation_cause(infcx, &mut err, obligation);
-                            err.emit();
+                        let violations = self.tcx.object_safety_violations(trait_def_id);
+                        let err = self.tcx.report_object_safety_error(span,
+                                                                      trait_def_id,
+                                                                      warning_node_id,
+                                                                      violations);
+                        if let Some(err) = err {
+                            err
+                        } else {
+                            return;
                         }
                     }
 
                     ty::Predicate::ClosureKind(closure_def_id, kind) => {
-                        let found_kind = infcx.closure_kind(closure_def_id).unwrap();
-                        let closure_span = infcx.tcx.map.span_if_local(closure_def_id).unwrap();
+                        let found_kind = self.closure_kind(closure_def_id).unwrap();
+                        let closure_span = self.tcx.map.span_if_local(closure_def_id).unwrap();
                         let mut err = struct_span_err!(
-                            infcx.tcx.sess, closure_span, E0525,
+                            self.tcx.sess, closure_span, E0525,
                             "expected a closure that implements the `{}` trait, but this closure \
                              only implements `{}`",
                             kind,
@@ -541,6 +504,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                             obligation.cause.span,
                             &format!("the requirement to implement `{}` derives from here", kind));
                         err.emit();
+                        return;
                     }
 
                     ty::Predicate::WellFormed(ty) => {
@@ -549,10 +513,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                         // ambiguity; otherwise, they always
                         // degenerate into other obligations
                         // (which may fail).
-                        span_bug!(
-                            obligation.cause.span,
-                            "WF predicate not satisfied for {:?}",
-                            ty);
+                        span_bug!(span, "WF predicate not satisfied for {:?}", ty);
                     }
 
                     ty::Predicate::Rfc1592(ref data) => {
@@ -566,49 +527,66 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         }
 
         OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
-            let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
-            let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
-            if !actual_trait_ref.self_ty().references_error() {
-                let mut err = struct_span_err!(
-                    infcx.tcx.sess, obligation.cause.span, E0281,
-                    "type mismatch: the type `{}` implements the trait `{}`, \
-                     but the trait `{}` is required ({})",
-                    expected_trait_ref.self_ty(),
-                    expected_trait_ref,
-                    actual_trait_ref,
-                    e);
-                note_obligation_cause(infcx, &mut err, obligation);
-                err.emit();
+            let expected_trait_ref = self.resolve_type_vars_if_possible(&*expected_trait_ref);
+            let actual_trait_ref = self.resolve_type_vars_if_possible(&*actual_trait_ref);
+            if actual_trait_ref.self_ty().references_error() {
+                return;
             }
+            struct_span_err!(self.tcx.sess, span, E0281,
+                "type mismatch: the type `{}` implements the trait `{}`, \
+                 but the trait `{}` is required ({})",
+                expected_trait_ref.self_ty(),
+                expected_trait_ref,
+                actual_trait_ref,
+                e)
         }
 
         TraitNotObjectSafe(did) => {
-            let violations = object_safety_violations(infcx.tcx, did);
-            let err = report_object_safety_error(infcx.tcx, obligation.cause.span, did,
-                                                 warning_node_id,
-                                                 violations);
-            if let Some(mut err) = err {
-                note_obligation_cause(infcx, &mut err, obligation);
-                err.emit();
+            let violations = self.tcx.object_safety_violations(did);
+            let err = self.tcx.report_object_safety_error(span, did,
+                                                          warning_node_id,
+                                                          violations);
+            if let Some(err) = err {
+                err
+            } else {
+                return;
             }
         }
-    }
+    };
+    self.note_obligation_cause(&mut err, obligation);
+    err.emit();
+}
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+pub fn recursive_type_with_infinite_size_error(&self,
+                                               type_def_id: DefId)
+                                               -> DiagnosticBuilder<'tcx>
+{
+    assert!(type_def_id.is_local());
+    let span = self.map.span_if_local(type_def_id).unwrap();
+    let mut err = struct_span_err!(self.sess, span, E0072, "recursive type `{}` has infinite size",
+                                   self.item_path_str(type_def_id));
+    err.help(&format!("insert indirection (e.g., a `Box`, `Rc`, or `&`) \
+                       at some point to make `{}` representable",
+                      self.item_path_str(type_def_id)));
+    err
 }
 
-pub fn report_object_safety_error<'tcx>(tcx: &TyCtxt<'tcx>,
-                                        span: Span,
-                                        trait_def_id: DefId,
-                                        warning_node_id: Option<ast::NodeId>,
-                                        violations: Vec<ObjectSafetyViolation>)
-                                        -> Option<DiagnosticBuilder<'tcx>>
+pub fn report_object_safety_error(&self,
+                                  span: Span,
+                                  trait_def_id: DefId,
+                                  warning_node_id: Option<ast::NodeId>,
+                                  violations: Vec<ObjectSafetyViolation>)
+                                  -> Option<DiagnosticBuilder<'tcx>>
 {
     let mut err = match warning_node_id {
         Some(_) => None,
         None => {
             Some(struct_span_err!(
-                tcx.sess, span, E0038,
+                self.sess, span, E0038,
                 "the trait `{}` cannot be made into an object",
-                tcx.item_path_str(trait_def_id)))
+                self.item_path_str(trait_def_id)))
         }
     };
 
@@ -652,7 +630,7 @@ pub fn report_object_safety_error<'tcx>(tcx: &TyCtxt<'tcx>,
         };
         match (warning_node_id, &mut err) {
             (Some(node_id), &mut None) => {
-                tcx.sess.add_lint(
+                self.sess.add_lint(
                     ::lint::builtin::OBJECT_UNSAFE_FRAGMENT,
                     node_id,
                     span,
@@ -666,15 +644,16 @@ pub fn report_object_safety_error<'tcx>(tcx: &TyCtxt<'tcx>,
     }
     err
 }
+}
 
-pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                        obligation: &PredicateObligation<'tcx>) {
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
     // Unable to successfully determine, probably means
     // insufficient type information, but could mean
     // ambiguous impls. The latter *ought* to be a
     // coherence violation, so we don't report it here.
 
-    let predicate = infcx.resolve_type_vars_if_possible(&obligation.predicate);
+    let predicate = self.resolve_type_vars_if_possible(&obligation.predicate);
 
     debug!("maybe_report_ambiguity(predicate={:?}, obligation={:?})",
            predicate,
@@ -682,7 +661,7 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 
     // Ambiguity errors are often caused as fallout from earlier
     // errors. So just ignore them if this infcx is tainted.
-    if infcx.is_tainted_by_errors() {
+    if self.is_tainted_by_errors() {
         return;
     }
 
@@ -717,18 +696,18 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                 // inhabited. But in any case I just threw in this check for
                 // has_errors() to be sure that compilation isn't happening
                 // anyway. In that case, why inundate the user.
-                if !infcx.tcx.sess.has_errors() {
+                if !self.tcx.sess.has_errors() {
                     if
-                        infcx.tcx.lang_items.sized_trait()
+                        self.tcx.lang_items.sized_trait()
                         .map_or(false, |sized_id| sized_id == trait_ref.def_id())
                     {
-                        need_type_info(infcx, obligation.cause.span, self_ty);
+                        self.need_type_info(obligation.cause.span, self_ty);
                     } else {
-                        let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0283,
+                        let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0283,
                                                        "type annotations required: \
                                                         cannot resolve `{}`",
                                                        predicate);
-                        note_obligation_cause(infcx, &mut err, obligation);
+                        self.note_obligation_cause(&mut err, obligation);
                         err.emit();
                     }
                 }
@@ -738,17 +717,17 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         ty::Predicate::WellFormed(ty) => {
             // Same hacky approach as above to avoid deluging user
             // with error messages.
-            if !ty.references_error() && !infcx.tcx.sess.has_errors() {
-                need_type_info(infcx, obligation.cause.span, ty);
+            if !ty.references_error() && !self.tcx.sess.has_errors() {
+                self.need_type_info(obligation.cause.span, ty);
             }
         }
 
         _ => {
-            if !infcx.tcx.sess.has_errors() {
-                let mut err = struct_span_err!(infcx.tcx.sess, obligation.cause.span, E0284,
+            if !self.tcx.sess.has_errors() {
+                let mut err = struct_span_err!(self.tcx.sess, obligation.cause.span, E0284,
                                                "type annotations required: cannot resolve `{}`",
                                                predicate);
-                note_obligation_cause(infcx, &mut err, obligation);
+                self.note_obligation_cause(&mut err, obligation);
                 err.emit();
             }
         }
@@ -757,10 +736,7 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 
 /// Returns whether the trait predicate may apply for *some* assignment
 /// to the type parameters.
-fn predicate_can_apply<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                 pred: ty::PolyTraitRef<'tcx>)
-                                 -> bool
-{
+fn predicate_can_apply(&self, pred: ty::PolyTraitRef<'tcx>) -> bool {
     struct ParamToVarFolder<'a, 'tcx: 'a> {
         infcx: &'a InferCtxt<'a, 'tcx>,
         var_map: FnvHashMap<Ty<'tcx>, Ty<'tcx>>
@@ -780,11 +756,11 @@ fn predicate_can_apply<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         }
     }
 
-    infcx.probe(|_| {
-        let mut selcx = SelectionContext::new(infcx);
+    self.probe(|_| {
+        let mut selcx = SelectionContext::new(self);
 
         let cleaned_pred = pred.fold_with(&mut ParamToVarFolder {
-            infcx: infcx,
+            infcx: self,
             var_map: FnvHashMap()
         });
 
@@ -804,34 +780,30 @@ fn predicate_can_apply<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 }
 
 
-fn need_type_info<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                            span: Span,
-                            ty: Ty<'tcx>)
-{
-    span_err!(infcx.tcx.sess, span, E0282,
+fn need_type_info(&self, span: Span, ty: Ty<'tcx>) {
+    span_err!(self.tcx.sess, span, E0282,
               "unable to infer enough type information about `{}`; \
                type annotations or generic parameter binding required",
               ty);
 }
 
-fn note_obligation_cause<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
-                                      err: &mut DiagnosticBuilder,
-                                      obligation: &Obligation<'tcx, T>)
+fn note_obligation_cause<T>(&self,
+                            err: &mut DiagnosticBuilder,
+                            obligation: &Obligation<'tcx, T>)
     where T: fmt::Display
 {
-    note_obligation_cause_code(infcx,
-                               err,
-                               &obligation.predicate,
-                               &obligation.cause.code);
+    self.note_obligation_cause_code(err,
+                                    &obligation.predicate,
+                                    &obligation.cause.code);
 }
 
-fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
-                                           err: &mut DiagnosticBuilder,
-                                           predicate: &T,
-                                           cause_code: &ObligationCauseCode<'tcx>)
+fn note_obligation_cause_code<T>(&self,
+                                 err: &mut DiagnosticBuilder,
+                                 predicate: &T,
+                                 cause_code: &ObligationCauseCode<'tcx>)
     where T: fmt::Display
 {
-    let tcx = infcx.tcx;
+    let tcx = self.tcx;
     match *cause_code {
         ObligationCauseCode::MiscObligation => { }
         ObligationCauseCode::SliceOrArrayElem => {
@@ -854,7 +826,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
         }
         ObligationCauseCode::ObjectCastObligation(object_ty) => {
             err.note(&format!("required for the cast to the object type `{}`",
-                              infcx.ty_to_string(object_ty)));
+                              self.ty_to_string(object_ty)));
         }
         ObligationCauseCode::RepeatVec => {
             err.note("the `Copy` trait is required because the \
@@ -891,26 +863,24 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
             err.note("shared static variables must have a type that implements `Sync`");
         }
         ObligationCauseCode::BuiltinDerivedObligation(ref data) => {
-            let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
+            let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
             err.note(&format!("required because it appears within the type `{}`",
                               parent_trait_ref.0.self_ty()));
             let parent_predicate = parent_trait_ref.to_predicate();
-            note_obligation_cause_code(infcx,
-                                       err,
-                                       &parent_predicate,
-                                       &data.parent_code);
+            self.note_obligation_cause_code(err,
+                                            &parent_predicate,
+                                            &data.parent_code);
         }
         ObligationCauseCode::ImplDerivedObligation(ref data) => {
-            let parent_trait_ref = infcx.resolve_type_vars_if_possible(&data.parent_trait_ref);
+            let parent_trait_ref = self.resolve_type_vars_if_possible(&data.parent_trait_ref);
             err.note(
                 &format!("required because of the requirements on the impl of `{}` for `{}`",
                          parent_trait_ref,
                          parent_trait_ref.0.self_ty()));
             let parent_predicate = parent_trait_ref.to_predicate();
-            note_obligation_cause_code(infcx,
-                                       err,
-                                       &parent_predicate,
-                                       &data.parent_code);
+            self.note_obligation_cause_code(err,
+                                            &parent_predicate,
+                                            &data.parent_code);
         }
         ObligationCauseCode::CompareImplMethodObligation => {
             err.note(
@@ -921,10 +891,11 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
     }
 }
 
-fn suggest_new_overflow_limit(tcx: &TyCtxt, err:&mut DiagnosticBuilder) {
-    let current_limit = tcx.sess.recursion_limit.get();
+fn suggest_new_overflow_limit(&self, err: &mut DiagnosticBuilder) {
+    let current_limit = self.tcx.sess.recursion_limit.get();
     let suggested_limit = current_limit * 2;
     err.note(&format!(
                       "consider adding a `#![recursion_limit=\"{}\"]` attribute to your crate",
                       suggested_limit));
 }
+}
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index a184e951b83..efee80c6566 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -21,16 +21,13 @@ use util::nodemap::{FnvHashMap, FnvHashSet, NodeMap};
 use super::CodeAmbiguity;
 use super::CodeProjectionError;
 use super::CodeSelectionError;
-use super::is_object_safe;
 use super::FulfillmentError;
 use super::FulfillmentErrorCode;
 use super::ObligationCause;
 use super::PredicateObligation;
 use super::project;
-use super::report_overflow_error_cycle;
 use super::select::SelectionContext;
 use super::Unimplemented;
-use super::util::predicate_for_builtin_bound;
 
 pub struct GlobalFulfilledPredicates<'tcx> {
     set: FnvHashSet<ty::PolyTraitPredicate<'tcx>>,
@@ -163,7 +160,7 @@ impl<'tcx> FulfillmentContext<'tcx> {
                                       builtin_bound: ty::BuiltinBound,
                                       cause: ObligationCause<'tcx>)
     {
-        match predicate_for_builtin_bound(infcx.tcx, cause, builtin_bound, 0, ty) {
+        match infcx.tcx.predicate_for_builtin_bound(cause, builtin_bound, 0, ty) {
             Ok(predicate) => {
                 self.register_predicate_obligation(infcx, predicate);
             }
@@ -449,7 +446,7 @@ fn process_child_obligations<'a,'tcx>(
                     debug!("process_child_obligations: coinductive match");
                     None
                 } else {
-                    report_overflow_error_cycle(selcx.infcx(), &cycle);
+                    selcx.infcx().report_overflow_error_cycle(&cycle);
                 }
             } else {
                 // Not a cycle. Just ignore this obligation then,
@@ -677,7 +674,7 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
         }
 
         ty::Predicate::ObjectSafe(trait_def_id) => {
-            if !is_object_safe(selcx.tcx(), trait_def_id) {
+            if !selcx.tcx().is_object_safe(trait_def_id) {
                 Err(CodeSelectionError(Unimplemented))
             } else {
                 Ok(Some(Vec::new()))
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index a4ea926e111..49851f720cc 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -19,46 +19,31 @@ use hir::def_id::DefId;
 use middle::free_region::FreeRegionMap;
 use ty::subst;
 use ty::{self, Ty, TypeFoldable};
-use infer::{fixup_err_to_string, InferCtxt};
+use infer::InferCtxt;
 
 use std::rc::Rc;
 use syntax::ast;
 use syntax::codemap::{Span, DUMMY_SP};
 
 pub use self::error_reporting::TraitErrorKey;
-pub use self::error_reporting::recursive_type_with_infinite_size_error;
-pub use self::error_reporting::report_fulfillment_errors;
-pub use self::error_reporting::report_fulfillment_errors_as_warnings;
-pub use self::error_reporting::report_overflow_error;
-pub use self::error_reporting::report_overflow_error_cycle;
-pub use self::error_reporting::report_selection_error;
-pub use self::error_reporting::report_object_safety_error;
 pub use self::coherence::orphan_check;
 pub use self::coherence::overlapping_impls;
 pub use self::coherence::OrphanCheckErr;
 pub use self::fulfill::{FulfillmentContext, GlobalFulfilledPredicates, RegionObligation};
 pub use self::project::{MismatchedProjectionTypes, ProjectionMode};
 pub use self::project::{normalize, Normalized};
-pub use self::object_safety::is_object_safe;
-pub use self::object_safety::astconv_object_safety_violations;
-pub use self::object_safety::object_safety_violations;
 pub use self::object_safety::ObjectSafetyViolation;
 pub use self::object_safety::MethodViolationCode;
-pub use self::object_safety::is_vtable_safe_method;
 pub use self::select::{EvaluationCache, SelectionContext, SelectionCache};
 pub use self::select::{MethodMatchResult, MethodMatched, MethodAmbiguous, MethodDidNotMatch};
 pub use self::select::{MethodMatchedData}; // intentionally don't export variants
 pub use self::specialize::{Overlap, specialization_graph, specializes, translate_substs};
 pub use self::util::elaborate_predicates;
-pub use self::util::get_vtable_index_of_object_method;
-pub use self::util::trait_ref_for_builtin_bound;
-pub use self::util::predicate_for_trait_def;
 pub use self::util::supertraits;
 pub use self::util::Supertraits;
 pub use self::util::supertrait_def_ids;
 pub use self::util::SupertraitDefIds;
 pub use self::util::transitive_bounds;
-pub use self::util::upcast;
 
 mod coherence;
 mod error_reporting;
@@ -343,7 +328,7 @@ pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
 
     let cause = ObligationCause::misc(span, ast::DUMMY_NODE_ID);
     let obligation =
-        util::predicate_for_builtin_bound(infcx.tcx, cause, bound, 0, ty);
+        infcx.tcx.predicate_for_builtin_bound(cause, bound, 0, ty);
     let obligation = match obligation {
         Ok(o) => o,
         Err(..) => return false
@@ -444,7 +429,7 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
                                            &infcx.parameter_environment.caller_bounds) {
         Ok(predicates) => predicates,
         Err(errors) => {
-            report_fulfillment_errors(&infcx, &errors);
+            infcx.report_fulfillment_errors(&errors);
             return infcx.parameter_environment; // an unnormalized env is better than nothing
         }
     };
@@ -464,8 +449,7 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
             // represents a legitimate failure due to some kind of
             // unconstrained variable, and it seems better not to ICE,
             // all things considered.
-            let err_msg = fixup_err_to_string(fixup_err);
-            tcx.sess.span_err(span, &err_msg);
+            tcx.sess.span_err(span, &fixup_err.to_string());
             return infcx.parameter_environment; // an unnormalized env is better than nothing
         }
     };
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 59db68b1c3c..ea129d437fb 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -53,15 +53,13 @@ pub enum MethodViolationCode {
     Generic,
 }
 
-pub fn is_object_safe<'tcx>(tcx: &TyCtxt<'tcx>,
-                            trait_def_id: DefId)
-                            -> bool
-{
+impl<'tcx> TyCtxt<'tcx> {
+pub fn is_object_safe(&self, trait_def_id: DefId) -> bool {
     // Because we query yes/no results frequently, we keep a cache:
-    let def = tcx.lookup_trait_def(trait_def_id);
+    let def = self.lookup_trait_def(trait_def_id);
 
     let result = def.object_safety().unwrap_or_else(|| {
-        let result = object_safety_violations(tcx, trait_def_id).is_empty();
+        let result = self.object_safety_violations(trait_def_id).is_empty();
 
         // Record just a yes/no result in the cache; this is what is
         // queried most frequently. Note that this may overwrite a
@@ -80,43 +78,40 @@ pub fn is_object_safe<'tcx>(tcx: &TyCtxt<'tcx>,
 /// astconv - currently, Self in supertraits. This is needed
 /// because `object_safety_violations` can't be used during
 /// type collection.
-pub fn astconv_object_safety_violations<'tcx>(tcx: &TyCtxt<'tcx>,
-                                              trait_def_id: DefId)
-                                              -> Vec<ObjectSafetyViolation<'tcx>>
+pub fn astconv_object_safety_violations(&self, trait_def_id: DefId)
+                                        -> Vec<ObjectSafetyViolation<'tcx>>
 {
     let mut violations = vec![];
 
-    if supertraits_reference_self(tcx, trait_def_id) {
+    if self.supertraits_reference_self(trait_def_id) {
         violations.push(ObjectSafetyViolation::SupertraitSelf);
     }
 
-    debug!("object_safety_violations_for_trait(trait_def_id={:?}) = {:?}",
+    debug!("astconv_object_safety_violations(trait_def_id={:?}) = {:?}",
            trait_def_id,
            violations);
 
     violations
 }
 
-pub fn object_safety_violations<'tcx>(tcx: &TyCtxt<'tcx>,
-                                      trait_def_id: DefId)
-                                      -> Vec<ObjectSafetyViolation<'tcx>>
+pub fn object_safety_violations(&self, trait_def_id: DefId)
+                                -> Vec<ObjectSafetyViolation<'tcx>>
 {
-    traits::supertrait_def_ids(tcx, trait_def_id)
-        .flat_map(|def_id| object_safety_violations_for_trait(tcx, def_id))
+    traits::supertrait_def_ids(self, trait_def_id)
+        .flat_map(|def_id| self.object_safety_violations_for_trait(def_id))
         .collect()
 }
 
-fn object_safety_violations_for_trait<'tcx>(tcx: &TyCtxt<'tcx>,
-                                            trait_def_id: DefId)
-                                            -> Vec<ObjectSafetyViolation<'tcx>>
+fn object_safety_violations_for_trait(&self, trait_def_id: DefId)
+                                      -> Vec<ObjectSafetyViolation<'tcx>>
 {
     // Check methods for violations.
     let mut violations: Vec<_> =
-        tcx.trait_items(trait_def_id).iter()
+        self.trait_items(trait_def_id).iter()
         .filter_map(|item| {
             match *item {
                 ty::MethodTraitItem(ref m) => {
-                    object_safety_violation_for_method(tcx, trait_def_id, &m)
+                    self.object_safety_violation_for_method(trait_def_id, &m)
                         .map(|code| ObjectSafetyViolation::Method(m.clone(), code))
                 }
                 _ => None,
@@ -125,10 +120,10 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &TyCtxt<'tcx>,
         .collect();
 
     // Check the trait itself.
-    if trait_has_sized_self(tcx, trait_def_id) {
+    if self.trait_has_sized_self(trait_def_id) {
         violations.push(ObjectSafetyViolation::SizedSelf);
     }
-    if supertraits_reference_self(tcx, trait_def_id) {
+    if self.supertraits_reference_self(trait_def_id) {
         violations.push(ObjectSafetyViolation::SupertraitSelf);
     }
 
@@ -139,18 +134,15 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &TyCtxt<'tcx>,
     violations
 }
 
-pub fn supertraits_reference_self<'tcx>(tcx: &TyCtxt<'tcx>,
-                                        trait_def_id: DefId)
-                                        -> bool
-{
-    let trait_def = tcx.lookup_trait_def(trait_def_id);
+fn supertraits_reference_self(&self, trait_def_id: DefId) -> bool {
+    let trait_def = self.lookup_trait_def(trait_def_id);
     let trait_ref = trait_def.trait_ref.clone();
     let trait_ref = trait_ref.to_poly_trait_ref();
-    let predicates = tcx.lookup_super_predicates(trait_def_id);
+    let predicates = self.lookup_super_predicates(trait_def_id);
     predicates
         .predicates
         .into_iter()
-        .map(|predicate| predicate.subst_supertrait(tcx, &trait_ref))
+        .map(|predicate| predicate.subst_supertrait(self, &trait_ref))
         .any(|predicate| {
             match predicate {
                 ty::Predicate::Trait(ref data) => {
@@ -174,30 +166,27 @@ pub fn supertraits_reference_self<'tcx>(tcx: &TyCtxt<'tcx>,
         })
 }
 
-fn trait_has_sized_self<'tcx>(tcx: &TyCtxt<'tcx>,
-                              trait_def_id: DefId)
-                              -> bool
-{
-    let trait_def = tcx.lookup_trait_def(trait_def_id);
-    let trait_predicates = tcx.lookup_predicates(trait_def_id);
-    generics_require_sized_self(tcx, &trait_def.generics, &trait_predicates)
+fn trait_has_sized_self(&self, trait_def_id: DefId) -> bool {
+    let trait_def = self.lookup_trait_def(trait_def_id);
+    let trait_predicates = self.lookup_predicates(trait_def_id);
+    self.generics_require_sized_self(&trait_def.generics, &trait_predicates)
 }
 
-fn generics_require_sized_self<'tcx>(tcx: &TyCtxt<'tcx>,
-                                     generics: &ty::Generics<'tcx>,
-                                     predicates: &ty::GenericPredicates<'tcx>)
-                                     -> bool
+fn generics_require_sized_self(&self,
+                               generics: &ty::Generics<'tcx>,
+                               predicates: &ty::GenericPredicates<'tcx>)
+                               -> bool
 {
-    let sized_def_id = match tcx.lang_items.sized_trait() {
+    let sized_def_id = match self.lang_items.sized_trait() {
         Some(def_id) => def_id,
         None => { return false; /* No Sized trait, can't require it! */ }
     };
 
     // Search for a predicate like `Self : Sized` amongst the trait bounds.
-    let free_substs = tcx.construct_free_substs(generics,
-                                                tcx.region_maps.node_extent(ast::DUMMY_NODE_ID));
-    let predicates = predicates.instantiate(tcx, &free_substs).predicates.into_vec();
-    elaborate_predicates(tcx, predicates)
+    let free_substs = self.construct_free_substs(generics,
+        self.region_maps.node_extent(ast::DUMMY_NODE_ID));
+    let predicates = predicates.instantiate(self, &free_substs).predicates.into_vec();
+    elaborate_predicates(self, predicates)
         .any(|predicate| {
             match predicate {
                 ty::Predicate::Trait(ref trait_pred) if trait_pred.def_id() == sized_def_id => {
@@ -219,40 +208,40 @@ fn generics_require_sized_self<'tcx>(tcx: &TyCtxt<'tcx>,
 }
 
 /// Returns `Some(_)` if this method makes the containing trait not object safe.
-fn object_safety_violation_for_method<'tcx>(tcx: &TyCtxt<'tcx>,
-                                            trait_def_id: DefId,
-                                            method: &ty::Method<'tcx>)
-                                            -> Option<MethodViolationCode>
+fn object_safety_violation_for_method(&self,
+                                      trait_def_id: DefId,
+                                      method: &ty::Method<'tcx>)
+                                      -> Option<MethodViolationCode>
 {
     // Any method that has a `Self : Sized` requisite is otherwise
     // exempt from the regulations.
-    if generics_require_sized_self(tcx, &method.generics, &method.predicates) {
+    if self.generics_require_sized_self(&method.generics, &method.predicates) {
         return None;
     }
 
-    virtual_call_violation_for_method(tcx, trait_def_id, method)
+    self.virtual_call_violation_for_method(trait_def_id, method)
 }
 
 /// We say a method is *vtable safe* if it can be invoked on a trait
 /// object.  Note that object-safe traits can have some
 /// non-vtable-safe methods, so long as they require `Self:Sized` or
 /// otherwise ensure that they cannot be used when `Self=Trait`.
-pub fn is_vtable_safe_method<'tcx>(tcx: &TyCtxt<'tcx>,
-                                   trait_def_id: DefId,
-                                   method: &ty::Method<'tcx>)
-                                   -> bool
+pub fn is_vtable_safe_method(&self,
+                             trait_def_id: DefId,
+                             method: &ty::Method<'tcx>)
+                             -> bool
 {
-    virtual_call_violation_for_method(tcx, trait_def_id, method).is_none()
+    self.virtual_call_violation_for_method(trait_def_id, method).is_none()
 }
 
 /// Returns `Some(_)` if this method cannot be called on a trait
 /// object; this does not necessarily imply that the enclosing trait
 /// is not object safe, because the method might have a where clause
 /// `Self:Sized`.
-fn virtual_call_violation_for_method<'tcx>(tcx: &TyCtxt<'tcx>,
-                                           trait_def_id: DefId,
-                                           method: &ty::Method<'tcx>)
-                                           -> Option<MethodViolationCode>
+fn virtual_call_violation_for_method(&self,
+                                     trait_def_id: DefId,
+                                     method: &ty::Method<'tcx>)
+                                     -> Option<MethodViolationCode>
 {
     // The method's first parameter must be something that derefs (or
     // autorefs) to `&self`. For now, we only accept `self`, `&self`
@@ -272,12 +261,12 @@ fn virtual_call_violation_for_method<'tcx>(tcx: &TyCtxt<'tcx>,
     // arguments or return type apart from the receiver.
     let ref sig = method.fty.sig;
     for &input_ty in &sig.0.inputs[1..] {
-        if contains_illegal_self_type_reference(tcx, trait_def_id, input_ty) {
+        if self.contains_illegal_self_type_reference(trait_def_id, input_ty) {
             return Some(MethodViolationCode::ReferencesSelf);
         }
     }
     if let ty::FnConverging(result_type) = sig.0.output {
-        if contains_illegal_self_type_reference(tcx, trait_def_id, result_type) {
+        if self.contains_illegal_self_type_reference(trait_def_id, result_type) {
             return Some(MethodViolationCode::ReferencesSelf);
         }
     }
@@ -290,10 +279,10 @@ fn virtual_call_violation_for_method<'tcx>(tcx: &TyCtxt<'tcx>,
     None
 }
 
-fn contains_illegal_self_type_reference<'tcx>(tcx: &TyCtxt<'tcx>,
-                                              trait_def_id: DefId,
-                                              ty: Ty<'tcx>)
-                                              -> bool
+fn contains_illegal_self_type_reference(&self,
+                                        trait_def_id: DefId,
+                                        ty: Ty<'tcx>)
+                                        -> bool
 {
     // This is somewhat subtle. In general, we want to forbid
     // references to `Self` in the argument and return types,
@@ -351,9 +340,9 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &TyCtxt<'tcx>,
 
                 // Compute supertraits of current trait lazily.
                 if supertraits.is_none() {
-                    let trait_def = tcx.lookup_trait_def(trait_def_id);
+                    let trait_def = self.lookup_trait_def(trait_def_id);
                     let trait_ref = ty::Binder(trait_def.trait_ref.clone());
-                    supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
+                    supertraits = Some(traits::supertraits(self, trait_ref).collect());
                 }
 
                 // Determine whether the trait reference `Foo as
@@ -381,3 +370,4 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &TyCtxt<'tcx>,
 
     error
 }
+}
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 7fb13f49cb4..bc26ee615f7 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -11,7 +11,6 @@
 //! Code for projecting associated types out of trait references.
 
 use super::elaborate_predicates;
-use super::report_overflow_error;
 use super::specialization_graph;
 use super::translate_substs;
 use super::Obligation;
@@ -188,7 +187,7 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
         let skol_obligation = obligation.with(skol_predicate);
         match project_and_unify_type(selcx, &skol_obligation) {
             Ok(result) => {
-                match infcx.leak_check(&skol_map, snapshot) {
+                match infcx.leak_check(false, &skol_map, snapshot) {
                     Ok(()) => Ok(infcx.plug_leaks(skol_map, snapshot, &result)),
                     Err(e) => Err(MismatchedProjectionTypes { err: e }),
                 }
@@ -231,7 +230,7 @@ fn project_and_unify_type<'cx,'tcx>(
 
     let infcx = selcx.infcx();
     let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span);
-    match infer::mk_eqty(infcx, true, origin, normalized_ty, obligation.predicate.ty) {
+    match infcx.eq_types(true, origin, normalized_ty, obligation.predicate.ty) {
         Ok(InferOk { obligations: inferred_obligations, .. }) => {
             // FIXME(#32730) propagate obligations
             assert!(inferred_obligations.is_empty());
@@ -262,11 +261,10 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
             let closure_typer = selcx.closure_typer();
             let closure_type = closure_typer.closure_type(closure_def_id, substs);
             let ty::Binder((_, ret_type)) =
-                util::closure_trait_ref_and_return_type(infcx.tcx,
-                                                        def_id,
-                                                        self_ty,
-                                                        &closure_type.sig,
-                                                        util::TupleArgumentsFlag::No);
+                infcx.tcx.closure_trait_ref_and_return_type(def_id,
+                                                            self_ty,
+                                                            &closure_type.sig,
+                                                            util::TupleArgumentsFlag::No);
             // We don't have to normalize the return type here - this is only
             // reached for TyClosure: Fn inputs where the closure kind is
             // still unknown, which should only occur in typeck where the
@@ -281,7 +279,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
                    ret_type);
             let origin = TypeOrigin::RelateOutputImplTypes(obligation.cause.span);
             let obligation_ty = obligation.predicate.ty;
-            match infer::mk_eqty(infcx, true, origin, obligation_ty, ret_type) {
+            match infcx.eq_types(true, origin, obligation_ty, ret_type) {
                 Ok(InferOk { obligations, .. }) => {
                     // FIXME(#32730) propagate obligations
                     assert!(obligations.is_empty());
@@ -578,7 +576,7 @@ fn project_type<'cx,'tcx>(
     let recursion_limit = selcx.tcx().sess.recursion_limit.get();
     if obligation.recursion_depth >= recursion_limit {
         debug!("project: overflow!");
-        report_overflow_error(selcx.infcx(), &obligation, true);
+        selcx.infcx().report_overflow_error(&obligation, true);
     }
 
     let obligation_trait_ref =
@@ -1053,11 +1051,10 @@ fn confirm_callable_candidate<'cx,'tcx>(
 
     // Note: we unwrap the binder here but re-create it below (1)
     let ty::Binder((trait_ref, ret_type)) =
-        util::closure_trait_ref_and_return_type(tcx,
-                                                fn_once_def_id,
-                                                obligation.predicate.trait_ref.self_ty(),
-                                                fn_sig,
-                                                flag);
+        tcx.closure_trait_ref_and_return_type(fn_once_def_id,
+                                              obligation.predicate.trait_ref.self_ty(),
+                                              fn_sig,
+                                              flag);
 
     let predicate = ty::Binder(ty::ProjectionPredicate { // (1) recreate binder here
         projection_ty: ty::ProjectionTy {
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 138ca7a0f35..c47f728eec5 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -20,7 +20,6 @@ use super::DerivedObligationCause;
 use super::project;
 use super::project::{normalize_with_depth, Normalized};
 use super::{PredicateObligation, TraitObligation, ObligationCause};
-use super::report_overflow_error;
 use super::{ObligationCauseCode, BuiltinDerivedObligation, ImplDerivedObligation};
 use super::{SelectionError, Unimplemented, OutputTypeParameterMismatch};
 use super::{ObjectCastObligation, Obligation};
@@ -32,7 +31,6 @@ use super::{VtableBuiltin, VtableImpl, VtableParam, VtableClosure,
             VtableFnPointer, VtableObject, VtableDefaultImpl};
 use super::{VtableImplData, VtableObjectData, VtableBuiltinData,
             VtableClosureData, VtableDefaultImplData};
-use super::object_safety;
 use super::util;
 
 use hir::def_id::DefId;
@@ -455,7 +453,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             ty::Predicate::ObjectSafe(trait_def_id) => {
-                if object_safety::is_object_safe(self.tcx(), trait_def_id) {
+                if self.tcx().is_object_safe(trait_def_id) {
                     EvaluatedToOk
                 } else {
                     EvaluatedToErr
@@ -683,7 +681,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // not update) the cache.
         let recursion_limit = self.infcx.tcx.sess.recursion_limit.get();
         if stack.obligation.recursion_depth >= recursion_limit {
-            report_overflow_error(self.infcx(), &stack.obligation, true);
+            self.infcx().report_overflow_error(&stack.obligation, true);
         }
 
         // Check the cache. Note that we skolemize the trait-ref
@@ -1155,7 +1153,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             Err(_) => { return false; }
         }
 
-        self.infcx.leak_check(skol_map, snapshot).is_ok()
+        self.infcx.leak_check(false, skol_map, snapshot).is_ok()
     }
 
     /// Given an obligation like `<SomeTrait for T>`, search the obligations that the caller
@@ -1397,7 +1395,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // these cases wind up being considered ambiguous due to a
         // (spurious) ambiguity introduced here.
         let predicate_trait_ref = obligation.predicate.to_poly_trait_ref();
-        if !object_safety::is_object_safe(self.tcx(), predicate_trait_ref.def_id()) {
+        if !self.tcx().is_object_safe(predicate_trait_ref.def_id()) {
             return;
         }
 
@@ -1855,7 +1853,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                                   recursion_depth,
                                                   &skol_ty);
                 let skol_obligation =
-                    util::predicate_for_trait_def(self.tcx(),
+                    self.tcx().predicate_for_trait_def(
                                                   cause.clone(),
                                                   trait_def_id,
                                                   recursion_depth,
@@ -2226,7 +2224,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             // entries, so that we can compute the offset for the selected
             // trait.
             vtable_base =
-                nonmatching.map(|t| util::count_own_vtable_entries(self.tcx(), t))
+                nonmatching.map(|t| self.tcx().count_own_vtable_entries(t))
                            .sum();
 
         }
@@ -2248,11 +2246,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
         let sig = self_ty.fn_sig();
         let trait_ref =
-            util::closure_trait_ref_and_return_type(self.tcx(),
-                                                    obligation.predicate.def_id(),
-                                                    self_ty,
-                                                    sig,
-                                                    util::TupleArgumentsFlag::Yes)
+            self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
+                                                         self_ty,
+                                                         sig,
+                                                         util::TupleArgumentsFlag::Yes)
             .map_bound(|(trait_ref, _)| trait_ref);
 
         self.confirm_poly_trait_refs(obligation.cause.clone(),
@@ -2396,7 +2393,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 //                    })
 //                    .chain(Some(data.principal_def_id()));
                 if let Some(did) = object_dids.find(|did| {
-                    !object_safety::is_object_safe(tcx, *did)
+                    !tcx.is_object_safe(*did)
                 }) {
                     return Err(TraitNotObjectSafe(did))
                 }
@@ -2422,7 +2419,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 // object type is Foo+Send, this would create an obligation
                 // for the Send check.)
                 for bound in &builtin_bounds {
-                    if let Ok(tr) = util::trait_ref_for_builtin_bound(tcx, bound, source) {
+                    if let Ok(tr) = tcx.trait_ref_for_builtin_bound(bound, source) {
                         push(tr.to_predicate());
                     } else {
                         return Err(Unimplemented);
@@ -2511,7 +2508,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 assert!(obligations.is_empty());
 
                 // Construct the nested Field<T>: Unsize<Field<U>> predicate.
-                nested.push(util::predicate_for_trait_def(tcx,
+                nested.push(tcx.predicate_for_trait_def(
                     obligation.cause.clone(),
                     obligation.predicate.def_id(),
                     obligation.recursion_depth + 1,
@@ -2605,7 +2602,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // FIXME(#32730) propagate obligations
         assert!(obligations.is_empty());
 
-        if let Err(e) = self.infcx.leak_check(&skol_map, snapshot) {
+        if let Err(e) = self.infcx.leak_check(false, &skol_map, snapshot) {
             debug!("match_impl: failed leak check due to `{}`", e);
             return Err(());
         }
@@ -2710,11 +2707,10 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     {
         let closure_type = self.infcx.closure_type(closure_def_id, substs);
         let ty::Binder((trait_ref, _)) =
-            util::closure_trait_ref_and_return_type(self.tcx(),
-                                                    obligation.predicate.def_id(),
-                                                    obligation.predicate.0.self_ty(), // (1)
-                                                    &closure_type.sig,
-                                                    util::TupleArgumentsFlag::No);
+            self.tcx().closure_trait_ref_and_return_type(obligation.predicate.def_id(),
+                                                         obligation.predicate.0.self_ty(), // (1)
+                                                         &closure_type.sig,
+                                                         util::TupleArgumentsFlag::No);
         // (1) Feels icky to skip the binder here, but OTOH we know
         // that the self-type is an unboxed closure type and hence is
         // in fact unparameterized (or at least does not reference any
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 0b075789f19..3d80e149f4f 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -21,7 +21,7 @@ use super::{SelectionContext, FulfillmentContext};
 use super::util::{fresh_type_vars_for_impl, impl_trait_ref_and_oblig};
 
 use hir::def_id::DefId;
-use infer::{self, InferCtxt, TypeOrigin};
+use infer::{InferCtxt, TypeOrigin};
 use middle::region;
 use ty::subst::{Subst, Substs};
 use traits::{self, ProjectionMode, ObligationCause, Normalized};
@@ -177,11 +177,10 @@ fn fulfill_implication<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                                                        &target_substs);
 
         // do the impls unify? If not, no specialization.
-        if let Err(_) = infer::mk_eq_trait_refs(&infcx,
-                                                true,
-                                                TypeOrigin::Misc(DUMMY_SP),
-                                                source_trait_ref,
-                                                target_trait_ref) {
+        if let Err(_) = infcx.eq_trait_refs(true,
+                                            TypeOrigin::Misc(DUMMY_SP),
+                                            source_trait_ref,
+                                            target_trait_ref) {
             debug!("fulfill_implication: {:?} does not unify with {:?}",
                    source_trait_ref,
                    target_trait_ref);
@@ -196,7 +195,7 @@ fn fulfill_implication<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             fulfill_cx.register_predicate_obligation(&infcx, oblig);
         }
 
-        if let Err(errors) = infer::drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()) {
+        if let Err(errors) = infcx.drain_fulfillment_cx(&mut fulfill_cx, &()) {
             // no dice!
             debug!("fulfill_implication: for impls on {:?} and {:?}, could not fulfill: {:?} given \
                     {:?}",
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index d82f9d7549d..629b1152b60 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -378,41 +378,40 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
     }).collect()
 }
 
-pub fn trait_ref_for_builtin_bound<'tcx>(
-    tcx: &TyCtxt<'tcx>,
+pub fn predicate_for_trait_ref<'tcx>(
+    cause: ObligationCause<'tcx>,
+    trait_ref: ty::TraitRef<'tcx>,
+    recursion_depth: usize)
+    -> PredicateObligation<'tcx>
+{
+    Obligation {
+        cause: cause,
+        recursion_depth: recursion_depth,
+        predicate: trait_ref.to_predicate(),
+    }
+}
+
+impl<'tcx> TyCtxt<'tcx> {
+pub fn trait_ref_for_builtin_bound(&self,
     builtin_bound: ty::BuiltinBound,
     param_ty: Ty<'tcx>)
     -> Result<ty::TraitRef<'tcx>, ErrorReported>
 {
-    match tcx.lang_items.from_builtin_kind(builtin_bound) {
+    match self.lang_items.from_builtin_kind(builtin_bound) {
         Ok(def_id) => {
             Ok(ty::TraitRef {
                 def_id: def_id,
-                substs: tcx.mk_substs(Substs::empty().with_self_ty(param_ty))
+                substs: self.mk_substs(Substs::empty().with_self_ty(param_ty))
             })
         }
         Err(e) => {
-            tcx.sess.err(&e);
+            self.sess.err(&e);
             Err(ErrorReported)
         }
     }
 }
 
-pub fn predicate_for_trait_ref<'tcx>(
-    cause: ObligationCause<'tcx>,
-    trait_ref: ty::TraitRef<'tcx>,
-    recursion_depth: usize)
-    -> PredicateObligation<'tcx>
-{
-    Obligation {
-        cause: cause,
-        recursion_depth: recursion_depth,
-        predicate: trait_ref.to_predicate(),
-    }
-}
-
-pub fn predicate_for_trait_def<'tcx>(
-    tcx: &TyCtxt<'tcx>,
+pub fn predicate_for_trait_def(&self,
     cause: ObligationCause<'tcx>,
     trait_def_id: DefId,
     recursion_depth: usize,
@@ -422,36 +421,35 @@ pub fn predicate_for_trait_def<'tcx>(
 {
     let trait_ref = ty::TraitRef {
         def_id: trait_def_id,
-        substs: tcx.mk_substs(Substs::new_trait(ty_params, vec![], param_ty))
+        substs: self.mk_substs(Substs::new_trait(ty_params, vec![], param_ty))
     };
     predicate_for_trait_ref(cause, trait_ref, recursion_depth)
 }
 
-pub fn predicate_for_builtin_bound<'tcx>(
-    tcx: &TyCtxt<'tcx>,
+pub fn predicate_for_builtin_bound(&self,
     cause: ObligationCause<'tcx>,
     builtin_bound: ty::BuiltinBound,
     recursion_depth: usize,
     param_ty: Ty<'tcx>)
     -> Result<PredicateObligation<'tcx>, ErrorReported>
 {
-    let trait_ref = trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty)?;
+    let trait_ref = self.trait_ref_for_builtin_bound(builtin_bound, param_ty)?;
     Ok(predicate_for_trait_ref(cause, trait_ref, recursion_depth))
 }
 
 /// Cast a trait reference into a reference to one of its super
 /// traits; returns `None` if `target_trait_def_id` is not a
 /// supertrait.
-pub fn upcast<'tcx>(tcx: &TyCtxt<'tcx>,
-                    source_trait_ref: ty::PolyTraitRef<'tcx>,
-                    target_trait_def_id: DefId)
-                    -> Vec<ty::PolyTraitRef<'tcx>>
+pub fn upcast_choices(&self,
+                      source_trait_ref: ty::PolyTraitRef<'tcx>,
+                      target_trait_def_id: DefId)
+                      -> Vec<ty::PolyTraitRef<'tcx>>
 {
     if source_trait_ref.def_id() == target_trait_def_id {
         return vec![source_trait_ref]; // shorcut the most common case
     }
 
-    supertraits(tcx, source_trait_ref)
+    supertraits(self, source_trait_ref)
         .filter(|r| r.def_id() == target_trait_def_id)
         .collect()
 }
@@ -459,13 +457,11 @@ pub fn upcast<'tcx>(tcx: &TyCtxt<'tcx>,
 /// Given a trait `trait_ref`, returns the number of vtable entries
 /// that come from `trait_ref`, excluding its supertraits. Used in
 /// computing the vtable base for an upcast trait of a trait object.
-pub fn count_own_vtable_entries<'tcx>(tcx: &TyCtxt<'tcx>,
-                                      trait_ref: ty::PolyTraitRef<'tcx>)
-                                      -> usize {
+pub fn count_own_vtable_entries(&self, trait_ref: ty::PolyTraitRef<'tcx>) -> usize {
     let mut entries = 0;
     // Count number of methods and add them to the total offset.
     // Skip over associated types and constants.
-    for trait_item in &tcx.trait_items(trait_ref.def_id())[..] {
+    for trait_item in &self.trait_items(trait_ref.def_id())[..] {
         if let ty::MethodTraitItem(_) = *trait_item {
             entries += 1;
         }
@@ -476,14 +472,14 @@ pub fn count_own_vtable_entries<'tcx>(tcx: &TyCtxt<'tcx>,
 /// Given an upcast trait object described by `object`, returns the
 /// index of the method `method_def_id` (which should be part of
 /// `object.upcast_trait_ref`) within the vtable for `object`.
-pub fn get_vtable_index_of_object_method<'tcx>(tcx: &TyCtxt<'tcx>,
-                                               object: &super::VtableObjectData<'tcx>,
-                                               method_def_id: DefId) -> usize {
+pub fn get_vtable_index_of_object_method(&self,
+                                         object: &super::VtableObjectData<'tcx>,
+                                         method_def_id: DefId) -> usize {
     // Count number of methods preceding the one we are selecting and
     // add them to the total offset.
     // Skip over associated types and constants.
     let mut entries = object.vtable_base;
-    for trait_item in &tcx.trait_items(object.upcast_trait_ref.def_id())[..] {
+    for trait_item in &self.trait_items(object.upcast_trait_ref.def_id())[..] {
         if trait_item.def_id() == method_def_id {
             // The item with the ID we were given really ought to be a method.
             assert!(match *trait_item {
@@ -502,10 +498,7 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &TyCtxt<'tcx>,
          method_def_id);
 }
 
-pub enum TupleArgumentsFlag { Yes, No }
-
-pub fn closure_trait_ref_and_return_type<'tcx>(
-    tcx: &TyCtxt<'tcx>,
+pub fn closure_trait_ref_and_return_type(&self,
     fn_trait_def_id: DefId,
     self_ty: Ty<'tcx>,
     sig: &ty::PolyFnSig<'tcx>,
@@ -514,12 +507,15 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
 {
     let arguments_tuple = match tuple_arguments {
         TupleArgumentsFlag::No => sig.0.inputs[0],
-        TupleArgumentsFlag::Yes => tcx.mk_tup(sig.0.inputs.to_vec()),
+        TupleArgumentsFlag::Yes => self.mk_tup(sig.0.inputs.to_vec()),
     };
     let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty);
     let trait_ref = ty::TraitRef {
         def_id: fn_trait_def_id,
-        substs: tcx.mk_substs(trait_substs),
+        substs: self.mk_substs(trait_substs),
     };
-    ty::Binder((trait_ref, sig.0.output.unwrap_or(tcx.mk_nil())))
+    ty::Binder((trait_ref, sig.0.output.unwrap_or(self.mk_nil())))
 }
+}
+
+pub enum TupleArgumentsFlag { Yes, No }
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index 3ea691b4dc7..bcdc9feab5b 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -12,7 +12,7 @@ pub use self::Integer::*;
 pub use self::Layout::*;
 pub use self::Primitive::*;
 
-use infer::{InferCtxt, drain_fulfillment_cx_or_panic};
+use infer::InferCtxt;
 use session::Session;
 use traits;
 use ty::{self, Ty, TyCtxt, TypeFoldable};
@@ -754,7 +754,7 @@ fn normalize_associated_type<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         fulfill_cx.register_predicate_obligation(infcx, obligation);
     }
 
-    drain_fulfillment_cx_or_panic(DUMMY_SP, infcx, &mut fulfill_cx, &result)
+    infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
 }
 
 impl Layout {
diff --git a/src/librustc/ty/outlives.rs b/src/librustc/ty/outlives.rs
index 898c9d65c78..ed50d151a2a 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -55,20 +55,18 @@ pub enum Component<'tcx> {
     EscapingProjection(Vec<Component<'tcx>>),
 }
 
+impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 /// Returns all the things that must outlive `'a` for the condition
 /// `ty0: 'a` to hold.
-pub fn components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                           ty0: Ty<'tcx>)
+pub fn outlives_components(&self, ty0: Ty<'tcx>)
                            -> Vec<Component<'tcx>> {
     let mut components = vec![];
-    compute_components(infcx, ty0, &mut components);
+    self.compute_components(ty0, &mut components);
     debug!("components({:?}) = {:?}", ty0, components);
     components
 }
 
-fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                               ty: Ty<'tcx>,
-                               out: &mut Vec<Component<'tcx>>) {
+fn compute_components(&self, ty: Ty<'tcx>, out: &mut Vec<Component<'tcx>>) {
     // Descend through the types, looking for the various "base"
     // components and collecting them into `out`. This is not written
     // with `collect()` because of the need to sometimes skip subtrees
@@ -114,7 +112,7 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
             // taking into consideration UFCS and so forth.
 
             for &upvar_ty in &substs.upvar_tys {
-                compute_components(infcx, upvar_ty, out);
+                self.compute_components(upvar_ty, out);
             }
         }
 
@@ -145,7 +143,7 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                 // fallback case: hard code
                 // OutlivesProjectionComponents.  Continue walking
                 // through and constrain Pi.
-                let subcomponents = capture_components(infcx, ty);
+                let subcomponents = self.capture_components(ty);
                 out.push(Component::EscapingProjection(subcomponents));
             }
         }
@@ -154,11 +152,11 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
         // and proceed with resolved version. If we cannot resolve it,
         // then record the unresolved variable as a component.
         ty::TyInfer(_) => {
-            let ty = infcx.resolve_type_vars_if_possible(&ty);
+            let ty = self.resolve_type_vars_if_possible(&ty);
             if let ty::TyInfer(infer_ty) = ty.sty {
                 out.push(Component::UnresolvedInferenceVariable(infer_ty));
             } else {
-                compute_components(infcx, ty, out);
+                self.compute_components(ty, out);
             }
         }
 
@@ -194,22 +192,21 @@ fn compute_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
 
             push_region_constraints(out, ty.regions());
             for subty in ty.walk_shallow() {
-                compute_components(infcx, subty, out);
+                self.compute_components(subty, out);
             }
         }
     }
 }
 
-fn capture_components<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
-                               ty: Ty<'tcx>)
-                               -> Vec<Component<'tcx>> {
+fn capture_components(&self, ty: Ty<'tcx>) -> Vec<Component<'tcx>> {
     let mut temp = vec![];
     push_region_constraints(&mut temp, ty.regions());
     for subty in ty.walk_shallow() {
-        compute_components(infcx, subty, &mut temp);
+        self.compute_components(subty, &mut temp);
     }
     temp
 }
+}
 
 fn push_region_constraints<'tcx>(out: &mut Vec<Component<'tcx>>, regions: Vec<ty::Region>) {
     for r in regions {
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 600ffc3da66..05d1dc75530 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -14,7 +14,6 @@ use middle::cstore;
 use hir::def_id::DefId;
 use middle::region;
 use ty::subst::{self, Substs};
-use traits;
 use ty::{self, AdtDef, ToPredicate, TypeFlags, Ty, TyCtxt, TyS, TypeFoldable};
 use util::common::ErrorReported;
 
@@ -633,7 +632,7 @@ pub struct DebruijnIndex {
 /// to be used. These also support explicit bounds: both the internally-stored
 /// *scope*, which the region is assumed to outlive, as well as other
 /// relations stored in the `FreeRegionMap`. Note that these relations
-/// aren't checked when you `make_subregion` (or `mk_eqty`), only by
+/// aren't checked when you `make_subregion` (or `eq_types`), only by
 /// `resolve_regions_and_report_errors`.
 ///
 /// When working with higher-ranked types, some region relations aren't
@@ -778,7 +777,7 @@ impl BuiltinBounds {
                                tcx: &TyCtxt<'tcx>,
                                self_ty: Ty<'tcx>) -> Vec<ty::Predicate<'tcx>> {
         self.iter().filter_map(|builtin_bound|
-            match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, self_ty) {
+            match tcx.trait_ref_for_builtin_bound(builtin_bound, self_ty) {
                 Ok(trait_ref) => Some(trait_ref.to_predicate()),
                 Err(ErrorReported) => { None }
             }
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index e362e295b41..c7cd900aa9a 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -10,7 +10,7 @@
 
 use hir::def_id::DefId;
 use infer::InferCtxt;
-use ty::outlives::{self, Component};
+use ty::outlives::Component;
 use ty::subst::Substs;
 use traits;
 use ty::{self, ToPredicate, Ty, TyCtxt, TypeFoldable};
@@ -182,7 +182,7 @@ pub fn implied_bounds<'a,'tcx>(
                         match infcx.tcx.no_late_bound_regions(data) {
                             None => vec![],
                             Some(ty::OutlivesPredicate(ty_a, r_b)) => {
-                                let components = outlives::components(infcx, ty_a);
+                                let components = infcx.outlives_components(ty_a);
                                 implied_bounds_from_components(r_b, components)
                             }
                         },
@@ -288,9 +288,7 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
                      rfc1592: bool) {
         if !subty.has_escaping_regions() {
             let cause = self.cause(cause);
-            match traits::trait_ref_for_builtin_bound(self.infcx.tcx,
-                                                      ty::BoundSized,
-                                                      subty) {
+            match self.infcx.tcx.trait_ref_for_builtin_bound(ty::BoundSized, subty) {
                 Ok(trait_ref) => {
                     let predicate = trait_ref.to_predicate();
                     let predicate = if rfc1592 {
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 92dd1c5fa17..ba29a6703e5 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -26,7 +26,6 @@ use rustc::hir::pat_util::def_to_path;
 use rustc::ty::{self, Ty, TyCtxt, subst};
 use rustc::ty::util::IntTypeExt;
 use rustc::traits::ProjectionMode;
-use rustc::middle::astconv_util::ast_ty_to_prim_ty;
 use rustc::util::nodemap::NodeMap;
 use rustc::lint;
 
@@ -100,7 +99,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
             None => None,
             Some(ast_map::NodeItem(it)) => match it.node {
                 hir::ItemConst(ref ty, ref const_expr) => {
-                    Some((&const_expr, ast_ty_to_prim_ty(tcx, ty)))
+                    Some((&const_expr, tcx.ast_ty_to_prim_ty(ty)))
                 }
                 _ => None
             },
@@ -126,7 +125,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
             },
             Some(ast_map::NodeImplItem(ii)) => match ii.node {
                 hir::ImplItemKind::Const(ref ty, ref expr) => {
-                    Some((&expr, ast_ty_to_prim_ty(tcx, ty)))
+                    Some((&expr, tcx.ast_ty_to_prim_ty(ty)))
                 }
                 _ => None
             },
@@ -144,7 +143,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
         let expr_ty = match tcx.sess.cstore.maybe_get_item_ast(tcx, def_id) {
             cstore::FoundAst::Found(&InlinedItem::Item(ref item)) => match item.node {
                 hir::ItemConst(ref ty, ref const_expr) => {
-                    Some((&**const_expr, ast_ty_to_prim_ty(tcx, ty)))
+                    Some((&**const_expr, tcx.ast_ty_to_prim_ty(ty)))
                 },
                 _ => None
             },
@@ -165,7 +164,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
             },
             cstore::FoundAst::Found(&InlinedItem::ImplItem(_, ref ii)) => match ii.node {
                 hir::ImplItemKind::Const(ref ty, ref expr) => {
-                    Some((&**expr, ast_ty_to_prim_ty(tcx, ty)))
+                    Some((&**expr, tcx.ast_ty_to_prim_ty(ty)))
                 },
                 _ => None
             },
@@ -679,7 +678,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &TyCtxt<'tcx>,
         }
       }
       hir::ExprCast(ref base, ref target_ty) => {
-        let ety = ast_ty_to_prim_ty(tcx, &target_ty).or_else(|| ety)
+        let ety = tcx.ast_ty_to_prim_ty(&target_ty).or(ety)
                 .unwrap_or_else(|| {
                     tcx.sess.span_fatal(target_ty.span,
                                         "target type not found for const cast")
@@ -1041,7 +1040,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a TyCtxt<'tcx>,
                 Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
                 None => match ti.node {
                     hir::ConstTraitItem(ref ty, Some(ref expr)) => {
-                        Some((&*expr, ast_ty_to_prim_ty(tcx, ty)))
+                        Some((&*expr, tcx.ast_ty_to_prim_ty(ty)))
                     },
                     _ => None,
                 },
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 98dc787111d..475e1f42559 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -242,17 +242,14 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     }
 
     pub fn make_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        match infer::mk_subty(self.infcx, true, TypeOrigin::Misc(DUMMY_SP), a, b) {
+        match self.infcx.sub_types(true, TypeOrigin::Misc(DUMMY_SP), a, b) {
             Ok(_) => true,
             Err(ref e) => panic!("Encountered error: {}", e),
         }
     }
 
     pub fn is_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        match infer::can_mk_subty(self.infcx, a, b) {
-            Ok(_) => true,
-            Err(_) => false,
-        }
+        self.infcx.can_sub_types(a, b).is_ok()
     }
 
     pub fn assert_subtype(&self, a: Ty<'tcx>, b: Ty<'tcx>) {
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 4a0c3bbf187..b7de78ec912 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -25,7 +25,6 @@ use middle::cstore::{LOCAL_CRATE, InlinedItemRef, LinkMeta, tls};
 use rustc::hir::def;
 use rustc::hir::def_id::{CRATE_DEF_INDEX, DefId};
 use middle::dependency_format::Linkage;
-use middle::stability;
 use rustc::ty::subst;
 use rustc::traits::specialization_graph;
 use rustc::ty::{self, Ty, TyCtxt};
@@ -283,8 +282,8 @@ fn encode_enum_variant_info<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         encode_attributes(rbml_w, &attrs);
         encode_repr_attrs(rbml_w, ecx, &attrs);
 
-        let stab = stability::lookup_stability(ecx.tcx, vid);
-        let depr = stability::lookup_deprecation(ecx.tcx, vid);
+        let stab = ecx.tcx.lookup_stability(vid);
+        let depr = ecx.tcx.lookup_deprecation(vid);
         encode_stability(rbml_w, stab);
         encode_deprecation(rbml_w, depr);
 
@@ -376,8 +375,8 @@ fn encode_info_for_mod(ecx: &EncodeContext,
 
     encode_visibility(rbml_w, vis);
 
-    let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(id));
-    let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(id));
+    let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(id));
+    let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(id));
     encode_stability(rbml_w, stab);
     encode_deprecation(rbml_w, depr);
 
@@ -484,8 +483,8 @@ fn encode_field<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     encode_bounds_and_type_for_item(rbml_w, ecx, index, id);
     encode_def_id_and_key(ecx, rbml_w, field.did);
 
-    let stab = stability::lookup_stability(ecx.tcx, field.did);
-    let depr = stability::lookup_deprecation(ecx.tcx, field.did);
+    let stab = ecx.tcx.lookup_stability(field.did);
+    let depr = ecx.tcx.lookup_deprecation(field.did);
     encode_stability(rbml_w, stab);
     encode_deprecation(rbml_w, depr);
 
@@ -517,8 +516,8 @@ fn encode_info_for_struct_ctor<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         encode_symbol(ecx, rbml_w, ctor_id);
     }
 
-    let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
-    let depr= stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(ctor_id));
+    let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(ctor_id));
+    let depr= ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(ctor_id));
     encode_stability(rbml_w, stab);
     encode_deprecation(rbml_w, depr);
 
@@ -646,8 +645,8 @@ fn encode_info_for_associated_const<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     encode_bounds_and_type_for_item(rbml_w, ecx, index,
                                     ecx.local_id(associated_const.def_id));
 
-    let stab = stability::lookup_stability(ecx.tcx, associated_const.def_id);
-    let depr = stability::lookup_deprecation(ecx.tcx, associated_const.def_id);
+    let stab = ecx.tcx.lookup_stability(associated_const.def_id);
+    let depr = ecx.tcx.lookup_deprecation(associated_const.def_id);
     encode_stability(rbml_w, stab);
     encode_deprecation(rbml_w, depr);
 
@@ -681,8 +680,8 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
     encode_item_sort(rbml_w, 'r');
 
-    let stab = stability::lookup_stability(ecx.tcx, m.def_id);
-    let depr = stability::lookup_deprecation(ecx.tcx, m.def_id);
+    let stab = ecx.tcx.lookup_stability(m.def_id);
+    let depr = ecx.tcx.lookup_deprecation(m.def_id);
     encode_stability(rbml_w, stab);
     encode_deprecation(rbml_w, depr);
 
@@ -736,8 +735,8 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     encode_parent_item(rbml_w, ecx.tcx.map.local_def_id(parent_id));
     encode_item_sort(rbml_w, 't');
 
-    let stab = stability::lookup_stability(ecx.tcx, associated_type.def_id);
-    let depr = stability::lookup_deprecation(ecx.tcx, associated_type.def_id);
+    let stab = ecx.tcx.lookup_stability(associated_type.def_id);
+    let depr = ecx.tcx.lookup_deprecation(associated_type.def_id);
     encode_stability(rbml_w, stab);
     encode_deprecation(rbml_w, depr);
 
@@ -872,8 +871,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 
     let vis = &item.vis;
     let def_id = ecx.tcx.map.local_def_id(item.id);
-    let stab = stability::lookup_stability(tcx, ecx.tcx.map.local_def_id(item.id));
-    let depr = stability::lookup_deprecation(tcx, ecx.tcx.map.local_def_id(item.id));
+    let stab = tcx.lookup_stability(ecx.tcx.map.local_def_id(item.id));
+    let depr = tcx.lookup_deprecation(ecx.tcx.map.local_def_id(item.id));
 
     match item.node {
       hir::ItemStatic(_, m, _) => {
@@ -1231,8 +1230,8 @@ fn encode_info_for_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
 
             encode_parent_item(rbml_w, def_id);
 
-            let stab = stability::lookup_stability(tcx, item_def_id.def_id());
-            let depr = stability::lookup_deprecation(tcx, item_def_id.def_id());
+            let stab = tcx.lookup_stability(item_def_id.def_id());
+            let depr = tcx.lookup_deprecation(item_def_id.def_id());
             encode_stability(rbml_w, stab);
             encode_deprecation(rbml_w, depr);
 
@@ -1358,8 +1357,8 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
             encode_symbol(ecx, rbml_w, nitem.id);
         }
         encode_attributes(rbml_w, &nitem.attrs);
-        let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
-        let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
+        let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id));
+        let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id));
         encode_stability(rbml_w, stab);
         encode_deprecation(rbml_w, depr);
         encode_method_argument_names(rbml_w, &fndecl);
@@ -1372,8 +1371,8 @@ fn encode_info_for_foreign_item<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         }
         encode_bounds_and_type_for_item(rbml_w, ecx, index, nitem.id);
         encode_attributes(rbml_w, &nitem.attrs);
-        let stab = stability::lookup_stability(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
-        let depr = stability::lookup_deprecation(ecx.tcx, ecx.tcx.map.local_def_id(nitem.id));
+        let stab = ecx.tcx.lookup_stability(ecx.tcx.map.local_def_id(nitem.id));
+        let depr = ecx.tcx.lookup_deprecation(ecx.tcx.map.local_def_id(nitem.id));
         encode_stability(rbml_w, stab);
         encode_deprecation(rbml_w, depr);
         encode_symbol(ecx, rbml_w, nitem.id);
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index ceff9c4875c..64214c98bf7 100644
--- a/src/librustc_mir/mir_map.rs
+++ b/src/librustc_mir/mir_map.rs
@@ -202,10 +202,10 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
     }
 }
 
-fn closure_self_ty<'a, 'tcx>(tcx: &TyCtxt<'tcx>,
-                             closure_expr_id: ast::NodeId,
-                             body_id: ast::NodeId)
-                             -> Ty<'tcx> {
+fn closure_self_ty<'tcx>(tcx: &TyCtxt<'tcx>,
+                         closure_expr_id: ast::NodeId,
+                         body_id: ast::NodeId)
+                         -> Ty<'tcx> {
     let closure_ty = tcx.node_id_to_type(closure_expr_id);
 
     // We're just hard-coding the idea that the signature will be
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index d8b570923bf..4d07e63dde6 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -1023,11 +1023,11 @@ impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
                 let mut fulfillment_cx = traits::FulfillmentContext::new();
                 fulfillment_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
                 if let Err(err) = fulfillment_cx.select_all_or_error(&infcx) {
-                    traits::report_fulfillment_errors(&infcx, &err);
+                    infcx.report_fulfillment_errors(&err);
                 }
 
-                if let Err(ref errors) = fulfillment_cx.select_rfc1592_obligations(&infcx) {
-                   traits::report_fulfillment_errors_as_warnings(&infcx, errors, id);
+                if let Err(errors) = fulfillment_cx.select_rfc1592_obligations(&infcx) {
+                    infcx.report_fulfillment_errors_as_warnings(&errors, id);
                 }
             }
         }
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 03f4dd48834..d8093f10d96 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -237,7 +237,7 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
                 let fty = self.sanitize_type(lvalue, fty);
                 match self.field_ty(lvalue, base, field) {
                     Ok(ty) => {
-                        if let Err(terr) = self.cx.mk_eqty(span, ty, fty) {
+                        if let Err(terr) = self.cx.eq_types(span, ty, fty) {
                             span_mirbug!(
                                 self, lvalue, "bad field access ({:?}: {:?}): {:?}",
                                 ty, fty, terr);
@@ -333,20 +333,18 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
     }
 
-    fn mk_subty(&self, span: Span, sup: Ty<'tcx>, sub: Ty<'tcx>)
-                -> infer::UnitResult<'tcx>
+    fn sub_types(&self, span: Span, sup: Ty<'tcx>, sub: Ty<'tcx>)
+                 -> infer::UnitResult<'tcx>
     {
-        infer::mk_subty(self.infcx, false, infer::TypeOrigin::Misc(span),
-                        sup, sub)
+        self.infcx.sub_types(false, infer::TypeOrigin::Misc(span), sup, sub)
             // FIXME(#32730) propagate obligations
             .map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
     }
 
-    fn mk_eqty(&self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>)
+    fn eq_types(&self, span: Span, a: Ty<'tcx>, b: Ty<'tcx>)
                 -> infer::UnitResult<'tcx>
     {
-        infer::mk_eqty(self.infcx, false, infer::TypeOrigin::Misc(span),
-                       a, b)
+        self.infcx.eq_types(false, infer::TypeOrigin::Misc(span), a, b)
             // FIXME(#32730) propagate obligations
             .map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
     }
@@ -363,7 +361,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
                 let lv_ty = mir.lvalue_ty(tcx, lv).to_ty(tcx);
                 let rv_ty = mir.rvalue_ty(tcx, rv);
                 if let Some(rv_ty) = rv_ty {
-                    if let Err(terr) = self.mk_subty(self.last_span, rv_ty, lv_ty) {
+                    if let Err(terr) = self.sub_types(self.last_span, rv_ty, lv_ty) {
                         span_mirbug!(self, stmt, "bad assignment ({:?} = {:?}): {:?}",
                                      lv_ty, rv_ty, terr);
                     }
@@ -399,7 +397,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
             TerminatorKind::SwitchInt { ref discr, switch_ty, .. } => {
                 let discr_ty = mir.lvalue_ty(tcx, discr).to_ty(tcx);
-                if let Err(terr) = self.mk_subty(self.last_span, discr_ty, switch_ty) {
+                if let Err(terr) = self.sub_types(self.last_span, discr_ty, switch_ty) {
                     span_mirbug!(self, term, "bad SwitchInt ({:?} on {:?}): {:?}",
                                  switch_ty, discr_ty, terr);
                 }
@@ -456,7 +454,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
             (&Some((ref dest, _)), ty::FnConverging(ty)) => {
                 let dest_ty = mir.lvalue_ty(tcx, dest).to_ty(tcx);
-                if let Err(terr) = self.mk_subty(self.last_span, ty, dest_ty) {
+                if let Err(terr) = self.sub_types(self.last_span, ty, dest_ty) {
                     span_mirbug!(self, term,
                                  "call dest mismatch ({:?} <- {:?}): {:?}",
                                  dest_ty, ty, terr);
@@ -482,7 +480,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
         }
         for (n, (fn_arg, op_arg)) in sig.inputs.iter().zip(args).enumerate() {
             let op_arg_ty = mir.operand_ty(self.tcx(), op_arg);
-            if let Err(terr) = self.mk_subty(self.last_span, op_arg_ty, fn_arg) {
+            if let Err(terr) = self.sub_types(self.last_span, op_arg_ty, fn_arg) {
                 span_mirbug!(self, term, "bad arg #{:?} ({:?} <- {:?}): {:?}",
                              n, fn_arg, op_arg_ty, terr);
             }
@@ -537,7 +535,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             }
         };
 
-        if let Err(terr) = self.mk_subty(self.last_span, arg_ty, pointee_ty) {
+        if let Err(terr) = self.sub_types(self.last_span, arg_ty, pointee_ty) {
             span_mirbug!(self, term, "bad box_free arg ({:?} <- {:?}): {:?}",
                          pointee_ty, arg_ty, terr);
         }
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index 8634c8cf9bd..6c4a568a70a 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -202,8 +202,7 @@ impl<'tcx> Callee<'tcx> {
             }
             traits::VtableObject(ref data) => {
                 Callee {
-                    data: Virtual(traits::get_vtable_index_of_object_method(
-                        tcx, data, def_id)),
+                    data: Virtual(tcx.get_vtable_index_of_object_method(data, def_id)),
                     ty: def_ty(tcx, def_id, substs)
                 }
             }
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 8d44658c835..bab18e1469d 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -19,7 +19,7 @@ use llvm::{True, False, Bool, OperandBundleDef};
 use rustc::cfg;
 use rustc::hir::def::Def;
 use rustc::hir::def_id::DefId;
-use rustc::infer::{self, InferCtxt};
+use rustc::infer::InferCtxt;
 use rustc::util::common::MemoizationMap;
 use middle::lang_items::LangItem;
 use rustc::ty::subst::Substs;
@@ -1107,9 +1107,7 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
         let vtable = selection.map(|predicate| {
             fulfill_cx.register_predicate_obligation(&infcx, predicate);
         });
-        let vtable = infer::drain_fulfillment_cx_or_panic(
-            span, &infcx, &mut fulfill_cx, &vtable
-        );
+        let vtable = infcx.drain_fulfillment_cx_or_panic(span, &mut fulfill_cx, &vtable);
 
         info!("Cache miss: {:?} => {:?}", trait_ref, vtable);
 
@@ -1142,7 +1140,7 @@ pub fn normalize_and_test_predicates<'tcx>(tcx: &TyCtxt<'tcx>,
         fulfill_cx.register_predicate_obligation(&infcx, obligation);
     }
 
-    infer::drain_fulfillment_cx(&infcx, &mut fulfill_cx, &()).is_ok()
+    infcx.drain_fulfillment_cx(&mut fulfill_cx, &()).is_ok()
 }
 
 pub fn langcall(bcx: Block,
diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs
index 22177fe9451..937c6ede603 100644
--- a/src/librustc_trans/meth.rs
+++ b/src/librustc_trans/meth.rs
@@ -256,7 +256,7 @@ pub fn get_vtable_methods<'tcx>(tcx: &TyCtxt<'tcx>,
             let name = trait_method_type.name;
 
             // Some methods cannot be called on an object; skip those.
-            if !traits::is_vtable_safe_method(tcx, trt_id, &trait_method_type) {
+            if !tcx.is_vtable_safe_method(trt_id, &trait_method_type) {
                 debug!("get_vtable_methods: not vtable safe");
                 return None;
             }
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index b756df05faa..0ddbfe3310f 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -48,7 +48,6 @@
 //! case but `&a` in the second.  Basically, defaults that appear inside
 //! an rptr (`&r.T`) use the region `r` that appears in the rptr.
 
-use middle::astconv_util::{prim_ty_to_ty, prohibit_type_params, prohibit_projection};
 use middle::const_val::ConstVal;
 use rustc_const_eval::{eval_const_expr_partial, ConstEvalErr};
 use rustc_const_eval::EvalHint::UncheckedExprHint;
@@ -338,7 +337,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
         }
     };
 
-    assoc_bindings.first().map(|b| prohibit_projection(this.tcx(), b.span));
+    assoc_bindings.first().map(|b| this.tcx().prohibit_projection(b.span));
 
     create_substs_for_ast_path(this,
                                span,
@@ -825,7 +824,7 @@ fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
                                         trait_def_id,
                                         self_ty,
                                         trait_segment);
-    assoc_bindings.first().map(|b| prohibit_projection(this.tcx(), b.span));
+    assoc_bindings.first().map(|b| this.tcx().prohibit_projection(b.span));
     ty::TraitRef::new(trait_def_id, substs)
 }
 
@@ -1141,10 +1140,10 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
     // most importantly, that the supertraits don't contain Self,
     // to avoid ICE-s.
     let object_safety_violations =
-        traits::astconv_object_safety_violations(tcx, principal.def_id());
+        tcx.astconv_object_safety_violations(principal.def_id());
     if !object_safety_violations.is_empty() {
-        traits::report_object_safety_error(
-            tcx, span, principal.def_id(), None, object_safety_violations)
+        tcx.report_object_safety_error(
+            span, principal.def_id(), None, object_safety_violations)
             .unwrap().emit();
         return tcx.types.err;
     }
@@ -1281,7 +1280,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
 
     debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);
 
-    prohibit_type_params(tcx, slice::ref_slice(item_segment));
+    tcx.prohibit_type_params(slice::ref_slice(item_segment));
 
     // Find the type of the associated item, and the trait where the associated
     // item is declared.
@@ -1383,7 +1382,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
 {
     let tcx = this.tcx();
 
-    prohibit_type_params(tcx, slice::ref_slice(item_segment));
+    tcx.prohibit_type_params(slice::ref_slice(item_segment));
 
     let self_ty = if let Some(ty) = opt_self_ty {
         ty
@@ -1472,7 +1471,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                                           base_segments.last().unwrap(),
                                                           &mut projection_bounds);
 
-            prohibit_type_params(tcx, base_segments.split_last().unwrap().1);
+            tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
             trait_ref_to_object_type(this,
                                      rscope,
                                      span,
@@ -1481,7 +1480,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                      &[])
         }
         Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
-            prohibit_type_params(tcx, base_segments.split_last().unwrap().1);
+            tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
             ast_path_to_ty(this,
                            rscope,
                            span,
@@ -1490,12 +1489,12 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                            base_segments.last().unwrap())
         }
         Def::TyParam(space, index, _, name) => {
-            prohibit_type_params(tcx, base_segments);
+            tcx.prohibit_type_params(base_segments);
             tcx.mk_param(space, index, name)
         }
         Def::SelfTy(_, Some((_, self_ty_id))) => {
             // Self in impl (we know the concrete type).
-            prohibit_type_params(tcx, base_segments);
+            tcx.prohibit_type_params(base_segments);
             if let Some(&ty) = tcx.ast_ty_to_ty_cache.borrow().get(&self_ty_id) {
                 if let Some(free_substs) = this.get_free_substs() {
                     ty.subst(tcx, free_substs)
@@ -1508,11 +1507,11 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         }
         Def::SelfTy(Some(_), None) => {
             // Self in trait.
-            prohibit_type_params(tcx, base_segments);
+            tcx.prohibit_type_params(base_segments);
             tcx.mk_self_type()
         }
         Def::AssociatedTy(trait_did, _) => {
-            prohibit_type_params(tcx, &base_segments[..base_segments.len()-2]);
+            tcx.prohibit_type_params(&base_segments[..base_segments.len()-2]);
             qpath_to_ty(this,
                         rscope,
                         span,
@@ -1536,7 +1535,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
             opt_self_ty.expect("missing T in <T>::a::b::c")
         }
         Def::PrimTy(prim_ty) => {
-            prim_ty_to_ty(tcx, base_segments, prim_ty)
+            tcx.prim_ty_to_ty(base_segments, prim_ty)
         }
         Def::Err => {
             this.set_tainted_by_errors();
@@ -2259,7 +2258,7 @@ impl<'tcx> Bounds<'tcx> {
         let mut vec = Vec::new();
 
         for builtin_bound in &self.builtin_bounds {
-            match traits::trait_ref_for_builtin_bound(tcx, builtin_bound, param_ty) {
+            match tcx.trait_ref_for_builtin_bound(builtin_bound, param_ty) {
                 Ok(trait_ref) => { vec.push(trait_ref.to_predicate()); }
                 Err(ErrorReported) => { }
             }
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index ae23ee79e91..d414effcda0 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -64,7 +64,6 @@ use check::{FnCtxt, UnresolvedTypeAction};
 
 use rustc::infer::{Coercion, InferOk, TypeOrigin, TypeTrace};
 use rustc::traits::{self, ObligationCause};
-use rustc::traits::{predicate_for_trait_def, report_selection_error};
 use rustc::ty::adjustment::{AutoAdjustment, AutoDerefRef, AdjustDerefRef};
 use rustc::ty::adjustment::{AutoPtr, AutoUnsafe, AdjustReifyFnPointer};
 use rustc::ty::adjustment::{AdjustUnsafeFnPointer, AdjustMutToConstPointer};
@@ -446,12 +445,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
         // Create an obligation for `Source: CoerceUnsized<Target>`.
         let cause = ObligationCause::misc(self.origin.span(), self.fcx.body_id);
-        queue.push_back(predicate_for_trait_def(self.tcx(),
-                                                cause,
-                                                coerce_unsized_did,
-                                                0,
-                                                source,
-                                                vec![target]));
+        queue.push_back(self.tcx().predicate_for_trait_def(cause,
+                                                           coerce_unsized_did,
+                                                           0,
+                                                           source,
+                                                           vec![target]));
 
         // Keep resolving `CoerceUnsized` and `Unsize` predicates to avoid
         // emitting a coercion in cases like `Foo<$1>` -> `Foo<$2>`, where
@@ -477,7 +475,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
                 // Object safety violations or miscellaneous.
                 Err(err) => {
-                    report_selection_error(self.fcx.infcx(), &obligation, &err, None);
+                    self.fcx.infcx().report_selection_error(&obligation, &err, None);
                     // Treat this like an obligation and follow through
                     // with the unsizing - the lack of a coercion should
                     // be silent, as it causes a type mismatch later.
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 28d8206a145..375ce6941ae 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -325,9 +325,9 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         debug!("compare_impl_method: trait_fty={:?}",
                trait_fty);
 
-        infer::mk_subty(&infcx, false, origin, impl_fty, trait_fty)?;
+        infcx.sub_types(false, origin, impl_fty, trait_fty)?;
 
-        infcx.leak_check(&skol_map, snapshot)
+        infcx.leak_check(false, &skol_map, snapshot)
     });
 
     match err {
@@ -347,7 +347,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     // Check that all obligations are satisfied by the implementation's
     // version.
     match fulfillment_cx.select_all_or_error(&infcx) {
-        Err(ref errors) => { traits::report_fulfillment_errors(&infcx, errors) }
+        Err(ref errors) => { infcx.report_fulfillment_errors(errors) }
         Ok(_) => {}
     }
 
@@ -361,8 +361,7 @@ pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     // anyway, so it shouldn't be needed there either. Anyway, we can
     // always add more relations later (it's backwards compat).
     let mut free_regions = FreeRegionMap::new();
-    free_regions.relate_free_regions_from_predicates(tcx,
-                                                     &infcx.parameter_environment.caller_bounds);
+    free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment.caller_bounds);
 
     infcx.resolve_regions_and_report_errors(&free_regions, impl_m_body_id);
 
@@ -474,7 +473,7 @@ pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         debug!("compare_const_impl: trait_ty={:?}",
                trait_ty);
 
-        infer::mk_subty(&infcx, false, origin, impl_ty, trait_ty)
+        infcx.sub_types(false, origin, impl_ty, trait_ty)
     });
 
     match err {
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 0ddf616bb54..09a23d28364 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -96,7 +96,7 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
         infcx.fresh_substs_for_generics(drop_impl_span, drop_impl_generics);
     let fresh_impl_self_ty = drop_impl_ty.subst(tcx, &fresh_impl_substs);
 
-    if let Err(_) = infer::mk_eqty(&infcx, true, infer::TypeOrigin::Misc(drop_impl_span),
+    if let Err(_) = infcx.eq_types(true, infer::TypeOrigin::Misc(drop_impl_span),
                                    named_type, fresh_impl_self_ty) {
         let item_span = tcx.map.span(self_type_node_id);
         struct_span_err!(tcx.sess, drop_impl_span, E0366,
@@ -110,13 +110,12 @@ fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
 
     if let Err(ref errors) = fulfillment_cx.select_all_or_error(&infcx) {
         // this could be reached when we get lazy normalization
-        traits::report_fulfillment_errors(&infcx, errors);
+        infcx.report_fulfillment_errors(errors);
         return Err(());
     }
 
     if let Err(ref errors) = fulfillment_cx.select_rfc1592_obligations(&infcx) {
-        traits::report_fulfillment_errors_as_warnings(&infcx, errors,
-                                                      drop_impl_node_id);
+        infcx.report_fulfillment_errors_as_warnings(errors, drop_impl_node_id);
     }
 
     let free_regions = FreeRegionMap::new();
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 77c74078de7..0b4dc55fbf7 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -19,7 +19,7 @@ use rustc::ty::{self, NoPreference, PreferMutLvalue, Ty, TyCtxt};
 use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
 use rustc::ty::fold::TypeFoldable;
 use rustc::infer;
-use rustc::infer::{InferCtxt, TypeOrigin};
+use rustc::infer::{InferCtxt, InferOk, TypeOrigin};
 use syntax::codemap::Span;
 use rustc::hir;
 
@@ -369,8 +369,12 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                        self_ty: Ty<'tcx>,
                        method_self_ty: Ty<'tcx>)
     {
-        match self.fcx.mk_subty(false, TypeOrigin::Misc(self.span), self_ty, method_self_ty) {
-            Ok(_) => {}
+        match self.fcx.infcx().sub_types(false, TypeOrigin::Misc(self.span),
+                                         self_ty, method_self_ty) {
+            Ok(InferOk { obligations, .. }) => {
+                // FIXME(#32730) propagate obligations
+                assert!(obligations.is_empty());
+            }
             Err(_) => {
                 span_bug!(
                     self.span,
@@ -636,9 +640,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
               target_trait_def_id: DefId)
               -> ty::PolyTraitRef<'tcx>
     {
-        let upcast_trait_refs = traits::upcast(self.tcx(),
-                                               source_trait_ref.clone(),
-                                               target_trait_def_id);
+        let upcast_trait_refs = self.tcx().upcast_choices(source_trait_ref.clone(),
+                                                          target_trait_def_id);
 
         // must be exactly one trait ref or we'd get an ambig error etc
         if upcast_trait_refs.len() != 1 {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 0da41ba41e4..686d33b5e53 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -84,14 +84,13 @@ use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
 use check::_match::PatCtxt;
 use dep_graph::DepNode;
 use fmt_macros::{Parser, Piece, Position};
-use middle::astconv_util::prohibit_type_params;
 use middle::cstore::LOCAL_CRATE;
 use hir::def::{self, Def};
 use hir::def_id::DefId;
 use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin, TypeTrace, type_variable};
 use hir::pat_util::{self, pat_id_map};
 use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace};
-use rustc::traits::{self, report_fulfillment_errors, ProjectionMode};
+use rustc::traits::{self, ProjectionMode};
 use rustc::ty::{GenericPredicates, TypeScheme};
 use rustc::ty::{ParamTy, ParameterEnvironment};
 use rustc::ty::{LvaluePreference, NoPreference, PreferMutLvalue};
@@ -1158,7 +1157,7 @@ pub fn check_representable(tcx: &TyCtxt,
     match rty.is_representable(tcx, sp) {
         Representability::SelfRecursive => {
             let item_def_id = tcx.map.local_def_id(item_id);
-            traits::recursive_type_with_infinite_size_error(tcx, item_def_id).emit();
+            tcx.recursive_type_with_infinite_size_error(item_def_id).emit();
             return false
         }
         Representability::Representable | Representability::ContainsRecursive => (),
@@ -1803,35 +1802,6 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn mk_subty(&self,
-                    a_is_expected: bool,
-                    origin: TypeOrigin,
-                    sub: Ty<'tcx>,
-                    sup: Ty<'tcx>)
-                    -> Result<(), TypeError<'tcx>> {
-        infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
-            // FIXME(#32730) propagate obligations
-            .map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
-    }
-
-    pub fn mk_eqty(&self,
-                   a_is_expected: bool,
-                   origin: TypeOrigin,
-                   sub: Ty<'tcx>,
-                   sup: Ty<'tcx>)
-                   -> Result<(), TypeError<'tcx>> {
-        infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
-            // FIXME(#32730) propagate obligations
-            .map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
-    }
-
-    pub fn mk_subr(&self,
-                   origin: infer::SubregionOrigin<'tcx>,
-                   sub: ty::Region,
-                   sup: ty::Region) {
-        infer::mk_subr(self.infcx(), origin, sub, sup)
-    }
-
     pub fn type_error_message<M>(&self,
                                  sp: Span,
                                  mk_msg: M,
@@ -2119,9 +2089,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             Neither => {
                                 if let Some(default) = default_map.get(ty) {
                                     let default = default.clone();
-                                    match infer::mk_eqty(self.infcx(), false,
-                                                         TypeOrigin::Misc(default.origin_span),
-                                                         ty, default.ty) {
+                                    match self.infcx().eq_types(false,
+                                            TypeOrigin::Misc(default.origin_span),
+                                            ty, default.ty) {
                                         Ok(InferOk { obligations, .. }) => {
                                             // FIXME(#32730) propagate obligations
                                             assert!(obligations.is_empty())
@@ -2215,9 +2185,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                     Neither => {
                         if let Some(default) = default_map.get(ty) {
                             let default = default.clone();
-                            match infer::mk_eqty(self.infcx(), false,
-                                                 TypeOrigin::Misc(default.origin_span),
-                                                 ty, default.ty) {
+                            match self.infcx().eq_types(false,
+                                    TypeOrigin::Misc(default.origin_span),
+                                    ty, default.ty) {
                                 // FIXME(#32730) propagate obligations
                                 Ok(InferOk { obligations, .. }) => assert!(obligations.is_empty()),
                                 Err(_) => {
@@ -2239,18 +2209,17 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // upvar inference should have ensured that all deferred call
         // resolutions are handled by now.
         assert!(self.inh.deferred_call_resolutions.borrow().is_empty());
-        let infcx = self.infcx();
 
         self.select_all_obligations_and_apply_defaults();
 
         let mut fulfillment_cx = self.inh.fulfillment_cx.borrow_mut();
-        match fulfillment_cx.select_all_or_error(infcx) {
+        match fulfillment_cx.select_all_or_error(self.infcx()) {
             Ok(()) => { }
-            Err(errors) => { report_fulfillment_errors(infcx, &errors); }
+            Err(errors) => { self.infcx().report_fulfillment_errors(&errors); }
         }
 
-        if let Err(ref errors) = fulfillment_cx.select_rfc1592_obligations(infcx) {
-            traits::report_fulfillment_errors_as_warnings(infcx, errors, self.body_id);
+        if let Err(ref errors) = fulfillment_cx.select_rfc1592_obligations(self.infcx()) {
+            self.infcx().report_fulfillment_errors_as_warnings(errors, self.body_id);
         }
     }
 
@@ -2262,7 +2231,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
             .select_where_possible(self.infcx())
         {
             Ok(()) => { }
-            Err(errors) => { report_fulfillment_errors(self.infcx(), &errors); }
+            Err(errors) => { self.infcx().report_fulfillment_errors(&errors); }
         }
     }
 
@@ -3570,16 +3539,18 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
       hir::ExprRet(ref expr_opt) => {
         match self.ret_ty {
             ty::FnConverging(result_type) => {
-                match *expr_opt {
-                    None =>
-                        if let Err(_) = self.mk_eqty(false, TypeOrigin::Misc(expr.span),
-                                                     result_type, self.tcx().mk_nil()) {
-                            span_err!(tcx.sess, expr.span, E0069,
-                                "`return;` in a function whose return type is \
-                                 not `()`");
-                        },
-                    Some(ref e) => {
-                        self.check_expr_coercable_to_type(&e, result_type);
+                if let Some(ref e) = *expr_opt {
+                    self.check_expr_coercable_to_type(&e, result_type);
+                } else {
+                    let eq_result = self.infcx().eq_types(false,
+                                                          TypeOrigin::Misc(expr.span),
+                                                          result_type,
+                                                          self.tcx().mk_nil())
+                        // FIXME(#32730) propagate obligations
+                        .map(|InferOk { obligations, .. }| assert!(obligations.is_empty()));
+                    if eq_result.is_err() {
+                        span_err!(tcx.sess, expr.span, E0069,
+                                  "`return;` in a function whose return type is not `()`");
                     }
                 }
             }
@@ -4370,7 +4341,7 @@ pub fn instantiate_path(&self,
                                                                  segment,
                                                                  &mut substs);
         } else {
-            prohibit_type_params(self.tcx(), slice::ref_slice(segment));
+            self.tcx().prohibit_type_params(slice::ref_slice(segment));
         }
     }
     if let Some(self_ty) = opt_self_ty {
@@ -4423,11 +4394,17 @@ pub fn instantiate_path(&self,
                    impl_scheme.generics.regions.len(subst::TypeSpace));
 
         let impl_ty = self.instantiate_type_scheme(span, &substs, &impl_scheme.ty);
-        if self.mk_subty(false, TypeOrigin::Misc(span), self_ty, impl_ty).is_err() {
-            span_bug!(span,
-                "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
-                self_ty,
-                impl_ty);
+        match self.infcx().sub_types(false, TypeOrigin::Misc(span), self_ty, impl_ty) {
+            Ok(InferOk { obligations, .. }) => {
+                // FIXME(#32730) propagate obligations
+                assert!(obligations.is_empty());
+            }
+            Err(_) => {
+                span_bug!(span,
+                    "instantiate_path: (UFCS) {:?} was a subtype of {:?} but now is not?",
+                    self_ty,
+                    impl_ty);
+            }
         }
     }
 
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 76c387ccc2c..9112c3db575 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -131,8 +131,7 @@ pub fn regionck_item(&self,
                      wf_tys: &[Ty<'tcx>]) {
     debug!("regionck_item(item.id={:?}, wf_tys={:?}", item_id, wf_tys);
     let mut rcx = Rcx::new(self, RepeatingScope(item_id), item_id, Subject(item_id));
-    let tcx = self.tcx();
-    rcx.free_region_map.relate_free_regions_from_predicates(tcx,
+    rcx.free_region_map.relate_free_regions_from_predicates(
         &self.infcx().parameter_environment.caller_bounds);
     rcx.relate_free_regions(wf_tys, item_id, span);
     rcx.visit_region_obligations(item_id);
@@ -152,8 +151,7 @@ pub fn regionck_fn(&self,
         rcx.visit_fn_body(fn_id, decl, blk, fn_span);
     }
 
-    let tcx = self.tcx();
-    rcx.free_region_map.relate_free_regions_from_predicates(tcx,
+    rcx.free_region_map.relate_free_regions_from_predicates(
         &self.infcx().parameter_environment.caller_bounds);
 
     rcx.resolve_regions_and_report_errors();
@@ -844,7 +842,7 @@ fn constrain_cast(rcx: &mut Rcx,
             /*From:*/ (&ty::TyRef(from_r, ref from_mt),
             /*To:  */  &ty::TyRef(to_r, ref to_mt)) => {
                 // Target cannot outlive source, naturally.
-                rcx.fcx.mk_subr(infer::Reborrow(cast_expr.span), *to_r, *from_r);
+                rcx.fcx.infcx().sub_regions(infer::Reborrow(cast_expr.span), *to_r, *from_r);
                 walk_cast(rcx, cast_expr, from_mt.ty, to_mt.ty);
             }
 
@@ -1038,8 +1036,8 @@ pub fn mk_subregion_due_to_dereference(rcx: &mut Rcx,
                                        deref_span: Span,
                                        minimum_lifetime: ty::Region,
                                        maximum_lifetime: ty::Region) {
-    rcx.fcx.mk_subr(infer::DerefPointer(deref_span),
-                    minimum_lifetime, maximum_lifetime)
+    rcx.fcx.infcx().sub_regions(infer::DerefPointer(deref_span),
+                                minimum_lifetime, maximum_lifetime)
 }
 
 fn check_safety_of_rvalue_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
@@ -1081,8 +1079,8 @@ fn constrain_index<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
     if let ty::TyRef(r_ptr, mt) = indexed_ty.sty {
         match mt.ty.sty {
             ty::TySlice(_) | ty::TyStr => {
-                rcx.fcx.mk_subr(infer::IndexSlice(index_expr.span),
-                                r_index_expr, *r_ptr);
+                rcx.fcx.infcx().sub_regions(infer::IndexSlice(index_expr.span),
+                                            r_index_expr, *r_ptr);
             }
             _ => {}
         }
@@ -1410,7 +1408,7 @@ fn link_reborrowed_region<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
     debug!("link_reborrowed_region: {:?} <= {:?}",
            borrow_region,
            ref_region);
-    rcx.fcx.mk_subr(cause, *borrow_region, ref_region);
+    rcx.fcx.infcx().sub_regions(cause, *borrow_region, ref_region);
 
     // If we end up needing to recurse and establish a region link
     // with `ref_cmt`, calculate what borrow kind we will end up
@@ -1492,7 +1490,7 @@ pub fn substs_wf_in_scope<'a,'tcx>(rcx: &mut Rcx<'a,'tcx>,
     let origin = infer::ParameterInScope(origin, expr_span);
 
     for &region in &substs.regions {
-        rcx.fcx.mk_subr(origin.clone(), expr_region, region);
+        rcx.fcx.infcx().sub_regions(origin.clone(), expr_region, region);
     }
 
     for &ty in &substs.types {
@@ -1518,7 +1516,7 @@ pub fn type_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
 
     assert!(!ty.has_escaping_regions());
 
-    let components = ty::outlives::components(rcx.infcx(), ty);
+    let components = rcx.infcx().outlives_components(ty);
     components_must_outlive(rcx, origin, components, region);
 }
 
@@ -1531,7 +1529,7 @@ fn components_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
         let origin = origin.clone();
         match component {
             ty::outlives::Component::Region(region1) => {
-                rcx.fcx.mk_subr(origin, region, region1);
+                rcx.fcx.infcx().sub_regions(origin, region, region1);
             }
             ty::outlives::Component::Param(param_ty) => {
                 param_ty_must_outlive(rcx, origin, region, param_ty);
@@ -1629,7 +1627,7 @@ fn projection_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
         }
 
         for &r in &projection_ty.trait_ref.substs.regions {
-            rcx.fcx.mk_subr(origin.clone(), region, r);
+            rcx.fcx.infcx().sub_regions(origin.clone(), region, r);
         }
 
         return;
@@ -1650,7 +1648,7 @@ fn projection_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
                                          .any(|r| env_bounds.contains(r))
         {
             debug!("projection_must_outlive: unique declared bound appears in trait ref");
-            rcx.fcx.mk_subr(origin.clone(), region, unique_bound);
+            rcx.fcx.infcx().sub_regions(origin.clone(), region, unique_bound);
             return;
         }
     }
@@ -1840,7 +1838,7 @@ fn declared_projection_bounds_from_trait<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
                        outlives);
 
                 // check whether this predicate applies to our current projection
-                match infer::mk_eqty(infcx, false, TypeOrigin::Misc(span), ty, outlives.0) {
+                match infcx.eq_types(false, TypeOrigin::Misc(span), ty, outlives.0) {
                     Ok(InferOk { obligations, .. }) => {
                         // FIXME(#32730) propagate obligations
                         assert!(obligations.is_empty());
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index f8e4cb0eb65..c84707ecbce 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -440,28 +440,24 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
             match self.reason {
                 ResolvingExpr(span) => {
                     span_err!(self.tcx.sess, span, E0101,
-                        "cannot determine a type for this expression: {}",
-                        infer::fixup_err_to_string(e));
+                        "cannot determine a type for this expression: {}", e);
                 }
 
                 ResolvingLocal(span) => {
                     span_err!(self.tcx.sess, span, E0102,
-                        "cannot determine a type for this local variable: {}",
-                        infer::fixup_err_to_string(e));
+                        "cannot determine a type for this local variable: {}", e);
                 }
 
                 ResolvingPattern(span) => {
                     span_err!(self.tcx.sess, span, E0103,
-                        "cannot determine a type for this pattern binding: {}",
-                        infer::fixup_err_to_string(e));
+                        "cannot determine a type for this pattern binding: {}", e);
                 }
 
                 ResolvingUpvar(upvar_id) => {
                     let span = self.reason.span(self.tcx);
                     span_err!(self.tcx.sess, span, E0104,
                         "cannot resolve lifetime for captured variable `{}`: {}",
-                        self.tcx.local_var_name_str(upvar_id.var_id).to_string(),
-                        infer::fixup_err_to_string(e));
+                        self.tcx.local_var_name_str(upvar_id.var_id), e);
                 }
 
                 ResolvingClosure(_) => {
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index c37504f2954..c7e8629cdf9 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -46,11 +46,28 @@ mod orphan;
 mod overlap;
 mod unsafety;
 
+struct CoherenceChecker<'a, 'tcx: 'a> {
+    crate_context: &'a CrateCtxt<'a, 'tcx>,
+    inference_context: InferCtxt<'a, 'tcx>,
+    inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<DefId>>>>>,
+}
+
+struct CoherenceCheckVisitor<'a, 'tcx: 'a> {
+    cc: &'a CoherenceChecker<'a, 'tcx>
+}
+
+impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
+    fn visit_item(&mut self, item: &Item) {
+        if let ItemImpl(..) = item.node {
+            self.cc.check_implementation(item)
+        }
+    }
+}
+
+impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
+
 // Returns the def ID of the base type, if there is one.
-fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
-                                  span: Span,
-                                  ty: Ty<'tcx>)
-                                  -> Option<DefId> {
+fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
     match ty.sty {
         TyEnum(def, _) |
         TyStruct(def, _) => {
@@ -62,7 +79,7 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
         }
 
         TyBox(_) => {
-            inference_context.tcx.lang_items.owned_box()
+            self.inference_context.tcx.lang_items.owned_box()
         }
 
         TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
@@ -83,25 +100,6 @@ fn get_base_type_def_id<'a, 'tcx>(inference_context: &InferCtxt<'a, 'tcx>,
     }
 }
 
-struct CoherenceChecker<'a, 'tcx: 'a> {
-    crate_context: &'a CrateCtxt<'a, 'tcx>,
-    inference_context: InferCtxt<'a, 'tcx>,
-    inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<DefId>>>>>,
-}
-
-struct CoherenceCheckVisitor<'a, 'tcx: 'a> {
-    cc: &'a CoherenceChecker<'a, 'tcx>
-}
-
-impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
-    fn visit_item(&mut self, item: &Item) {
-        if let ItemImpl(..) = item.node {
-            self.cc.check_implementation(item)
-        }
-    }
-}
-
-impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
     fn check(&self) {
         // Check implementations and traits. This populates the tables
         // containing the inherent methods and extension methods. It also
@@ -167,9 +165,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             // Add the implementation to the mapping from implementation to base
             // type def ID, if there is a base type for this implementation and
             // the implementation does not have any associated traits.
-            if let Some(base_type_def_id) = get_base_type_def_id(
-                    &self.inference_context, item.span, self_type.ty) {
-                self.add_inherent_impl(base_type_def_id, impl_did);
+            if let Some(base_def_id) = self.get_base_type_def_id(item.span, self_type.ty) {
+                self.add_inherent_impl(base_def_id, impl_did);
             }
         }
 
@@ -394,7 +391,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 (&ty::TyBox(a), &ty::TyBox(b)) => (a, b, unsize_trait, None),
 
                 (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => {
-                    infer::mk_subr(&infcx, infer::RelateObjectBound(span), *r_b, *r_a);
+                    infcx.sub_regions(infer::RelateObjectBound(span), *r_b, *r_a);
                     check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
                 }
 
@@ -466,19 +463,19 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
 
             // Register an obligation for `A: Trait<B>`.
             let cause = traits::ObligationCause::misc(span, impl_node_id);
-            let predicate = traits::predicate_for_trait_def(tcx, cause, trait_def_id,
-                                                            0, source, vec![target]);
+            let predicate = tcx.predicate_for_trait_def(cause, trait_def_id, 0,
+                                                        source, vec![target]);
             fulfill_cx.register_predicate_obligation(&infcx, predicate);
 
             // Check that all transitive obligations are satisfied.
             if let Err(errors) = fulfill_cx.select_all_or_error(&infcx) {
-                traits::report_fulfillment_errors(&infcx, &errors);
+                infcx.report_fulfillment_errors(&errors);
             }
 
             // Finally, resolve all regions.
             let mut free_regions = FreeRegionMap::new();
-            free_regions.relate_free_regions_from_predicates(tcx, &infcx.parameter_environment
-                                                                        .caller_bounds);
+            free_regions.relate_free_regions_from_predicates(&infcx.parameter_environment
+                                                                   .caller_bounds);
             infcx.resolve_regions_and_report_errors(&free_regions, impl_node_id);
 
             if let Some(kind) = kind {
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index 8284e8717b9..ea87b870694 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -174,7 +174,7 @@ impl<'cx, 'tcx,'v> intravisit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
                     // This is something like impl Trait1 for Trait2. Illegal
                     // if Trait1 is a supertrait of Trait2 or Trait2 is not object safe.
 
-                    if !traits::is_object_safe(self.tcx, data.principal_def_id()) {
+                    if !self.tcx.is_object_safe(data.principal_def_id()) {
                         // This is an error, but it will be
                         // reported by wfcheck.  Ignore it
                         // here. This is tested by
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index e5e4fda10ef..b28a7302d5f 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -201,10 +201,10 @@ fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 -> bool
 {
     let err = if let Some(infcx) = maybe_infcx {
-        infer::mk_eqty(infcx, false, TypeOrigin::Misc(span), t1, t2).err()
+        infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2).err()
     } else {
         let infcx = InferCtxt::new(ccx.tcx, &ccx.tcx.tables, None, ProjectionMode::AnyFinal);
-        infer::mk_eqty(&infcx, false, TypeOrigin::Misc(span), t1, t2).err()
+        infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2).err()
     };
 
     if let Some(ref terr) = err {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 742afdc5e98..97a56e50176 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -22,7 +22,6 @@ use rustc::hir::def_id::DefId;
 use rustc::hir::print as pprust;
 use rustc::ty::{self, TyCtxt};
 use rustc::ty::subst;
-use rustc::middle::stability;
 
 use rustc_const_eval::lookup_const_by_id;
 
@@ -124,8 +123,8 @@ fn try_inline_def(cx: &DocContext, tcx: &TyCtxt,
         attrs: load_attrs(cx, tcx, did),
         inner: inner,
         visibility: Some(clean::Public),
-        stability: stability::lookup_stability(tcx, did).clean(cx),
-        deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
+        stability: tcx.lookup_stability(did).clean(cx),
+        deprecation: tcx.lookup_deprecation(did).clean(cx),
         def_id: did,
     });
     Some(ret)
@@ -305,8 +304,8 @@ pub fn build_impl(cx: &DocContext,
             name: None,
             attrs: attrs,
             visibility: Some(clean::Inherited),
-            stability: stability::lookup_stability(tcx, did).clean(cx),
-            deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
+            stability: tcx.lookup_stability(did).clean(cx),
+            deprecation: tcx.lookup_deprecation(did).clean(cx),
             def_id: did,
         });
     }
@@ -347,8 +346,8 @@ pub fn build_impl(cx: &DocContext,
                     source: clean::Span::empty(),
                     attrs: vec![],
                     visibility: None,
-                    stability: stability::lookup_stability(tcx, did).clean(cx),
-                    deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
+                    stability: tcx.lookup_stability(did).clean(cx),
+                    deprecation: tcx.lookup_deprecation(did).clean(cx),
                     def_id: did
                 })
             }
@@ -396,8 +395,8 @@ pub fn build_impl(cx: &DocContext,
                     source: clean::Span::empty(),
                     attrs: vec![],
                     visibility: None,
-                    stability: stability::lookup_stability(tcx, did).clean(cx),
-                    deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
+                    stability: tcx.lookup_stability(did).clean(cx),
+                    deprecation: tcx.lookup_deprecation(did).clean(cx),
                     def_id: did
                 })
             }
@@ -436,8 +435,8 @@ pub fn build_impl(cx: &DocContext,
         name: None,
         attrs: attrs,
         visibility: Some(clean::Inherited),
-        stability: stability::lookup_stability(tcx, did).clean(cx),
-        deprecation: stability::lookup_deprecation(tcx, did).clean(cx),
+        stability: tcx.lookup_stability(did).clean(cx),
+        deprecation: tcx.lookup_deprecation(did).clean(cx),
         def_id: did,
     });
 }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index a47b66bf2f7..7d8ab70a859 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -64,11 +64,11 @@ mod simplify;
 
 // extract the stability index for a node from tcx, if possible
 fn get_stability(cx: &DocContext, def_id: DefId) -> Option<Stability> {
-    cx.tcx_opt().and_then(|tcx| stability::lookup_stability(tcx, def_id)).clean(cx)
+    cx.tcx_opt().and_then(|tcx| tcx.lookup_stability(def_id)).clean(cx)
 }
 
 fn get_deprecation(cx: &DocContext, def_id: DefId) -> Option<Deprecation> {
-    cx.tcx_opt().and_then(|tcx| stability::lookup_deprecation(tcx, def_id)).clean(cx)
+    cx.tcx_opt().and_then(|tcx| tcx.lookup_deprecation(def_id)).clean(cx)
 }
 
 pub trait Clean<T> {
@@ -2878,8 +2878,8 @@ impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
             inner: AssociatedTypeItem(bounds, self.ty.clean(cx)),
             visibility: self.vis.clean(cx),
             def_id: self.def_id,
-            stability: stability::lookup_stability(cx.tcx(), self.def_id).clean(cx),
-            deprecation: stability::lookup_deprecation(cx.tcx(), self.def_id).clean(cx),
+            stability: cx.tcx().lookup_stability(self.def_id).clean(cx),
+            deprecation: cx.tcx().lookup_deprecation(self.def_id).clean(cx),
         }
     }
 }
diff --git a/src/librustdoc/visit_ast.rs b/src/librustdoc/visit_ast.rs
index d9ea82acbea..d5309d74334 100644
--- a/src/librustdoc/visit_ast.rs
+++ b/src/librustdoc/visit_ast.rs
@@ -22,7 +22,6 @@ use syntax::codemap::Span;
 
 use rustc::hir::map as hir_map;
 use rustc::hir::def::Def;
-use rustc::middle::stability;
 use rustc::middle::privacy::AccessLevel;
 
 use rustc::hir;
@@ -64,7 +63,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     fn stability(&self, id: ast::NodeId) -> Option<attr::Stability> {
         self.cx.tcx_opt().and_then(|tcx| {
             self.cx.map.opt_local_def_id(id)
-                       .and_then(|def_id| stability::lookup_stability(tcx, def_id))
+                       .and_then(|def_id| tcx.lookup_stability(def_id))
                        .cloned()
         })
     }
@@ -72,7 +71,7 @@ impl<'a, 'tcx> RustdocVisitor<'a, 'tcx> {
     fn deprecation(&self, id: ast::NodeId) -> Option<attr::Deprecation> {
         self.cx.tcx_opt().and_then(|tcx| {
             self.cx.map.opt_local_def_id(id)
-                       .and_then(|def_id| stability::lookup_deprecation(tcx, def_id))
+                       .and_then(|def_id| tcx.lookup_deprecation(def_id))
         })
     }