about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-03-11 16:33:42 +0200
committerEduard Burtescu <edy.burt@gmail.com>2016-05-11 04:14:58 +0300
commitef2f5f6d8ef51010d060d6f8cff6cac2ef83fd42 (patch)
treebcad64a4db0b489019924c731bbdc5f3f8fe9d75
parente387e6c7c82bed6a32631a04bc66f3957384faa8 (diff)
typeck: Avoid passing &TyCtxt around where possible.
-rw-r--r--src/librustc/ty/util.rs12
-rw-r--r--src/librustc_typeck/astconv.rs31
-rw-r--r--src/librustc_typeck/check/_match.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs2
-rw-r--r--src/librustc_typeck/check/compare_method.rs47
-rw-r--r--src/librustc_typeck/check/dropck.rs34
-rw-r--r--src/librustc_typeck/check/intrinsic.rs48
-rw-r--r--src/librustc_typeck/check/method/mod.rs26
-rw-r--r--src/librustc_typeck/check/method/probe.rs43
-rw-r--r--src/librustc_typeck/check/method/suggest.rs10
-rw-r--r--src/librustc_typeck/check/mod.rs45
-rw-r--r--src/librustc_typeck/check/wfcheck.rs21
-rw-r--r--src/librustc_typeck/check/writeback.rs8
-rw-r--r--src/librustc_typeck/collect.rs250
-rw-r--r--src/librustc_typeck/constrained_type_params.rs11
-rw-r--r--src/librustc_typeck/lib.rs57
16 files changed, 288 insertions, 359 deletions
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 75a31d15651..a18fdebbaa9 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -33,7 +33,7 @@ use hir;
 
 pub trait IntTypeExt {
     fn to_ty<'tcx>(&self, tcx: &TyCtxt<'tcx>) -> Ty<'tcx>;
-    fn disr_incr(&self, val: Disr) -> Option<Disr>;
+    fn disr_incr(&self, tcx: &TyCtxt, val: Option<Disr>) -> Option<Disr>;
     fn assert_ty_matches(&self, val: Disr);
     fn initial_discriminant(&self, tcx: &TyCtxt) -> Disr;
 }
@@ -93,9 +93,13 @@ impl IntTypeExt for attr::IntType {
         }
     }
 
-    fn disr_incr(&self, val: Disr) -> Option<Disr> {
-        self.assert_ty_matches(val);
-        (val + ConstInt::Infer(1)).ok()
+    fn disr_incr(&self, tcx: &TyCtxt, val: Option<Disr>) -> Option<Disr> {
+        if let Some(val) = val {
+            self.assert_ty_matches(val);
+            (val + ConstInt::Infer(1)).ok()
+        } else {
+            Some(self.initial_discriminant(tcx))
+        }
     }
 }
 
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 5e07011d5ba..b756df05faa 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -338,7 +338,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
         }
     };
 
-    prohibit_projections(this.tcx(), &assoc_bindings);
+    assoc_bindings.first().map(|b| prohibit_projection(this.tcx(), b.span));
 
     create_substs_for_ast_path(this,
                                span,
@@ -580,10 +580,11 @@ fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>,
 /// Returns the appropriate lifetime to use for any output lifetimes
 /// (if one exists) and a vector of the (pattern, number of lifetimes)
 /// corresponding to each input type/pattern.
-fn find_implied_output_region<'tcx>(tcx: &TyCtxt<'tcx>,
+fn find_implied_output_region<'tcx>(this: &AstConv<'tcx>,
                                     input_tys: &[Ty<'tcx>],
                                     input_pats: Vec<String>) -> ElidedLifetime
 {
+    let tcx = this.tcx();
     let mut lifetimes_for_params = Vec::new();
     let mut possible_implied_output_region = None;
 
@@ -655,7 +656,7 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
                    .collect::<Vec<Ty<'tcx>>>();
 
     let input_params = vec![String::new(); inputs.len()];
-    let implied_output_region = find_implied_output_region(this.tcx(), &inputs, input_params);
+    let implied_output_region = find_implied_output_region(this, &inputs, input_params);
 
     let input_ty = this.tcx().mk_tup(inputs);
 
@@ -824,7 +825,7 @@ fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
                                         trait_def_id,
                                         self_ty,
                                         trait_segment);
-    prohibit_projections(this.tcx(), &assoc_bindings);
+    assoc_bindings.first().map(|b| prohibit_projection(this.tcx(), b.span));
     ty::TraitRef::new(trait_def_id, substs)
 }
 
@@ -960,7 +961,7 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
         }
     }
 
-    let candidate = one_bound_for_assoc_type(tcx,
+    let candidate = one_bound_for_assoc_type(this,
                                              candidates,
                                              &trait_ref.to_string(),
                                              &binding.item_name.as_str(),
@@ -1219,7 +1220,7 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
         .filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
         .collect();
 
-    one_bound_for_assoc_type(tcx,
+    one_bound_for_assoc_type(this,
                              suitable_bounds,
                              &ty_param_name.as_str(),
                              &assoc_name.as_str(),
@@ -1229,7 +1230,7 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
 
 // Checks that bounds contains exactly one element and reports appropriate
 // errors otherwise.
-fn one_bound_for_assoc_type<'tcx>(tcx: &TyCtxt<'tcx>,
+fn one_bound_for_assoc_type<'tcx>(this: &AstConv<'tcx>,
                                   bounds: Vec<ty::PolyTraitRef<'tcx>>,
                                   ty_param_name: &str,
                                   assoc_name: &str,
@@ -1237,7 +1238,7 @@ fn one_bound_for_assoc_type<'tcx>(tcx: &TyCtxt<'tcx>,
     -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
 {
     if bounds.is_empty() {
-        span_err!(tcx.sess, span, E0220,
+        span_err!(this.tcx().sess, span, E0220,
                   "associated type `{}` not found for `{}`",
                   assoc_name,
                   ty_param_name);
@@ -1245,7 +1246,7 @@ fn one_bound_for_assoc_type<'tcx>(tcx: &TyCtxt<'tcx>,
     }
 
     if bounds.len() > 1 {
-        let mut err = struct_span_err!(tcx.sess, span, E0221,
+        let mut err = struct_span_err!(this.tcx().sess, span, E0221,
                                        "ambiguous associated type `{}` in bounds of `{}`",
                                        assoc_name,
                                        ty_param_name);
@@ -1305,7 +1306,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
                                                                      assoc_name))
                 .collect();
 
-            match one_bound_for_assoc_type(tcx,
+            match one_bound_for_assoc_type(this,
                                            candidates,
                                            "Self",
                                            &assoc_name.as_str(),
@@ -1814,7 +1815,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
     // have that lifetime.
     let implied_output_region = match explicit_self_category {
         Some(ty::ExplicitSelfCategory::ByReference(region, _)) => Ok(region),
-        _ => find_implied_output_region(this.tcx(), &arg_tys, arg_pats)
+        _ => find_implied_output_region(this, &arg_tys, arg_pats)
     };
 
     let output_ty = match decl.output {
@@ -2208,14 +2209,6 @@ pub fn partition_bounds<'a>(tcx: &TyCtxt,
     }
 }
 
-fn prohibit_projections<'tcx>(tcx: &TyCtxt<'tcx>,
-                              bindings: &[ConvertedBinding<'tcx>])
-{
-    for binding in bindings.iter().take(1) {
-        prohibit_projection(tcx, binding.span);
-    }
-}
-
 fn check_type_argument_count(tcx: &TyCtxt, span: Span, supplied: usize,
                              required: usize, accepted: usize) {
     if supplied < required {
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 544fb117f36..b07437d299b 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -116,7 +116,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
             // Check that the types of the end-points can be unified.
             let types_unify = require_same_types(
-                tcx, Some(fcx.infcx()), false, pat.span, rhs_ty, lhs_ty,
+                fcx.ccx, Some(fcx.infcx()), pat.span, rhs_ty, lhs_ty,
                 "mismatched types in range",
             );
 
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index a96b739ebcf..5d37d5123e4 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -251,7 +251,7 @@ fn confirm_builtin_call<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
             // In that case, we check each argument against "error" in order to
             // set up all the node type bindings.
             error_fn_sig = ty::Binder(ty::FnSig {
-                inputs: err_args(fcx.tcx(), arg_exprs.len()),
+                inputs: err_args(fcx, arg_exprs.len()),
                 output: ty::FnConverging(fcx.tcx().types.err),
                 variadic: false
             });
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 36944733dc8..28d8206a145 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -10,13 +10,14 @@
 
 use middle::free_region::FreeRegionMap;
 use rustc::infer::{self, InferCtxt, InferOk, TypeOrigin};
-use rustc::ty::{self, TyCtxt};
+use rustc::ty;
 use rustc::traits::{self, ProjectionMode};
 use rustc::ty::subst::{self, Subst, Substs, VecPerParamSpace};
 
 use syntax::ast;
 use syntax::codemap::Span;
 
+use CrateCtxt;
 use super::assoc;
 
 /// Checks that a method from an impl conforms to the signature of
@@ -30,18 +31,19 @@ use super::assoc;
 /// - trait_m: the method in the trait
 /// - impl_trait_ref: the TraitRef corresponding to the trait implementation
 
-pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
-                                 impl_m: &ty::Method<'tcx>,
-                                 impl_m_span: Span,
-                                 impl_m_body_id: ast::NodeId,
-                                 trait_m: &ty::Method<'tcx>,
-                                 impl_trait_ref: &ty::TraitRef<'tcx>) {
+pub fn compare_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                     impl_m: &ty::Method<'tcx>,
+                                     impl_m_span: Span,
+                                     impl_m_body_id: ast::NodeId,
+                                     trait_m: &ty::Method<'tcx>,
+                                     impl_trait_ref: &ty::TraitRef<'tcx>) {
     debug!("compare_impl_method(impl_trait_ref={:?})",
            impl_trait_ref);
 
     debug!("compare_impl_method: impl_trait_ref (liberated) = {:?}",
            impl_trait_ref);
 
+    let tcx = ccx.tcx;
     let mut infcx = InferCtxt::new(tcx, &tcx.tables, None, ProjectionMode::AnyFinal);
     let mut fulfillment_cx = traits::FulfillmentContext::new();
 
@@ -186,7 +188,7 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
 
     // Check region bounds. FIXME(@jroesch) refactor this away when removing
     // ParamBounds.
-    if !check_region_bounds_on_impl_method(tcx,
+    if !check_region_bounds_on_impl_method(ccx,
                                            impl_m_span,
                                            impl_m,
                                            &trait_m.generics,
@@ -364,14 +366,14 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
 
     infcx.resolve_regions_and_report_errors(&free_regions, impl_m_body_id);
 
-    fn check_region_bounds_on_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
-                                                span: Span,
-                                                impl_m: &ty::Method<'tcx>,
-                                                trait_generics: &ty::Generics<'tcx>,
-                                                impl_generics: &ty::Generics<'tcx>,
-                                                trait_to_skol_substs: &Substs<'tcx>,
-                                                impl_to_skol_substs: &Substs<'tcx>)
-                                                -> bool
+    fn check_region_bounds_on_impl_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                                    span: Span,
+                                                    impl_m: &ty::Method<'tcx>,
+                                                    trait_generics: &ty::Generics<'tcx>,
+                                                    impl_generics: &ty::Generics<'tcx>,
+                                                    trait_to_skol_substs: &Substs<'tcx>,
+                                                    impl_to_skol_substs: &Substs<'tcx>)
+                                                    -> bool
     {
 
         let trait_params = trait_generics.regions.get_slice(subst::FnSpace);
@@ -397,7 +399,7 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
         // are zero. Since I don't quite know how to phrase things at
         // the moment, give a kind of vague error message.
         if trait_params.len() != impl_params.len() {
-            span_err!(tcx.sess, span, E0195,
+            span_err!(ccx.tcx.sess, span, E0195,
                 "lifetime parameters or bounds on method `{}` do \
                          not match the trait declaration",
                          impl_m.name);
@@ -408,14 +410,15 @@ pub fn compare_impl_method<'tcx>(tcx: &TyCtxt<'tcx>,
     }
 }
 
-pub fn compare_const_impl<'tcx>(tcx: &TyCtxt<'tcx>,
-                                impl_c: &ty::AssociatedConst<'tcx>,
-                                impl_c_span: Span,
-                                trait_c: &ty::AssociatedConst<'tcx>,
-                                impl_trait_ref: &ty::TraitRef<'tcx>) {
+pub fn compare_const_impl<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                    impl_c: &ty::AssociatedConst<'tcx>,
+                                    impl_c_span: Span,
+                                    trait_c: &ty::AssociatedConst<'tcx>,
+                                    impl_trait_ref: &ty::TraitRef<'tcx>) {
     debug!("compare_const_impl(impl_trait_ref={:?})",
            impl_trait_ref);
 
+    let tcx = ccx.tcx;
     let infcx = InferCtxt::new(tcx, &tcx.tables, None, ProjectionMode::AnyFinal);
     let mut fulfillment_cx = traits::FulfillmentContext::new();
 
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 2e2b3686f85..0ddf616bb54 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -8,6 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
+use CrateCtxt;
 use check::regionck::{self, Rcx};
 
 use hir::def_id::DefId;
@@ -15,7 +16,7 @@ use middle::free_region::FreeRegionMap;
 use rustc::infer::{self, InferCtxt};
 use middle::region;
 use rustc::ty::subst::{self, Subst};
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty};
 use rustc::traits::{self, ProjectionMode};
 use util::nodemap::FnvHashSet;
 
@@ -39,20 +40,20 @@ use syntax::codemap::{self, Span};
 ///    struct/enum definition for the nominal type itself (i.e.
 ///    cannot do `struct S<T>; impl<T:Clone> Drop for S<T> { ... }`).
 ///
-pub fn check_drop_impl(tcx: &TyCtxt, drop_impl_did: DefId) -> Result<(), ()> {
+pub fn check_drop_impl(ccx: &CrateCtxt, drop_impl_did: DefId) -> Result<(), ()> {
     let ty::TypeScheme { generics: ref dtor_generics,
-                         ty: dtor_self_type } = tcx.lookup_item_type(drop_impl_did);
-    let dtor_predicates = tcx.lookup_predicates(drop_impl_did);
+                         ty: dtor_self_type } = ccx.tcx.lookup_item_type(drop_impl_did);
+    let dtor_predicates = ccx.tcx.lookup_predicates(drop_impl_did);
     match dtor_self_type.sty {
         ty::TyEnum(adt_def, self_to_impl_substs) |
         ty::TyStruct(adt_def, self_to_impl_substs) => {
-            ensure_drop_params_and_item_params_correspond(tcx,
+            ensure_drop_params_and_item_params_correspond(ccx,
                                                           drop_impl_did,
                                                           dtor_generics,
                                                           &dtor_self_type,
                                                           adt_def.did)?;
 
-            ensure_drop_predicates_are_implied_by_item_defn(tcx,
+            ensure_drop_predicates_are_implied_by_item_defn(ccx,
                                                             drop_impl_did,
                                                             &dtor_predicates,
                                                             adt_def.did,
@@ -61,7 +62,7 @@ pub fn check_drop_impl(tcx: &TyCtxt, drop_impl_did: DefId) -> Result<(), ()> {
         _ => {
             // Destructors only work on nominal types.  This was
             // already checked by coherence, so we can panic here.
-            let span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
+            let span = ccx.tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
             span_bug!(span,
                       "should have been rejected by coherence check: {}",
                       dtor_self_type);
@@ -69,13 +70,14 @@ pub fn check_drop_impl(tcx: &TyCtxt, drop_impl_did: DefId) -> Result<(), ()> {
     }
 }
 
-fn ensure_drop_params_and_item_params_correspond<'tcx>(
-    tcx: &TyCtxt<'tcx>,
+fn ensure_drop_params_and_item_params_correspond<'a, 'tcx>(
+    ccx: &CrateCtxt<'a, 'tcx>,
     drop_impl_did: DefId,
     drop_impl_generics: &ty::Generics<'tcx>,
     drop_impl_ty: &ty::Ty<'tcx>,
     self_type_did: DefId) -> Result<(), ()>
 {
+    let tcx = ccx.tcx;
     let drop_impl_node_id = tcx.map.as_local_node_id(drop_impl_did).unwrap();
     let self_type_node_id = tcx.map.as_local_node_id(self_type_did).unwrap();
 
@@ -124,8 +126,8 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
 
 /// Confirms that every predicate imposed by dtor_predicates is
 /// implied by assuming the predicates attached to self_type_did.
-fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
-    tcx: &TyCtxt<'tcx>,
+fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
+    ccx: &CrateCtxt<'a, 'tcx>,
     drop_impl_did: DefId,
     dtor_predicates: &ty::GenericPredicates<'tcx>,
     self_type_did: DefId,
@@ -166,6 +168,8 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
     // absent. So we report an error that the Drop impl injected a
     // predicate that is not present on the struct definition.
 
+    let tcx = ccx.tcx;
+
     let self_type_node_id = tcx.map.as_local_node_id(self_type_did).unwrap();
 
     let drop_impl_span = tcx.map.def_id_span(drop_impl_did, codemap::DUMMY_SP);
@@ -407,7 +411,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
     // unbounded type parameter `T`, we must resume the recursive
     // analysis on `T` (since it would be ignored by
     // type_must_outlive).
-    if has_dtor_of_interest(tcx, ty) {
+    if has_dtor_of_interest(cx, ty) {
         debug!("iterate_over_potentially_unsafe_regions_in_type \
                 {}ty: {} - is a dtorck type!",
                (0..depth).map(|_| ' ').collect::<String>(),
@@ -499,11 +503,11 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
     }
 }
 
-fn has_dtor_of_interest<'tcx>(tcx: &TyCtxt<'tcx>,
-                              ty: ty::Ty<'tcx>) -> bool {
+fn has_dtor_of_interest<'a, 'b, 'tcx>(cx: &DropckContext<'a, 'b, 'tcx>,
+                                      ty: ty::Ty<'tcx>) -> bool {
     match ty.sty {
         ty::TyEnum(def, _) | ty::TyStruct(def, _) => {
-            def.is_dtorck(tcx)
+            def.is_dtorck(cx.rcx.tcx())
         }
         ty::TyTrait(..) | ty::TyProjection(..) => {
             debug!("ty: {:?} isn't known, and therefore is a dropck type", ty);
diff --git a/src/librustc_typeck/check/intrinsic.rs b/src/librustc_typeck/check/intrinsic.rs
index 29a9ae9e516..79aa647d239 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -14,7 +14,7 @@
 use intrinsics;
 use rustc::ty::subst::{self, Substs};
 use rustc::ty::FnSig;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, Ty};
 use {CrateCtxt, require_same_types};
 
 use std::collections::{HashMap};
@@ -25,11 +25,13 @@ use syntax::parse::token;
 
 use rustc::hir;
 
-fn equate_intrinsic_type<'a, 'tcx>(tcx: &TyCtxt<'tcx>, it: &hir::ForeignItem,
+fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                   it: &hir::ForeignItem,
                                    n_tps: usize,
                                    abi: Abi,
                                    inputs: Vec<ty::Ty<'tcx>>,
                                    output: ty::FnOutput<'tcx>) {
+    let tcx = ccx.tcx;
     let def_id = tcx.map.local_def_id(it.id);
     let i_ty = tcx.lookup_item_type(def_id);
 
@@ -52,9 +54,8 @@ fn equate_intrinsic_type<'a, 'tcx>(tcx: &TyCtxt<'tcx>, it: &hir::ForeignItem,
              parameters: found {}, expected {}",
              i_n_tps, n_tps);
     } else {
-        require_same_types(tcx,
+        require_same_types(ccx,
                            None,
-                           false,
                            it.span,
                            i_ty.ty,
                            fty,
@@ -304,14 +305,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &hir::ForeignItem) {
         };
         (n_tps, inputs, ty::FnConverging(output))
     };
-    equate_intrinsic_type(
-        tcx,
-        it,
-        n_tps,
-        Abi::RustIntrinsic,
-        inputs,
-        output
-        )
+    equate_intrinsic_type(ccx, it, n_tps, Abi::RustIntrinsic, inputs, output)
 }
 
 /// Type-check `extern "platform-intrinsic" { ... }` functions.
@@ -377,10 +371,10 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt,
                     }
                     let input_pairs = intr.inputs.iter().zip(&sig.inputs);
                     for (i, (expected_arg, arg)) in input_pairs.enumerate() {
-                        match_intrinsic_type_to_type(tcx, &format!("argument {}", i + 1), it.span,
+                        match_intrinsic_type_to_type(ccx, &format!("argument {}", i + 1), it.span,
                                                      &mut structural_to_nomimal, expected_arg, arg);
                     }
-                    match_intrinsic_type_to_type(tcx, "return value", it.span,
+                    match_intrinsic_type_to_type(ccx, "return value", it.span,
                                                  &mut structural_to_nomimal,
                                                  &intr.output, sig.output.unwrap());
                     return
@@ -394,21 +388,15 @@ pub fn check_platform_intrinsic_type(ccx: &CrateCtxt,
         }
     };
 
-    equate_intrinsic_type(
-        tcx,
-        it,
-        n_tps,
-        Abi::PlatformIntrinsic,
-        inputs,
-        ty::FnConverging(output)
-        )
+    equate_intrinsic_type(ccx, it, n_tps, Abi::PlatformIntrinsic,
+                          inputs, ty::FnConverging(output))
 }
 
 // walk the expected type and the actual type in lock step, checking they're
 // the same, in a kinda-structural way, i.e. `Vector`s have to be simd structs with
 // exactly the right element type
 fn match_intrinsic_type_to_type<'tcx, 'a>(
-        tcx: &TyCtxt<'tcx>,
+        ccx: &CrateCtxt<'a, 'tcx>,
         position: &str,
         span: Span,
         structural_to_nominal: &mut HashMap<&'a intrinsics::Type, ty::Ty<'tcx>>,
@@ -417,7 +405,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
     use intrinsics::Type::*;
 
     let simple_error = |real: &str, expected: &str| {
-        span_err!(tcx.sess, span, E0442,
+        span_err!(ccx.tcx.sess, span, E0442,
                   "intrinsic {} has wrong type: found {}, expected {}",
                   position, real, expected)
     };
@@ -455,7 +443,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
                         simple_error(&format!("`{}`", t),
                                      if const_ {"const pointer"} else {"mut pointer"})
                     }
-                    match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal,
+                    match_intrinsic_type_to_type(ccx, position, span, structural_to_nominal,
                                                  inner_expected, ty)
                 }
                 _ => simple_error(&format!("`{}`", t), "raw pointer"),
@@ -466,19 +454,19 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
                 simple_error(&format!("non-simd type `{}`", t), "simd type");
                 return;
             }
-            let t_len = t.simd_size(tcx);
+            let t_len = t.simd_size(ccx.tcx);
             if len as usize != t_len {
                 simple_error(&format!("vector with length {}", t_len),
                              &format!("length {}", len));
                 return;
             }
-            let t_ty = t.simd_type(tcx);
+            let t_ty = t.simd_type(ccx.tcx);
             {
                 // check that a given structural type always has the same an intrinsic definition
                 let previous = structural_to_nominal.entry(expected).or_insert(t);
                 if *previous != t {
                     // this gets its own error code because it is non-trivial
-                    span_err!(tcx.sess, span, E0443,
+                    span_err!(ccx.tcx.sess, span, E0443,
                               "intrinsic {} has wrong type: found `{}`, expected `{}` which \
                                was used for this vector type previously in this signature",
                               position,
@@ -487,7 +475,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
                     return;
                 }
             }
-            match_intrinsic_type_to_type(tcx,
+            match_intrinsic_type_to_type(ccx,
                                          position,
                                          span,
                                          structural_to_nominal,
@@ -503,7 +491,7 @@ fn match_intrinsic_type_to_type<'tcx, 'a>(
                         return
                     }
                     for (e, c) in expected_contents.iter().zip(contents) {
-                        match_intrinsic_type_to_type(tcx, position, span, structural_to_nominal,
+                        match_intrinsic_type_to_type(ccx, position, span, structural_to_nominal,
                                                      e, c)
                     }
                 }
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 26d1f50f8c5..467956b6497 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -15,7 +15,7 @@ use hir::def::Def;
 use hir::def_id::DefId;
 use rustc::ty::subst;
 use rustc::traits;
-use rustc::ty::{self, TyCtxt, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
+use rustc::ty::{self, ToPredicate, ToPolyTraitRef, TraitRef, TypeFoldable};
 use rustc::ty::adjustment::{AdjustDerefRef, AutoDerefRef, AutoPtr};
 use rustc::infer;
 
@@ -219,7 +219,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // Trait must have a method named `m_name` and it should not have
     // type parameters or early-bound regions.
     let tcx = fcx.tcx();
-    let method_item = trait_item(tcx, trait_def_id, m_name).unwrap();
+    let method_item = trait_item(fcx, trait_def_id, m_name).unwrap();
     let method_ty = method_item.as_opt_method().unwrap();
     assert_eq!(method_ty.generics.types.len(subst::FnSpace), 0);
     assert_eq!(method_ty.generics.regions.len(subst::FnSpace), 0);
@@ -361,26 +361,26 @@ pub fn resolve_ufcs<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
 /// Find item with name `item_name` defined in `trait_def_id`
 /// and return it, or `None`, if no such item.
-fn trait_item<'tcx>(tcx: &TyCtxt<'tcx>,
-                    trait_def_id: DefId,
-                    item_name: ast::Name)
-                    -> Option<ty::ImplOrTraitItem<'tcx>>
+pub fn trait_item<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                            trait_def_id: DefId,
+                            item_name: ast::Name)
+                            -> Option<ty::ImplOrTraitItem<'tcx>>
 {
-    let trait_items = tcx.trait_items(trait_def_id);
+    let trait_items = fcx.tcx().trait_items(trait_def_id);
     trait_items.iter()
                .find(|item| item.name() == item_name)
                .cloned()
 }
 
-fn impl_item<'tcx>(tcx: &TyCtxt<'tcx>,
-                   impl_def_id: DefId,
-                   item_name: ast::Name)
-                   -> Option<ty::ImplOrTraitItem<'tcx>>
+pub fn impl_item<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                           impl_def_id: DefId,
+                           item_name: ast::Name)
+                           -> Option<ty::ImplOrTraitItem<'tcx>>
 {
-    let impl_items = tcx.impl_items.borrow();
+    let impl_items = fcx.tcx().impl_items.borrow();
     let impl_items = impl_items.get(&impl_def_id).unwrap();
     impl_items
         .iter()
-        .map(|&did| tcx.impl_or_trait_item(did.def_id()))
+        .map(|&did| fcx.tcx().impl_or_trait_item(did.def_id()))
         .find(|m| m.name() == item_name)
 }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 0e064fbc45b..96cedc76d05 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -406,7 +406,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
         debug!("assemble_inherent_impl_probe {:?}", impl_def_id);
 
-        let item = match impl_item(self.tcx(), impl_def_id, self.item_name) {
+        let item = match self.impl_item(impl_def_id) {
             Some(m) => m,
             None => { return; } // No method with correct name on this impl
         };
@@ -563,9 +563,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
         let tcx = self.tcx();
         for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
-            let item = match trait_item(tcx,
-                                        bound_trait_ref.def_id(),
-                                        self.item_name) {
+            let item = match self.trait_item(bound_trait_ref.def_id()) {
                 Some(v) => v,
                 None => { continue; }
             };
@@ -1311,33 +1309,20 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     {
         self.tcx().erase_late_bound_regions(value)
     }
-}
 
-fn impl_item<'tcx>(tcx: &TyCtxt<'tcx>,
-                   impl_def_id: DefId,
-                   item_name: ast::Name)
-                   -> Option<ty::ImplOrTraitItem<'tcx>>
-{
-    let impl_items = tcx.impl_items.borrow();
-    let impl_items = impl_items.get(&impl_def_id).unwrap();
-    impl_items
-        .iter()
-        .map(|&did| tcx.impl_or_trait_item(did.def_id()))
-        .find(|item| item.name() == item_name)
-}
+    fn impl_item(&self, impl_def_id: DefId)
+                 -> Option<ty::ImplOrTraitItem<'tcx>>
+    {
+        super::impl_item(self.fcx, impl_def_id, self.item_name)
+    }
 
-/// Find item with name `item_name` defined in `trait_def_id`
-/// and return it, or `None`, if no such item.
-fn trait_item<'tcx>(tcx: &TyCtxt<'tcx>,
-                    trait_def_id: DefId,
-                    item_name: ast::Name)
-                    -> Option<ty::ImplOrTraitItem<'tcx>>
-{
-    let trait_items = tcx.trait_items(trait_def_id);
-    debug!("trait_method; items: {:?}", trait_items);
-    trait_items.iter()
-               .find(|item| item.name() == item_name)
-               .cloned()
+    /// Find item with name `item_name` defined in `trait_def_id`
+    /// and return it, or `None`, if no such item.
+    fn trait_item(&self, trait_def_id: DefId)
+                  -> Option<ty::ImplOrTraitItem<'tcx>>
+    {
+        super::trait_item(self.fcx, trait_def_id, self.item_name)
+    }
 }
 
 impl<'tcx> Candidate<'tcx> {
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 6b90dcd54bf..9b81c4e2e92 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -233,10 +233,10 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 CandidateSource::ImplSource(impl_did) => {
                     // Provide the best span we can. Use the item, if local to crate, else
                     // the impl, if local to crate (item may be defaulted), else nothing.
-                    let item = impl_item(fcx.tcx(), impl_did, item_name)
+                    let item = impl_item(fcx, impl_did, item_name)
                         .or_else(|| {
                             trait_item(
-                                fcx.tcx(),
+                                fcx,
                                 fcx.tcx().impl_trait_ref(impl_did).unwrap().def_id,
                                 item_name
                             )
@@ -268,7 +268,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     }
                 }
                 CandidateSource::TraitSource(trait_did) => {
-                    let item = trait_item(fcx.tcx(), trait_did, item_name).unwrap();
+                    let item = trait_item(fcx, trait_did, item_name).unwrap();
                     let item_span = fcx.tcx().map.def_id_span(item.def_id(), span);
                     span_note!(err, item_span,
                                "candidate #{} is defined in the trait `{}`",
@@ -291,8 +291,6 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                       rcvr_expr: Option<&hir::Expr>,
                                       valid_out_of_scope_traits: Vec<DefId>)
 {
-    let tcx = fcx.tcx();
-
     if !valid_out_of_scope_traits.is_empty() {
         let mut candidates = valid_out_of_scope_traits;
         candidates.sort();
@@ -328,7 +326,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             // implementing a trait would be legal but is rejected
             // here).
             (type_is_local || info.def_id.is_local())
-                && trait_item(tcx, info.def_id, item_name).is_some()
+                && trait_item(fcx, info.def_id, item_name).is_some()
         })
         .collect::<Vec<_>>();
 
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 2ad64e44870..d9807cc7bae 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -413,7 +413,7 @@ pub fn check_drop_impls(ccx: &CrateCtxt) -> CompileResult {
         drop_trait.for_each_impl(ccx.tcx, |drop_impl_did| {
             let _task = ccx.tcx.dep_graph.in_task(DepNode::DropckImpl(drop_impl_did));
             if drop_impl_did.is_local() {
-                match dropck::check_drop_impl(ccx.tcx, drop_impl_did) {
+                match dropck::check_drop_impl(ccx, drop_impl_did) {
                     Ok(()) => {}
                     Err(()) => {
                         assert!(ccx.tcx.sess.has_errors());
@@ -947,7 +947,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
                     // Find associated const definition.
                     if let &ty::ConstTraitItem(ref trait_const) = ty_trait_item {
-                        compare_const_impl(ccx.tcx,
+                        compare_const_impl(ccx,
                                            &impl_const,
                                            impl_item.span,
                                            trait_const,
@@ -969,7 +969,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                     };
 
                     if let &ty::MethodTraitItem(ref trait_method) = ty_trait_item {
-                        compare_impl_method(ccx.tcx,
+                        compare_impl_method(ccx,
                                             &impl_method,
                                             impl_item.span,
                                             body.id,
@@ -2116,7 +2116,7 @@ pub fn autoderef<'a, 'b, 'tcx, E, I, T, F>(fcx: &FnCtxt<'a, 'tcx>,
                 let method_call = MethodCall::autoderef(expr.id, autoderefs as u32);
                 fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
             }
-            make_overloaded_lvalue_return_type(fcx.tcx(), method)
+            make_overloaded_lvalue_return_type(fcx, method)
         } else {
             return (resolved_t, autoderefs, None);
         };
@@ -2167,14 +2167,14 @@ fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 /// For the overloaded lvalue expressions (`*x`, `x[3]`), the trait returns a type of `&T`, but the
 /// actual type we assign to the *expression* is `T`. So this function just peels off the return
 /// type by one layer to yield `T`.
-fn make_overloaded_lvalue_return_type<'tcx>(tcx: &TyCtxt<'tcx>,
-                                            method: MethodCallee<'tcx>)
-                                            -> ty::TypeAndMut<'tcx>
+fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                                method: MethodCallee<'tcx>)
+                                                -> ty::TypeAndMut<'tcx>
 {
     // extract method return type, which will be &T;
     // all LB regions should have been instantiated during method lookup
     let ret_ty = method.ty.fn_ret();
-    let ret_ty = tcx.no_late_bound_regions(&ret_ty).unwrap().unwrap();
+    let ret_ty = fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap();
 
     // method returns &T, but the type as visible to user is T, so deref
     ret_ty.builtin_deref(true, NoPreference).unwrap()
@@ -2295,7 +2295,7 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     method.map(|method| {
         debug!("try_index_step: success, using overloaded indexing");
         fcx.inh.tables.borrow_mut().method_map.insert(method_call, method);
-        (input_ty, make_overloaded_lvalue_return_type(fcx.tcx(), method).ty)
+        (input_ty, make_overloaded_lvalue_return_type(fcx, method).ty)
     })
 }
 
@@ -2308,7 +2308,7 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          expected: Expectation<'tcx>)
                                          -> ty::FnOutput<'tcx> {
     if method_fn_ty.references_error() {
-        let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
+        let err_inputs = err_args(fcx, args_no_rcvr.len());
 
         let err_inputs = match tuple_arguments {
             DontTupleArguments => err_inputs,
@@ -2387,7 +2387,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         args.len(),
                         if args.len() == 1 {" was"} else {"s were"});
                     expected_arg_tys = &[];
-                    err_args(fcx.tcx(), args.len())
+                    err_args(fcx, args.len())
                 } else {
                     expected_arg_tys = match expected_arg_tys.get(0) {
                         Some(&ty) => match ty.sty {
@@ -2404,7 +2404,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     "cannot use call notation; the first type parameter \
                      for the function trait is neither a tuple nor unit");
                 expected_arg_tys = &[];
-                err_args(fcx.tcx(), args.len())
+                err_args(fcx, args.len())
             }
         }
     } else if expected_arg_count == supplied_arg_count {
@@ -2421,7 +2421,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 supplied_arg_count,
                 if supplied_arg_count == 1 {" was"} else {"s were"});
             expected_arg_tys = &[];
-            err_args(fcx.tcx(), supplied_arg_count)
+            err_args(fcx, supplied_arg_count)
         }
     } else {
         span_err!(tcx.sess, sp, E0061,
@@ -2431,7 +2431,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             supplied_arg_count,
             if supplied_arg_count == 1 {" was"} else {"s were"});
         expected_arg_tys = &[];
-        err_args(fcx.tcx(), supplied_arg_count)
+        err_args(fcx, supplied_arg_count)
     };
 
     debug!("check_argument_types: formal_tys={:?}",
@@ -2490,7 +2490,7 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 // The special-cased logic below has three functions:
                 // 1. Provide as good of an expected type as possible.
                 let expected = expected_arg_tys.get(i).map(|&ty| {
-                    Expectation::rvalue_hint(fcx.tcx(), ty)
+                    Expectation::rvalue_hint(fcx, ty)
                 });
 
                 check_expr_with_expectation(fcx, &arg,
@@ -2571,9 +2571,8 @@ fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     }
 }
 
-// FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
-fn err_args<'tcx>(tcx: &TyCtxt<'tcx>, len: usize) -> Vec<Ty<'tcx>> {
-    (0..len).map(|_| tcx.types.err).collect()
+fn err_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, len: usize) -> Vec<Ty<'tcx>> {
+    (0..len).map(|_| fcx.tcx().types.err).collect()
 }
 
 fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
@@ -3241,7 +3240,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
       hir::ExprBox(ref subexpr) => {
         let expected_inner = expected.to_option(fcx).map_or(NoExpectation, |ty| {
             match ty.sty {
-                ty::TyBox(ty) => Expectation::rvalue_hint(tcx, ty),
+                ty::TyBox(ty) => Expectation::rvalue_hint(fcx, ty),
                 _ => NoExpectation
             }
         });
@@ -3286,7 +3285,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         oprnd_t = mt.ty;
                     } else if let Some(method) = try_overloaded_deref(
                             fcx, expr.span, Some(&oprnd), oprnd_t, lvalue_pref) {
-                        oprnd_t = make_overloaded_lvalue_return_type(tcx, method).ty;
+                        oprnd_t = make_overloaded_lvalue_return_type(fcx, method).ty;
                         fcx.inh.tables.borrow_mut().method_map.insert(MethodCall::expr(expr.id),
                                                                       method);
                     } else {
@@ -3329,7 +3328,7 @@ fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                         // the last field of a struct can be unsized.
                         ExpectHasType(mt.ty)
                     } else {
-                        Expectation::rvalue_hint(tcx, mt.ty)
+                        Expectation::rvalue_hint(fcx, mt.ty)
                     }
                 }
                 _ => NoExpectation
@@ -3810,8 +3809,8 @@ impl<'tcx> Expectation<'tcx> {
     /// which still is useful, because it informs integer literals and the like.
     /// See the test case `test/run-pass/coerce-expect-unsized.rs` and #20169
     /// for examples of where this comes up,.
-    fn rvalue_hint(tcx: &TyCtxt<'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
-        match tcx.struct_tail(ty).sty {
+    fn rvalue_hint<'a>(fcx: &FnCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
+        match fcx.tcx().struct_tail(ty).sty {
             ty::TySlice(_) | ty::TyStr | ty::TyTrait(..) => {
                 ExpectRvalueLikeUnsized(ty)
             }
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index ffdae233970..17856dc4255 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -414,7 +414,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
 
         let _ = ::require_same_types(
-            fcx.tcx(), Some(fcx.infcx()), false, span,
+            fcx.ccx, Some(fcx.infcx()), span,
             sig.inputs[0], rcvr_ty,
             "mismatched method receiver");
     }
@@ -435,8 +435,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                      .map(|p| Parameter::Type(p))
                      .collect();
 
-        identify_constrained_type_params(self.tcx(),
-                                         ty_predicates.predicates.as_slice(),
+        identify_constrained_type_params(ty_predicates.predicates.as_slice(),
                                          None,
                                          &mut constrained_parameters);
 
@@ -494,7 +493,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                          span: Span,
                          param_name: ast::Name)
     {
-        let mut err = error_392(self.tcx(), span, param_name);
+        let mut err = error_392(self.ccx, span, param_name);
 
         let suggested_marker_id = self.tcx().lang_items.phantom_data();
         match suggested_marker_id {
@@ -512,9 +511,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 }
 
-fn reject_shadowing_type_parameters<'tcx>(tcx: &TyCtxt<'tcx>,
-                                          span: Span,
-                                          generics: &ty::Generics<'tcx>) {
+fn reject_shadowing_type_parameters(tcx: &TyCtxt, span: Span, generics: &ty::Generics) {
     let impl_params = generics.types.get_slice(subst::TypeSpace).iter()
         .map(|tp| tp.name).collect::<HashSet<_>>();
 
@@ -607,25 +604,25 @@ fn impl_implied_bounds<'fcx,'tcx>(fcx: &FnCtxt<'fcx, 'tcx>,
     }
 }
 
-pub fn error_192<'ccx,'tcx>(ccx: &'ccx CrateCtxt<'ccx, 'tcx>, span: Span) {
+fn error_192(ccx: &CrateCtxt, span: Span) {
     span_err!(ccx.tcx.sess, span, E0192,
               "negative impls are only allowed for traits with \
                default impls (e.g., `Send` and `Sync`)")
 }
 
-pub fn error_380<'ccx,'tcx>(ccx: &'ccx CrateCtxt<'ccx, 'tcx>, span: Span) {
+fn error_380(ccx: &CrateCtxt, span: Span) {
     span_err!(ccx.tcx.sess, span, E0380,
               "traits with default impls (`e.g. unsafe impl \
                Trait for ..`) must have no methods or associated items")
 }
 
-pub fn error_392<'tcx>(tcx: &TyCtxt<'tcx>, span: Span, param_name: ast::Name)
+fn error_392<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, span: Span, param_name: ast::Name)
                        -> DiagnosticBuilder<'tcx> {
-    struct_span_err!(tcx.sess, span, E0392,
+    struct_span_err!(ccx.tcx.sess, span, E0392,
                      "parameter `{}` is never used", param_name)
 }
 
-pub fn error_194<'tcx>(tcx: &TyCtxt<'tcx>, span: Span, name: ast::Name) {
+fn error_194(tcx: &TyCtxt, span: Span, name: ast::Name) {
     span_err!(tcx.sess, span, E0194,
               "type parameter `{}` shadows another type parameter of the same name",
               name);
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 4341ae5dac1..a7039dcd91c 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -195,7 +195,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
 
         let var_ty = self.fcx.local_ty(l.span, l.id);
         let var_ty = self.resolve(&var_ty, ResolvingLocal(l.span));
-        write_ty_to_tcx(self.tcx(), l.id, var_ty);
+        write_ty_to_tcx(self.fcx.ccx, l.id, var_ty);
         intravisit::walk_local(self, l);
     }
 
@@ -203,7 +203,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         match t.node {
             hir::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&ty);
-                write_ty_to_tcx(self.tcx(), count_expr.id, self.tcx().types.usize);
+                write_ty_to_tcx(self.fcx.ccx, count_expr.id, self.tcx().types.usize);
             }
             hir::TyBareFn(ref function_declaration) => {
                 intravisit::walk_fn_decl_nopat(self, &function_declaration.decl);
@@ -263,12 +263,12 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
         // Resolve the type of the node with id `id`
         let n_ty = self.fcx.node_ty(id);
         let n_ty = self.resolve(&n_ty, reason);
-        write_ty_to_tcx(self.tcx(), id, n_ty);
+        write_ty_to_tcx(self.fcx.ccx, id, n_ty);
         debug!("Node {} has type {:?}", id, n_ty);
 
         // Resolve any substitutions
         self.fcx.opt_node_ty_substs(id, |item_substs| {
-            write_substs_to_tcx(self.tcx(), id,
+            write_substs_to_tcx(self.fcx.ccx, id,
                                 self.resolve(item_substs, reason));
         });
     }
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 787324897a3..9393dd1bce7 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -87,9 +87,7 @@ use std::collections::HashSet;
 use std::collections::hash_map::Entry::{Occupied, Vacant};
 use std::rc::Rc;
 
-use syntax::abi;
-use syntax::ast;
-use syntax::attr;
+use syntax::{abi, ast, attr};
 use syntax::codemap::Span;
 use syntax::parse::token::keywords;
 use syntax::ptr::P;
@@ -565,7 +563,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     });
     ccx.tcx.predicates.borrow_mut().insert(def_id, ty_method.predicates.clone());
 
-    write_ty_to_tcx(ccx.tcx, id, fty);
+    write_ty_to_tcx(ccx, id, fty);
 
     debug!("writing method type: def_id={:?} mty={:?}",
             def_id, ty_method);
@@ -582,7 +580,7 @@ fn convert_field<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 {
     let tt = ccx.icx(struct_predicates).to_ty(&ExplicitRscope, &field.ty);
     ty_f.fulfill_ty(tt);
-    write_ty_to_tcx(ccx.tcx, field.id, tt);
+    write_ty_to_tcx(ccx, field.id, tt);
 
     /* add the field to the tcache */
     ccx.tcx.register_item_type(ccx.tcx.map.local_def_id(field.id),
@@ -606,7 +604,7 @@ fn convert_associated_const<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     ccx.tcx.predicates.borrow_mut().insert(ccx.tcx.map.local_def_id(id),
                                            ty::GenericPredicates::empty());
 
-    write_ty_to_tcx(ccx.tcx, id, ty);
+    write_ty_to_tcx(ccx, id, ty);
 
     let associated_const = Rc::new(ty::AssociatedConst {
         name: name,
@@ -684,7 +682,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
         }
         hir::ItemEnum(ref enum_definition, _) => {
             let (scheme, predicates) = convert_typed_item(ccx, it);
-            write_ty_to_tcx(tcx, it.id, scheme.ty);
+            write_ty_to_tcx(ccx, it.id, scheme.ty);
             convert_enum_variant_types(ccx,
                                        tcx.lookup_adt_def_master(ccx.tcx.map.local_def_id(it.id)),
                                        scheme,
@@ -717,7 +715,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
             debug!("convert: impl_bounds={:?}", ty_predicates);
 
             let selfty = ccx.icx(&ty_predicates).to_ty(&ExplicitRscope, &selfty);
-            write_ty_to_tcx(tcx, it.id, selfty);
+            write_ty_to_tcx(ccx, it.id, selfty);
 
             tcx.register_item_type(def_id,
                                    TypeScheme { generics: ty_generics.clone(),
@@ -730,7 +728,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
             });
             tcx.impl_trait_refs.borrow_mut().insert(def_id, trait_ref);
 
-            enforce_impl_params_are_constrained(tcx, generics, &mut ty_predicates, def_id);
+            enforce_impl_params_are_constrained(ccx, generics, &mut ty_predicates, def_id);
             tcx.predicates.borrow_mut().insert(def_id, ty_predicates.clone());
 
 
@@ -807,7 +805,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                 }
             }
 
-            enforce_impl_lifetimes_are_constrained(tcx, generics, def_id, impl_items);
+            enforce_impl_lifetimes_are_constrained(ccx, generics, def_id, impl_items);
         },
         hir::ItemTrait(_, _, _, ref trait_items) => {
             let trait_def = trait_def_of_item(ccx, it);
@@ -891,7 +889,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
         },
         hir::ItemStruct(ref struct_def, _) => {
             let (scheme, predicates) = convert_typed_item(ccx, it);
-            write_ty_to_tcx(tcx, it.id, scheme.ty);
+            write_ty_to_tcx(ccx, it.id, scheme.ty);
 
             let it_def_id = ccx.tcx.map.local_def_id(it.id);
             let variant = tcx.lookup_adt_def_master(it_def_id).struct_variant();
@@ -907,14 +905,14 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
         hir::ItemTy(_, ref generics) => {
             ensure_no_ty_param_bounds(ccx, it.span, generics, "type");
             let (scheme, _) = convert_typed_item(ccx, it);
-            write_ty_to_tcx(tcx, it.id, scheme.ty);
+            write_ty_to_tcx(ccx, it.id, scheme.ty);
         },
         _ => {
             // This call populates the type cache with the converted type
             // of the item in passing. All we have to do here is to write
             // it into the node type table.
             let (scheme, _) = convert_typed_item(ccx, it);
-            write_ty_to_tcx(tcx, it.id, scheme.ty);
+            write_ty_to_tcx(ccx, it.id, scheme.ty);
         },
     }
 }
@@ -946,7 +944,7 @@ fn convert_variant_ctor<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             })
         }
     };
-    write_ty_to_tcx(tcx, ctor_id, ctor_ty);
+    write_ty_to_tcx(ccx, ctor_id, ctor_ty);
     tcx.predicates.borrow_mut().insert(tcx.map.local_def_id(ctor_id), predicates);
     tcx.register_item_type(tcx.map.local_def_id(ctor_id),
                            TypeScheme {
@@ -978,18 +976,19 @@ fn convert_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-fn convert_struct_variant<'tcx>(tcx: &TyCtxt<'tcx>,
-                                did: DefId,
-                                name: ast::Name,
-                                disr_val: ty::Disr,
-                                def: &hir::VariantData) -> ty::VariantDefData<'tcx, 'tcx> {
+fn convert_struct_variant<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                    did: DefId,
+                                    name: ast::Name,
+                                    disr_val: ty::Disr,
+                                    def: &hir::VariantData)
+                                    -> ty::VariantDefData<'tcx, 'tcx> {
     let mut seen_fields: FnvHashMap<ast::Name, Span> = FnvHashMap();
-    let node_id = tcx.map.as_local_node_id(did).unwrap();
+    let node_id = ccx.tcx.map.as_local_node_id(did).unwrap();
     let fields = def.fields().iter().map(|f| {
-        let fid = tcx.map.local_def_id(f.id);
+        let fid = ccx.tcx.map.local_def_id(f.id);
         let dup_span = seen_fields.get(&f.name).cloned();
         if let Some(prev_span) = dup_span {
-            let mut err = struct_span_err!(tcx.sess, f.span, E0124,
+            let mut err = struct_span_err!(ccx.tcx.sess, f.span, E0124,
                                            "field `{}` is already declared",
                                            f.name);
             span_note!(&mut err, prev_span, "previously declared here");
@@ -998,7 +997,8 @@ fn convert_struct_variant<'tcx>(tcx: &TyCtxt<'tcx>,
             seen_fields.insert(f.name, f.span);
         }
 
-        ty::FieldDefData::new(fid, f.name, ty::Visibility::from_hir(&f.vis, node_id, tcx))
+        ty::FieldDefData::new(fid, f.name,
+            ty::Visibility::from_hir(&f.vis, node_id, ccx.tcx))
     }).collect();
     ty::VariantDefData {
         did: did,
@@ -1009,71 +1009,63 @@ fn convert_struct_variant<'tcx>(tcx: &TyCtxt<'tcx>,
     }
 }
 
-fn convert_struct_def<'tcx>(tcx: &TyCtxt<'tcx>,
-                            it: &hir::Item,
-                            def: &hir::VariantData)
-                            -> ty::AdtDefMaster<'tcx>
+fn convert_struct_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                it: &hir::Item,
+                                def: &hir::VariantData)
+                                -> ty::AdtDefMaster<'tcx>
 {
 
-    let did = tcx.map.local_def_id(it.id);
+    let did = ccx.tcx.map.local_def_id(it.id);
     let ctor_id = if !def.is_struct() {
-        tcx.map.local_def_id(def.id())
+        ccx.tcx.map.local_def_id(def.id())
     } else {
         did
     };
-    tcx.intern_adt_def(
-        did,
-        ty::AdtKind::Struct,
-        vec![convert_struct_variant(tcx, ctor_id, it.name, ConstInt::Infer(0), def)]
-    )
+    ccx.tcx.intern_adt_def(did, ty::AdtKind::Struct,
+        vec![convert_struct_variant(ccx, ctor_id, it.name, ConstInt::Infer(0), def)])
 }
 
-fn convert_enum_def<'tcx>(tcx: &TyCtxt<'tcx>,
-                          it: &hir::Item,
-                          def: &hir::EnumDef)
-                          -> ty::AdtDefMaster<'tcx>
-{
-    fn print_err(tcx: &TyCtxt, span: Span, ty: ty::Ty, cv: ConstVal) {
-        struct_span_err!(tcx.sess, span, E0079, "mismatched types")
-            .note_expected_found(&"type", &ty, &format!("{}", cv.description()))
-            .emit();
-    }
-    fn evaluate_disr_expr<'tcx>(tcx: &TyCtxt<'tcx>,
-                                repr_ty: attr::IntType,
-                                e: &hir::Expr) -> Option<ty::Disr> {
+    fn evaluate_disr_expr(ccx: &CrateCtxt, repr_ty: attr::IntType, e: &hir::Expr)
+                          -> Option<ty::Disr> {
         debug!("disr expr, checking {}", pprust::expr_to_string(e));
 
-        let ty_hint = repr_ty.to_ty(tcx);
+        let ty_hint = repr_ty.to_ty(ccx.tcx);
+        let print_err = |cv: ConstVal| {
+            struct_span_err!(ccx.tcx.sess, e.span, E0079, "mismatched types")
+                .note_expected_found(&"type", &ty_hint, &format!("{}", cv.description()))
+                .emit();
+        };
+
         let hint = UncheckedExprHint(ty_hint);
-        match eval_const_expr_partial(tcx, e, hint, None) {
+        match eval_const_expr_partial(ccx.tcx, e, hint, None) {
             Ok(ConstVal::Integral(i)) => {
                 // FIXME: eval_const_expr_partial should return an error if the hint is wrong
                 match (repr_ty, i) {
-                    (attr::SignedInt(ast::IntTy::I8), ConstInt::I8(_)) => Some(i),
-                    (attr::SignedInt(ast::IntTy::I16), ConstInt::I16(_)) => Some(i),
-                    (attr::SignedInt(ast::IntTy::I32), ConstInt::I32(_)) => Some(i),
-                    (attr::SignedInt(ast::IntTy::I64), ConstInt::I64(_)) => Some(i),
-                    (attr::SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) => Some(i),
-                    (attr::UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) => Some(i),
-                    (attr::UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) => Some(i),
-                    (attr::UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) => Some(i),
-                    (attr::UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) => Some(i),
+                    (attr::SignedInt(ast::IntTy::I8), ConstInt::I8(_)) |
+                    (attr::SignedInt(ast::IntTy::I16), ConstInt::I16(_)) |
+                    (attr::SignedInt(ast::IntTy::I32), ConstInt::I32(_)) |
+                    (attr::SignedInt(ast::IntTy::I64), ConstInt::I64(_)) |
+                    (attr::SignedInt(ast::IntTy::Is), ConstInt::Isize(_)) |
+                    (attr::UnsignedInt(ast::UintTy::U8), ConstInt::U8(_)) |
+                    (attr::UnsignedInt(ast::UintTy::U16), ConstInt::U16(_)) |
+                    (attr::UnsignedInt(ast::UintTy::U32), ConstInt::U32(_)) |
+                    (attr::UnsignedInt(ast::UintTy::U64), ConstInt::U64(_)) |
                     (attr::UnsignedInt(ast::UintTy::Us), ConstInt::Usize(_)) => Some(i),
                     (_, i) => {
-                        print_err(tcx, e.span, ty_hint, ConstVal::Integral(i));
+                        print_err(ConstVal::Integral(i));
                         None
                     },
                 }
             },
             Ok(cv) => {
-                print_err(tcx, e.span, ty_hint, cv);
+                print_err(cv);
                 None
             },
             // enum variant evaluation happens before the global constant check
             // so we need to report the real error
             Err(ConstEvalErr { kind: ErroneousReferencedConstant(box err), ..}) |
             Err(err) => {
-                let mut diag = struct_span_err!(tcx.sess, err.span, E0080,
+                let mut diag = struct_span_err!(ccx.tcx.sess, err.span, E0080,
                                                 "constant evaluation error: {}",
                                                 err.description());
                 if !e.span.contains(err.span) {
@@ -1085,54 +1077,34 @@ fn convert_enum_def<'tcx>(tcx: &TyCtxt<'tcx>,
         }
     }
 
-    fn report_discrim_overflow(tcx: &TyCtxt,
-                               variant_span: Span,
-                               variant_name: &str,
-                               prev_val: ty::Disr) {
-        span_err!(tcx.sess, variant_span, E0370,
-                  "enum discriminant overflowed on value after {}; \
-                   set explicitly via {} = {} if that is desired outcome",
-                  prev_val, variant_name, prev_val.wrap_incr());
-    }
-
-    fn next_disr(tcx: &TyCtxt,
-                 v: &hir::Variant,
-                 repr_type: attr::IntType,
-                 prev_disr_val: Option<ty::Disr>) -> Option<ty::Disr> {
-        if let Some(prev_disr_val) = prev_disr_val {
-            let result = repr_type.disr_incr(prev_disr_val);
-            if let None = result {
-                report_discrim_overflow(tcx, v.span, &v.node.name.as_str(), prev_disr_val);
-            }
-            result
-        } else {
-            Some(repr_type.initial_discriminant(tcx))
-        }
-    }
-    fn convert_enum_variant<'tcx>(tcx: &TyCtxt<'tcx>,
-                                  v: &hir::Variant,
-                                  disr: ty::Disr)
-                                  -> ty::VariantDefData<'tcx, 'tcx>
-    {
-        let did = tcx.map.local_def_id(v.node.data.id());
-        let name = v.node.name;
-        convert_struct_variant(tcx, did, name, disr, &v.node.data)
-    }
+fn convert_enum_def<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                              it: &hir::Item,
+                              def: &hir::EnumDef)
+                              -> ty::AdtDefMaster<'tcx>
+{
+    let tcx = ccx.tcx;
     let did = tcx.map.local_def_id(it.id);
     let repr_hints = tcx.lookup_repr_hints(did);
     let repr_type = tcx.enum_repr_type(repr_hints.get(0));
-    let mut prev_disr = None;
+    let initial = repr_type.initial_discriminant(tcx);
+    let mut prev_disr = None::<ty::Disr>;
     let variants = def.variants.iter().map(|v| {
-        let disr = match v.node.disr_expr {
-            Some(ref e) => evaluate_disr_expr(tcx, repr_type, e),
-            None => next_disr(tcx, v, repr_type, prev_disr)
-        }.unwrap_or_else(|| {
-            prev_disr.map(ty::Disr::wrap_incr)
-                     .unwrap_or(repr_type.initial_discriminant(tcx))
-        });
-
+        let wrapped_disr = prev_disr.map_or(initial, |d| d.wrap_incr());
+        let disr = if let Some(ref e) = v.node.disr_expr {
+            evaluate_disr_expr(ccx, repr_type, e)
+        } else if let Some(disr) = repr_type.disr_incr(tcx, prev_disr) {
+            Some(disr)
+        } else {
+            span_err!(tcx.sess, v.span, E0370,
+                      "enum discriminant overflowed on value after {}; \
+                       set explicitly via {} = {} if that is desired outcome",
+                      prev_disr.unwrap(), v.node.name, wrapped_disr);
+            None
+        }.unwrap_or(wrapped_disr);
         prev_disr = Some(disr);
-        convert_enum_variant(tcx, v, disr)
+
+        let did = tcx.map.local_def_id(v.node.data.id());
+        convert_struct_variant(ccx, did, v.node.name, disr, &v.node.data)
     }).collect();
     tcx.intern_adt_def(tcx.map.local_def_id(it.id), ty::AdtKind::Enum, variants)
 }
@@ -1471,16 +1443,16 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
         hir::ItemEnum(ref ei, ref generics) => {
+            let def = convert_enum_def(ccx, it, ei);
             let ty_generics = ty_generics_for_type(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
-            let def = convert_enum_def(tcx, it, ei);
             let t = tcx.mk_enum(def, tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
         hir::ItemStruct(ref si, ref generics) => {
+            let def = convert_struct_def(ccx, it, si);
             let ty_generics = ty_generics_for_type(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
-            let def = convert_struct_def(tcx, it, si);
             let t = tcx.mk_struct(def, tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
@@ -1606,7 +1578,7 @@ fn convert_foreign_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     let abi = tcx.map.get_foreign_abi(it.id);
 
     let scheme = type_scheme_of_foreign_item(ccx, it, abi);
-    write_ty_to_tcx(ccx.tcx, it.id, scheme.ty);
+    write_ty_to_tcx(ccx, it.id, scheme.ty);
 
     let predicates = match it.node {
         hir::ForeignItemFn(_, ref generics) => {
@@ -2229,13 +2201,13 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 }
 
 /// Checks that all the type parameters on an impl
-fn enforce_impl_params_are_constrained<'tcx>(tcx: &TyCtxt<'tcx>,
-                                             ast_generics: &hir::Generics,
-                                             impl_predicates: &mut ty::GenericPredicates<'tcx>,
-                                             impl_def_id: DefId)
+fn enforce_impl_params_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                                 ast_generics: &hir::Generics,
+                                                 impl_predicates: &mut ty::GenericPredicates<'tcx>,
+                                                 impl_def_id: DefId)
 {
-    let impl_scheme = tcx.lookup_item_type(impl_def_id);
-    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
+    let impl_scheme = ccx.tcx.lookup_item_type(impl_def_id);
+    let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id);
 
     assert!(impl_predicates.predicates.is_empty_in(FnSpace));
     assert!(impl_predicates.predicates.is_empty_in(SelfSpace));
@@ -2249,8 +2221,7 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &TyCtxt<'tcx>,
         input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref, false));
     }
 
-    ctp::setup_constraining_predicates(tcx,
-                                       impl_predicates.predicates.get_mut_slice(TypeSpace),
+    ctp::setup_constraining_predicates(impl_predicates.predicates.get_mut_slice(TypeSpace),
                                        impl_trait_ref,
                                        &mut input_parameters);
 
@@ -2259,42 +2230,41 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &TyCtxt<'tcx>,
                                      idx: index as u32,
                                      name: ty_param.name };
         if !input_parameters.contains(&ctp::Parameter::Type(param_ty)) {
-            report_unused_parameter(tcx, ty_param.span, "type", &param_ty.to_string());
+            report_unused_parameter(ccx, ty_param.span, "type", &param_ty.to_string());
         }
     }
 }
 
-fn enforce_impl_lifetimes_are_constrained<'tcx>(tcx: &TyCtxt<'tcx>,
-                                                ast_generics: &hir::Generics,
-                                                impl_def_id: DefId,
-                                                impl_items: &[hir::ImplItem])
+fn enforce_impl_lifetimes_are_constrained<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                                    ast_generics: &hir::Generics,
+                                                    impl_def_id: DefId,
+                                                    impl_items: &[hir::ImplItem])
 {
     // Every lifetime used in an associated type must be constrained.
-    let impl_scheme = tcx.lookup_item_type(impl_def_id);
-    let impl_predicates = tcx.lookup_predicates(impl_def_id);
-    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
+    let impl_scheme = ccx.tcx.lookup_item_type(impl_def_id);
+    let impl_predicates = ccx.tcx.lookup_predicates(impl_def_id);
+    let impl_trait_ref = ccx.tcx.impl_trait_ref(impl_def_id);
 
     let mut input_parameters: HashSet<_> =
         ctp::parameters_for_type(impl_scheme.ty, false).into_iter().collect();
     if let Some(ref trait_ref) = impl_trait_ref {
         input_parameters.extend(ctp::parameters_for_trait_ref(trait_ref, false));
     }
-    ctp::identify_constrained_type_params(tcx,
+    ctp::identify_constrained_type_params(
         &impl_predicates.predicates.as_slice(), impl_trait_ref, &mut input_parameters);
 
-    let lifetimes_in_associated_types: HashSet<_> =
-        impl_items.iter()
-                  .map(|item| tcx.impl_or_trait_item(tcx.map.local_def_id(item.id)))
-                  .filter_map(|item| match item {
-                      ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
-                      ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
-                  })
-                  .flat_map(|ty| ctp::parameters_for_type(ty, true))
-                  .filter_map(|p| match p {
-                      ctp::Parameter::Type(_) => None,
-                      ctp::Parameter::Region(r) => Some(r),
-                  })
-                  .collect();
+    let lifetimes_in_associated_types: HashSet<_> = impl_items.iter()
+        .map(|item| ccx.tcx.impl_or_trait_item(ccx.tcx.map.local_def_id(item.id)))
+        .filter_map(|item| match item {
+            ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
+            ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
+        })
+        .flat_map(|ty| ctp::parameters_for_type(ty, true))
+        .filter_map(|p| match p {
+            ctp::Parameter::Type(_) => None,
+            ctp::Parameter::Region(r) => Some(r),
+        })
+        .collect();
 
     for (index, lifetime_def) in ast_generics.lifetimes.iter().enumerate() {
         let region = ty::EarlyBoundRegion { space: TypeSpace,
@@ -2304,7 +2274,7 @@ fn enforce_impl_lifetimes_are_constrained<'tcx>(tcx: &TyCtxt<'tcx>,
             lifetimes_in_associated_types.contains(&region) && // (*)
             !input_parameters.contains(&ctp::Parameter::Region(region))
         {
-            report_unused_parameter(tcx, lifetime_def.lifetime.span,
+            report_unused_parameter(ccx, lifetime_def.lifetime.span,
                                     "lifetime", &region.name.to_string());
         }
     }
@@ -2329,12 +2299,12 @@ fn enforce_impl_lifetimes_are_constrained<'tcx>(tcx: &TyCtxt<'tcx>,
     // used elsewhere are not projected back out.
 }
 
-fn report_unused_parameter(tcx: &TyCtxt,
+fn report_unused_parameter(ccx: &CrateCtxt,
                            span: Span,
                            kind: &str,
                            name: &str)
 {
-    span_err!(tcx.sess, span, E0207,
+    span_err!(ccx.tcx.sess, span, E0207,
               "the {} parameter `{}` is not constrained by the \
                impl trait, self type, or predicates",
               kind, name);
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index 7e8b08c5853..08c1b5fcc82 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -8,8 +8,7 @@
 // option. This file may not be copied, modified, or distributed
 // except according to those terms.
 
-use rustc::ty::subst;
-use rustc::ty::{self, Ty, TyCtxt};
+use rustc::ty::{self, subst, Ty};
 
 use std::collections::HashSet;
 
@@ -94,13 +93,12 @@ fn parameters_for_region(region: &ty::Region) -> Option<Parameter> {
     }
 }
 
-pub fn identify_constrained_type_params<'tcx>(_tcx: &TyCtxt<'tcx>,
-                                              predicates: &[ty::Predicate<'tcx>],
+pub fn identify_constrained_type_params<'tcx>(predicates: &[ty::Predicate<'tcx>],
                                               impl_trait_ref: Option<ty::TraitRef<'tcx>>,
                                               input_parameters: &mut HashSet<Parameter>)
 {
     let mut predicates = predicates.to_owned();
-    setup_constraining_predicates(_tcx, &mut predicates, impl_trait_ref, input_parameters);
+    setup_constraining_predicates(&mut predicates, impl_trait_ref, input_parameters);
 }
 
 
@@ -144,8 +142,7 @@ pub fn identify_constrained_type_params<'tcx>(_tcx: &TyCtxt<'tcx>,
 /// which is determined by 1, which requires `U`, that is determined
 /// by 0. I should probably pick a less tangled example, but I can't
 /// think of any.
-pub fn setup_constraining_predicates<'tcx>(_tcx: &TyCtxt<'tcx>,
-                                           predicates: &mut [ty::Predicate<'tcx>],
+pub fn setup_constraining_predicates<'tcx>(predicates: &mut [ty::Predicate<'tcx>],
                                            impl_trait_ref: Option<ty::TraitRef<'tcx>>,
                                            input_parameters: &mut HashSet<Parameter>)
 {
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index c65b12b1829..e5e4fda10ef 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -153,13 +153,13 @@ pub struct CrateCtxt<'a, 'tcx: 'a> {
 }
 
 // Functions that write types into the node type table
-fn write_ty_to_tcx<'tcx>(tcx: &TyCtxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
+fn write_ty_to_tcx<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
     debug!("write_ty_to_tcx({}, {:?})", node_id,  ty);
     assert!(!ty.needs_infer());
-    tcx.node_type_insert(node_id, ty);
+    ccx.tcx.node_type_insert(node_id, ty);
 }
 
-fn write_substs_to_tcx<'tcx>(tcx: &TyCtxt<'tcx>,
+fn write_substs_to_tcx<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                  node_id: ast::NodeId,
                                  item_substs: ty::ItemSubsts<'tcx>) {
     if !item_substs.is_noop() {
@@ -169,7 +169,7 @@ fn write_substs_to_tcx<'tcx>(tcx: &TyCtxt<'tcx>,
 
         assert!(!item_substs.substs.types.needs_infer());
 
-        tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs);
+        ccx.tcx.tables.borrow_mut().item_substs.insert(node_id, item_substs);
     }
 }
 
@@ -192,44 +192,35 @@ fn require_c_abi_if_variadic(tcx: &TyCtxt,
     }
 }
 
-fn require_same_types<'a, 'tcx>(tcx: &TyCtxt<'tcx>,
+fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                 maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
-                                t1_is_expected: bool,
                                 span: Span,
                                 t1: Ty<'tcx>,
                                 t2: Ty<'tcx>,
                                 msg: &str)
                                 -> bool
 {
-    let result = match maybe_infcx {
-        None => {
-            let infcx = InferCtxt::new(tcx, &tcx.tables, None, ProjectionMode::AnyFinal);
-            infer::mk_eqty(&infcx, t1_is_expected, TypeOrigin::Misc(span), t1, t2)
-        }
-        Some(infcx) => {
-            infer::mk_eqty(infcx, t1_is_expected, TypeOrigin::Misc(span), t1, t2)
-        }
+    let err = if let Some(infcx) = maybe_infcx {
+        infer::mk_eqty(infcx, 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()
     };
 
-    match result {
-        Ok(_) => true,
-        Err(ref terr) => {
-            let mut err = struct_span_err!(tcx.sess, span, E0211, "{}", msg);
-            err = err.span_label(span, &terr);
-            let (mut expected_ty, mut found_ty) =
-                if t1_is_expected {(t1, t2)} else {(t2, t1)};
-            if let Some(infcx) = maybe_infcx {
-                expected_ty = infcx.resolve_type_vars_if_possible(&expected_ty);
-                found_ty = infcx.resolve_type_vars_if_possible(&found_ty);
-            }
-            err = err.note_expected_found(&"type",
-                                          &expected_ty,
-                                          &found_ty);
-            tcx.note_and_explain_type_err(&mut err, terr, span);
-            err.emit();
-            false
+    if let Some(ref terr) = err {
+        let mut err = struct_span_err!(ccx.tcx.sess, span, E0211, "{}", msg);
+        err = err.span_label(span, &terr);
+        let (mut expected_ty, mut found_ty) = (t2, t1);
+        if let Some(infcx) = maybe_infcx {
+            expected_ty = infcx.resolve_type_vars_if_possible(&expected_ty);
+            found_ty = infcx.resolve_type_vars_if_possible(&found_ty);
         }
+        err = err.note_expected_found(&"type", &expected_ty, &found_ty);
+        ccx.tcx.note_and_explain_type_err(&mut err, terr, span);
+        err.emit();
     }
+
+    err.is_none()
 }
 
 fn check_main_fn_ty(ccx: &CrateCtxt,
@@ -265,7 +256,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 })
             });
 
-            require_same_types(tcx, None, false, main_span, main_t, se_ty,
+            require_same_types(ccx, None, main_span, main_t, se_ty,
                                "main function has wrong type");
         }
         _ => {
@@ -313,7 +304,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 }),
             });
 
-            require_same_types(tcx, None, false, start_span, start_t, se_ty,
+            require_same_types(ccx, None, start_span, start_t, se_ty,
                                "start function has wrong type");
         }
         _ => {