about summary refs log tree commit diff
diff options
context:
space:
mode:
authorEduard Burtescu <edy.burt@gmail.com>2016-05-02 18:07:47 +0300
committerEduard Burtescu <edy.burt@gmail.com>2016-05-11 04:14:58 +0300
commit31a07b0ce662e95119a76cce8dcfc29d2055f738 (patch)
tree377d11b243e3e4347b7019ca883c0847aed7014d
parent3a3013613a437e0f10cf3d978c9352c94dc284df (diff)
downloadrust-31a07b0ce662e95119a76cce8dcfc29d2055f738.tar.gz
rust-31a07b0ce662e95119a76cce8dcfc29d2055f738.zip
rustc_typeck: Generalize over 'tcx != 'gcx.
-rw-r--r--src/librustc/infer/mod.rs2
-rw-r--r--src/librustc/infer/region_inference/graphviz.rs28
-rw-r--r--src/librustc/infer/region_inference/mod.rs30
-rw-r--r--src/librustc/middle/astconv_util.rs2
-rw-r--r--src/librustc/middle/expr_use_visitor.rs20
-rw-r--r--src/librustc/middle/free_region.rs10
-rw-r--r--src/librustc/middle/mem_categorization.rs30
-rw-r--r--src/librustc/ty/context.rs39
-rw-r--r--src/librustc/ty/mod.rs6
-rw-r--r--src/librustc/ty/structural_impls.rs77
-rw-r--r--src/librustc/ty/util.rs2
-rw-r--r--src/librustc_typeck/astconv.rs1003
-rw-r--r--src/librustc_typeck/check/_match.rs29
-rw-r--r--src/librustc_typeck/check/assoc.rs13
-rw-r--r--src/librustc_typeck/check/callee.rs32
-rw-r--r--src/librustc_typeck/check/cast.rs30
-rw-r--r--src/librustc_typeck/check/closure.rs25
-rw-r--r--src/librustc_typeck/check/coercion.rs16
-rw-r--r--src/librustc_typeck/check/demand.rs14
-rw-r--r--src/librustc_typeck/check/dropck.rs24
-rw-r--r--src/librustc_typeck/check/intrinsic.rs1
-rw-r--r--src/librustc_typeck/check/method/confirm.rs18
-rw-r--r--src/librustc_typeck/check/method/mod.rs6
-rw-r--r--src/librustc_typeck/check/method/probe.rs10
-rw-r--r--src/librustc_typeck/check/method/suggest.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs160
-rw-r--r--src/librustc_typeck/check/op.rs30
-rw-r--r--src/librustc_typeck/check/regionck.rs14
-rw-r--r--src/librustc_typeck/check/upvar.rs18
-rw-r--r--src/librustc_typeck/check/wfcheck.rs6
-rw-r--r--src/librustc_typeck/check/writeback.rs42
-rw-r--r--src/librustc_typeck/collect.rs40
-rw-r--r--src/librustc_typeck/lib.rs51
33 files changed, 942 insertions, 888 deletions
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index fdb4c3500c6..e6d9db20ece 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -89,7 +89,7 @@ pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     float_unification_table: RefCell<UnificationTable<ty::FloatVid>>,
 
     // For region variables.
-    region_vars: RegionVarBindings<'a, 'tcx>,
+    region_vars: RegionVarBindings<'a, 'gcx, 'tcx>,
 
     pub parameter_environment: ty::ParameterEnvironment<'gcx>,
 
diff --git a/src/librustc/infer/region_inference/graphviz.rs b/src/librustc/infer/region_inference/graphviz.rs
index 5c39e39bee0..c9037d6b12a 100644
--- a/src/librustc/infer/region_inference/graphviz.rs
+++ b/src/librustc/infer/region_inference/graphviz.rs
@@ -53,8 +53,10 @@ graphs will be printed.                                                     \n\
 ");
 }
 
-pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a, 'tcx>,
-                                             subject_node: ast::NodeId) {
+pub fn maybe_print_constraints_for<'a, 'gcx, 'tcx>(
+    region_vars: &RegionVarBindings<'a, 'gcx, 'tcx>,
+    subject_node: ast::NodeId)
+{
     let tcx = region_vars.tcx;
 
     if !region_vars.tcx.sess.opts.debugging_opts.print_region_graph {
@@ -118,8 +120,8 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
     }
 }
 
-struct ConstraintGraph<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+struct ConstraintGraph<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     graph_name: String,
     map: &'a FnvHashMap<Constraint, SubregionOrigin<'tcx>>,
     node_ids: FnvHashMap<Node, usize>,
@@ -138,11 +140,11 @@ enum Edge {
     EnclScope(CodeExtent, CodeExtent),
 }
 
-impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> ConstraintGraph<'a, 'gcx, 'tcx> {
+    fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>,
            name: String,
            map: &'a ConstraintMap<'tcx>)
-           -> ConstraintGraph<'a, 'tcx> {
+           -> ConstraintGraph<'a, 'gcx, 'tcx> {
         let mut i = 0;
         let mut node_ids = FnvHashMap();
         {
@@ -173,7 +175,7 @@ impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> dot::Labeller<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
     type Node = Node;
     type Edge = Edge;
     fn graph_id(&self) -> dot::Id {
@@ -226,7 +228,7 @@ fn edge_to_nodes(e: &Edge) -> (Node, Node) {
     }
 }
 
-impl<'a, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'gcx, 'tcx> {
     type Node = Node;
     type Edge = Edge;
     fn nodes(&self) -> dot::Nodes<Node> {
@@ -258,10 +260,10 @@ impl<'a, 'tcx> dot::GraphWalk<'a> for ConstraintGraph<'a, 'tcx> {
 
 pub type ConstraintMap<'tcx> = FnvHashMap<Constraint, SubregionOrigin<'tcx>>;
 
-fn dump_region_constraints_to<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                            map: &ConstraintMap<'tcx>,
-                                            path: &str)
-                                            -> io::Result<()> {
+fn dump_region_constraints_to<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                              map: &ConstraintMap<'tcx>,
+                                              path: &str)
+                                              -> io::Result<()> {
     debug!("dump_region_constraints map (len: {}) path: {}",
            map.len(),
            path);
diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs
index 3e231f8bb3e..b889d0a9daa 100644
--- a/src/librustc/infer/region_inference/mod.rs
+++ b/src/librustc/infer/region_inference/mod.rs
@@ -190,8 +190,8 @@ impl SameRegions {
 
 pub type CombineMap = FnvHashMap<TwoRegions, RegionVid>;
 
-pub struct RegionVarBindings<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx, 'tcx>,
+pub struct RegionVarBindings<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     var_origins: RefCell<Vec<RegionVariableOrigin>>,
 
     // Constraints of the form `A <= B` introduced by the region
@@ -253,8 +253,8 @@ pub struct RegionSnapshot {
     skolemization_count: u32,
 }
 
-impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> RegionVarBindings<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'gcx, 'tcx>) -> RegionVarBindings<'a, 'gcx, 'tcx> {
         RegionVarBindings {
             tcx: tcx,
             var_origins: RefCell::new(Vec::new()),
@@ -600,7 +600,7 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
                            origin: SubregionOrigin<'tcx>,
                            mut relate: F)
                            -> Region
-        where F: FnMut(&RegionVarBindings<'a, 'tcx>, Region, Region)
+        where F: FnMut(&RegionVarBindings<'a, 'gcx, 'tcx>, Region, Region)
     {
         let vars = TwoRegions { a: a, b: b };
         match self.combine_map(t).borrow().get(&vars) {
@@ -816,7 +816,7 @@ struct RegionAndOrigin<'tcx> {
 
 type RegionGraph = graph::Graph<(), Constraint>;
 
-impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
+impl<'a, 'gcx, 'tcx> RegionVarBindings<'a, 'gcx, 'tcx> {
     fn infer_variable_values(&self,
                              free_regions: &FreeRegionMap,
                              errors: &mut Vec<RegionResolutionError<'tcx>>,
@@ -1249,11 +1249,11 @@ impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
         let WalkState {result, dup_found, ..} = state;
         return (result, dup_found);
 
-        fn process_edges<'a, 'tcx>(this: &RegionVarBindings<'a, 'tcx>,
-                                   state: &mut WalkState<'tcx>,
-                                   graph: &RegionGraph,
-                                   source_vid: RegionVid,
-                                   dir: Direction) {
+        fn process_edges<'a, 'gcx, 'tcx>(this: &RegionVarBindings<'a, 'gcx, 'tcx>,
+                                         state: &mut WalkState<'tcx>,
+                                         graph: &RegionGraph,
+                                         source_vid: RegionVid,
+                                         dir: Direction) {
             debug!("process_edges(source_vid={:?}, dir={:?})", source_vid, dir);
 
             let source_node_index = NodeIndex(source_vid.index as usize);
@@ -1362,8 +1362,8 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
     }
 }
 
-impl<'a, 'tcx> GenericKind<'tcx> {
-    pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
+impl<'a, 'gcx, 'tcx> GenericKind<'tcx> {
+    pub fn to_ty(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Ty<'tcx> {
         match *self {
             GenericKind::Param(ref p) => p.to_ty(tcx),
             GenericKind::Projection(ref p) => tcx.mk_projection(p.trait_ref.clone(), p.item_name),
@@ -1371,7 +1371,7 @@ impl<'a, 'tcx> GenericKind<'tcx> {
     }
 }
 
-impl<'a, 'tcx> VerifyBound {
+impl<'a, 'gcx, 'tcx> VerifyBound {
     fn for_each_region(&self, f: &mut FnMut(ty::Region)) {
         match self {
             &VerifyBound::AnyRegion(ref rs) |
@@ -1424,7 +1424,7 @@ impl<'a, 'tcx> VerifyBound {
         }
     }
 
-    fn is_met(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+    fn is_met(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>,
               free_regions: &FreeRegionMap,
               var_values: &Vec<VarValue>,
               min: ty::Region)
diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs
index 99521f9ef0f..4129c53c988 100644
--- a/src/librustc/middle/astconv_util.rs
+++ b/src/librustc/middle/astconv_util.rs
@@ -20,7 +20,7 @@ use ty::{Ty, TyCtxt};
 use syntax::codemap::Span;
 use hir as ast;
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
 pub fn prohibit_type_params(self, segments: &[ast::PathSegment]) {
     for segment in segments {
         for typ in segment.parameters.types() {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index 6bb3c380234..4cee8c5d89a 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -209,8 +209,7 @@ enum OverloadedCallType {
 }
 
 impl OverloadedCallType {
-    fn from_trait_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_id: DefId)
-                               -> OverloadedCallType {
+    fn from_trait_id(tcx: TyCtxt, trait_id: DefId) -> OverloadedCallType {
         for &(maybe_function_trait, overloaded_call_type) in &[
             (tcx.lang_items.fn_once_trait(), FnOnceOverloadedCall),
             (tcx.lang_items.fn_mut_trait(), FnMutOverloadedCall),
@@ -227,8 +226,7 @@ impl OverloadedCallType {
         bug!("overloaded call didn't map to known function trait")
     }
 
-    fn from_method_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, method_id: DefId)
-                                -> OverloadedCallType {
+    fn from_method_id(tcx: TyCtxt, method_id: DefId) -> OverloadedCallType {
         let method = tcx.impl_or_trait_item(method_id);
         OverloadedCallType::from_trait_id(tcx, method.container().id())
     }
@@ -271,9 +269,9 @@ enum PassArgs {
     ByRef,
 }
 
-impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> ExprUseVisitor<'a, 'gcx, 'tcx> {
     pub fn new(delegate: &'a mut (Delegate<'tcx>+'a),
-               infcx: &'a InferCtxt<'a, 'tcx, 'tcx>) -> Self
+               infcx: &'a InferCtxt<'a, 'gcx, 'tcx>) -> Self
     {
         ExprUseVisitor {
             mc: mc::MemCategorizationContext::new(infcx),
@@ -305,7 +303,7 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
         }
     }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
         self.mc.infcx.tcx
     }
 
@@ -1184,10 +1182,10 @@ impl<'a, 'tcx> ExprUseVisitor<'a, 'tcx, 'tcx> {
     }
 }
 
-fn copy_or_move<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
-                          cmt: &mc::cmt<'tcx>,
-                          move_reason: MoveReason)
-                          -> ConsumeMode
+fn copy_or_move<'a, 'gcx, 'tcx>(infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+                                cmt: &mc::cmt<'tcx>,
+                                move_reason: MoveReason)
+                                -> ConsumeMode
 {
     if infcx.type_moves_by_default(cmt.ty, cmt.span) {
         Move(move_reason)
diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs
index 90d4627c93d..e4ce8976713 100644
--- a/src/librustc/middle/free_region.rs
+++ b/src/librustc/middle/free_region.rs
@@ -120,11 +120,11 @@ impl FreeRegionMap {
 
     /// Determines whether one region is a subregion of another.  This is intended to run *after
     /// inference* and sadly the logic is somewhat duplicated with the code in infer.rs.
-    pub fn is_subregion_of<'a, 'tcx>(&self,
-                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                     sub_region: ty::Region,
-                                     super_region: ty::Region)
-                                     -> bool {
+    pub fn is_subregion_of(&self,
+                           tcx: TyCtxt,
+                           sub_region: ty::Region,
+                           super_region: ty::Region)
+                           -> bool {
         let result = sub_region == super_region || {
             match (sub_region, super_region) {
                 (ty::ReEmpty, _) |
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 53e6102587b..3999b02425d 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -302,9 +302,7 @@ impl MutabilityCategory {
         ret
     }
 
-    fn from_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                            id: ast::NodeId)
-                            -> MutabilityCategory {
+    fn from_local(tcx: TyCtxt, id: ast::NodeId) -> MutabilityCategory {
         let ret = match tcx.map.get(id) {
             ast_map::NodeLocal(p) => match p.node {
                 PatKind::Ident(bind_mode, _, _) => {
@@ -360,13 +358,13 @@ impl MutabilityCategory {
     }
 }
 
-impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>)
-               -> MemCategorizationContext<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> MemCategorizationContext<'a, 'gcx, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'gcx, 'tcx>)
+               -> MemCategorizationContext<'a, 'gcx, 'tcx> {
         MemCategorizationContext { infcx: infcx }
     }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'gcx, 'tcx> {
         self.infcx.tcx
     }
 
@@ -1074,9 +1072,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
                              slice_pat: &hir::Pat)
                              -> McResult<(cmt<'tcx>, hir::Mutability, ty::Region)> {
         let slice_ty = self.node_ty(slice_pat.id)?;
-        let (slice_mutbl, slice_r) = vec_slice_info(self.tcx(),
-                                                    slice_pat,
-                                                    slice_ty);
+        let (slice_mutbl, slice_r) = vec_slice_info(slice_pat, slice_ty);
         let context = InteriorOffsetKind::Pattern;
         let cmt_vec = self.deref_vec(slice_pat, vec_cmt, context)?;
         let cmt_slice = self.cat_index(slice_pat, cmt_vec, context)?;
@@ -1085,14 +1081,12 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
         /// In a pattern like [a, b, ..c], normally `c` has slice type, but if you have [a, b,
         /// ..ref c], then the type of `ref c` will be `&&[]`, so to extract the slice details we
         /// have to recurse through rptrs.
-        fn vec_slice_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                    pat: &hir::Pat,
-                                    slice_ty: Ty)
-                                    -> (hir::Mutability, ty::Region) {
+        fn vec_slice_info(pat: &hir::Pat, slice_ty: Ty)
+                          -> (hir::Mutability, ty::Region) {
             match slice_ty.sty {
                 ty::TyRef(r, ref mt) => match mt.ty.sty {
                     ty::TySlice(_) => (mt.mutbl, *r),
-                    _ => vec_slice_info(tcx, pat, mt.ty),
+                    _ => vec_slice_info(pat, mt.ty),
                 },
 
                 _ => {
@@ -1140,7 +1134,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
     }
 
     pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()>
-        where F: FnMut(&MemCategorizationContext<'a, 'tcx, 'tcx>, cmt<'tcx>, &hir::Pat),
+        where F: FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat),
     {
         self.cat_pattern_(cmt, pat, &mut op)
     }
@@ -1148,7 +1142,7 @@ impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
     // FIXME(#19596) This is a workaround, but there should be a better way to do this
     fn cat_pattern_<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, op: &mut F)
                        -> McResult<()>
-        where F : FnMut(&MemCategorizationContext<'a, 'tcx, 'tcx>, cmt<'tcx>, &hir::Pat),
+        where F : FnMut(&MemCategorizationContext<'a, 'gcx, 'tcx>, cmt<'tcx>, &hir::Pat),
     {
         // Here, `cmt` is the categorization for the value being
         // matched and pat is the pattern it is being matched against.
@@ -1466,7 +1460,7 @@ impl<'tcx> cmt_<'tcx> {
     }
 
 
-    pub fn descriptive_string<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
+    pub fn descriptive_string(&self, tcx: TyCtxt) -> String {
         match self.cat {
             Categorization::StaticItem => {
                 "static item".to_string()
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 69e979f6273..f5610de062f 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -92,7 +92,7 @@ struct CtxtInterners<'tcx> {
     type_list: RefCell<FnvHashSet<InternedTyList<'tcx>>>,
     substs: RefCell<FnvHashSet<InternedSubsts<'tcx>>>,
     bare_fn: RefCell<FnvHashSet<&'tcx BareFnTy<'tcx>>>,
-    region: RefCell<FnvHashSet<&'tcx Region>>,
+    region: RefCell<FnvHashSet<InternedRegion<'tcx>>>,
     stability: RefCell<FnvHashSet<&'tcx attr::Stability>>,
     layout: RefCell<FnvHashSet<&'tcx Layout>>,
 }
@@ -740,6 +740,23 @@ impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for &'a Region {
+    type Lifted = &'tcx Region;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx Region> {
+        if let Some(&InternedRegion { region }) = tcx.interners.region.borrow().get(*self) {
+            if *self as *const _ == region as *const _ {
+                return Some(region);
+            }
+        }
+        // Also try in the global tcx if we're not that.
+        if !tcx.is_global() {
+            self.lift_to_tcx(tcx.global_tcx())
+        } else {
+            None
+        }
+    }
+}
+
 impl<'a, 'tcx> Lift<'tcx> for &'a [Ty<'a>] {
     type Lifted = &'tcx [Ty<'tcx>];
     fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<&'tcx [Ty<'tcx>]> {
@@ -953,6 +970,18 @@ impl<'tcx: 'lcx, 'lcx> Borrow<Substs<'lcx>> for InternedSubsts<'tcx> {
     }
 }
 
+/// An entry in the region interner.
+#[derive(PartialEq, Eq, Hash)]
+struct InternedRegion<'tcx> {
+    region: &'tcx Region
+}
+
+impl<'tcx> Borrow<Region> for InternedRegion<'tcx> {
+    fn borrow<'a>(&'a self) -> &'a Region {
+        self.region
+    }
+}
+
 fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
     bounds.is_empty() ||
         bounds[1..].iter().enumerate().all(
@@ -1006,12 +1035,14 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     }
 
     pub fn mk_region(self, region: Region) -> &'tcx Region {
-        if let Some(region) = self.interners.region.borrow().get(&region) {
-            return *region;
+        if let Some(interned) = self.interners.region.borrow().get(&region) {
+            return interned.region;
         }
 
         let region = self.interners.arenas.region.alloc(region);
-        self.interners.region.borrow_mut().insert(region);
+        self.interners.region.borrow_mut().insert(InternedRegion {
+            region: region
+        });
         region
     }
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 27f74de2470..7bede488964 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -1590,7 +1590,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
         }
     }
 
-    fn calculate_dtorck(&'gcx self, tcx: TyCtxt<'a, 'gcx, 'tcx>) {
+    fn calculate_dtorck(&'gcx self, tcx: TyCtxt) {
         if tcx.is_adt_dtorck(self) {
             self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK);
         }
@@ -1611,7 +1611,7 @@ impl<'a, 'gcx, 'tcx, 'container> AdtDefData<'gcx, 'container> {
     /// true, this type being safe for destruction requires it to be
     /// alive; Otherwise, only the contents are required to be.
     #[inline]
-    pub fn is_dtorck(&'gcx self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> bool {
+    pub fn is_dtorck(&'gcx self, tcx: TyCtxt) -> bool {
         if !self.flags.get().intersects(AdtFlags::IS_DTORCK_VALID) {
             self.calculate_dtorck(tcx)
         }
@@ -2932,7 +2932,7 @@ pub enum ExplicitSelfCategory {
     ByBox,
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     pub fn with_freevars<T, F>(self, fid: NodeId, f: F) -> T where
         F: FnOnce(&[hir::Freevar]) -> T,
     {
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index 088ca15acb9..284019ed6a2 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -32,7 +32,10 @@ impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) {
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Option<T> {
     type Lifted = Option<T::Lifted>;
     fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
-        self.as_ref().map(|x| tcx.lift(x))
+        match *self {
+            Some(ref x) => tcx.lift(x).map(Some),
+            None => Some(None)
+        }
     }
 }
 
@@ -63,6 +66,13 @@ impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] {
     }
 }
 
+impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for Vec<T> {
+    type Lifted = Vec<T::Lifted>;
+    fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self[..])
+    }
+}
+
 impl<'tcx> Lift<'tcx> for ty::Region {
     type Lifted = Self;
     fn lift_to_tcx(&self, _: TyCtxt) -> Option<ty::Region> {
@@ -140,6 +150,71 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ClosureSubsts<'a> {
     }
 }
 
+impl<'a, 'tcx> Lift<'tcx> for ty::ItemSubsts<'a> {
+    type Lifted = ty::ItemSubsts<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.substs).map(|substs| {
+            ty::ItemSubsts {
+                substs: substs
+            }
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ty::adjustment::AutoRef<'a> {
+    type Lifted = ty::adjustment::AutoRef<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        match *self {
+            ty::adjustment::AutoPtr(r, m) => {
+                tcx.lift(&r).map(|r| ty::adjustment::AutoPtr(r, m))
+            }
+            ty::adjustment::AutoUnsafe(m) => {
+                Some(ty::adjustment::AutoUnsafe(m))
+            }
+        }
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ty::FnOutput<'a> {
+    type Lifted = ty::FnOutput<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        match *self {
+            ty::FnConverging(ty) => {
+                tcx.lift(&ty).map(ty::FnConverging)
+            }
+            ty::FnDiverging => Some(ty::FnDiverging)
+        }
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ty::FnSig<'a> {
+    type Lifted = ty::FnSig<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.inputs[..]).and_then(|inputs| {
+            tcx.lift(&self.output).map(|output| {
+                ty::FnSig {
+                    inputs: inputs,
+                    output: output,
+                    variadic: self.variadic
+                }
+            })
+        })
+    }
+}
+
+impl<'a, 'tcx> Lift<'tcx> for ty::ClosureTy<'a> {
+    type Lifted = ty::ClosureTy<'tcx>;
+    fn lift_to_tcx<'b, 'gcx>(&self, tcx: TyCtxt<'b, 'gcx, 'tcx>) -> Option<Self::Lifted> {
+        tcx.lift(&self.sig).map(|sig| {
+            ty::ClosureTy {
+                sig: sig,
+                unsafety: self.unsafety,
+                abi: self.abi
+            }
+        })
+    }
+}
+
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::error::ExpectedFound<T> {
     type Lifted = ty::error::ExpectedFound<T::Lifted>;
     fn lift_to_tcx<'a, 'gcx>(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Option<Self::Lifted> {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 88ebb332354..4b96527cbe1 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -489,7 +489,7 @@ impl<'a, 'gcx, 'tcx> TyCtxt<'a, 'gcx, 'tcx> {
     /// `adt` that do not strictly outlive the adt value itself.
     /// (This allows programs to make cyclic structures without
     /// resorting to unasfe means; see RFCs 769 and 1238).
-    pub fn is_adt_dtorck(self, adt: ty::AdtDef<'tcx>) -> bool {
+    pub fn is_adt_dtorck(self, adt: ty::AdtDef) -> bool {
         let dtor_method = match adt.destructor() {
             Some(dtor) => dtor,
             None => return false
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 9825829e3bd..b6f1e86780b 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -149,6 +149,27 @@ pub trait AstConv<'gcx, 'tcx> {
     fn set_tainted_by_errors(&self);
 }
 
+#[derive(PartialEq, Eq)]
+pub enum PathParamMode {
+    // Any path in a type context.
+    Explicit,
+    // The `module::Type` in `module::Type::method` in an expression.
+    Optional
+}
+
+struct ConvertedBinding<'tcx> {
+    item_name: ast::Name,
+    ty: Ty<'tcx>,
+    span: Span,
+}
+
+struct SelfInfo<'a, 'tcx> {
+    untransformed_self_ty: Ty<'tcx>,
+    explicit_self: &'a hir::ExplicitSelf,
+}
+
+type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
+
 pub fn ast_region_to_region(tcx: TyCtxt, lifetime: &hir::Lifetime)
                             -> ty::Region {
     let r = match tcx.named_region_map.get(&lifetime.id) {
@@ -254,21 +275,21 @@ fn report_elision_failure(
     }
 }
 
-pub fn opt_ast_region_to_region<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+impl<'o, 'gcx: 'tcx, 'tcx> AstConv<'gcx, 'tcx>+'o {
+pub fn opt_ast_region_to_region(&self,
     rscope: &RegionScope,
     default_span: Span,
     opt_lifetime: &Option<hir::Lifetime>) -> ty::Region
 {
     let r = match *opt_lifetime {
         Some(ref lifetime) => {
-            ast_region_to_region(this.tcx(), lifetime)
+            ast_region_to_region(self.tcx(), lifetime)
         }
 
         None => match rscope.anon_regions(default_span, 1) {
             Ok(rs) => rs[0],
             Err(params) => {
-                let mut err = struct_span_err!(this.tcx().sess, default_span, E0106,
+                let mut err = struct_span_err!(self.tcx().sess, default_span, E0106,
                                                "missing lifetime specifier");
                 if let Some(params) = params {
                     report_elision_failure(&mut err, params);
@@ -288,8 +309,7 @@ pub fn opt_ast_region_to_region<'tcx>(
 
 /// Given a path `path` that refers to an item `I` with the declared generics `decl_generics`,
 /// returns an appropriate set of substitutions for this particular reference to `I`.
-pub fn ast_path_substs_for_ty<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+pub fn ast_path_substs_for_ty(&self,
     rscope: &RegionScope,
     span: Span,
     param_mode: PathParamMode,
@@ -297,7 +317,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
     item_segment: &hir::PathSegment)
     -> Substs<'tcx>
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
     // ast_path_substs() is only called to convert paths that are
     // known to refer to traits, types, or structs. In these cases,
@@ -312,7 +332,7 @@ pub fn ast_path_substs_for_ty<'tcx>(
 
     let (regions, types, assoc_bindings) = match item_segment.parameters {
         hir::AngleBracketedParameters(ref data) => {
-            convert_angle_bracketed_parameters(this, rscope, span, decl_generics, data)
+            self.convert_angle_bracketed_parameters(rscope, span, decl_generics, data)
         }
         hir::ParenthesizedParameters(..) => {
             span_err!(tcx.sess, span, E0214,
@@ -324,34 +344,24 @@ pub fn ast_path_substs_for_ty<'tcx>(
         }
     };
 
-    assoc_bindings.first().map(|b| this.tcx().prohibit_projection(b.span));
-
-    create_substs_for_ast_path(this,
-                               span,
-                               param_mode,
-                               decl_generics,
-                               None,
-                               types,
-                               regions)
-}
+    assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span));
 
-#[derive(PartialEq, Eq)]
-pub enum PathParamMode {
-    // Any path in a type context.
-    Explicit,
-    // The `module::Type` in `module::Type::method` in an expression.
-    Optional
+    self.create_substs_for_ast_path(span,
+                                    param_mode,
+                                    decl_generics,
+                                    None,
+                                    types,
+                                    regions)
 }
 
-fn create_region_substs<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn create_region_substs(&self,
     rscope: &RegionScope,
     span: Span,
     decl_generics: &ty::Generics<'tcx>,
     regions_provided: Vec<ty::Region>)
     -> Substs<'tcx>
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
     // If the type is parameterized by this region, then replace this
     // region with the current anon region binding (in other words,
@@ -387,8 +397,7 @@ fn create_region_substs<'tcx>(
 /// The `region_substs` should be the result of `create_region_substs`
 /// -- that is, a substitution with no types but the correct number of
 /// regions.
-fn create_substs_for_ast_path<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn create_substs_for_ast_path(&self,
     span: Span,
     param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
@@ -397,7 +406,7 @@ fn create_substs_for_ast_path<'tcx>(
     region_substs: Substs<'tcx>)
     -> Substs<'tcx>
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
     debug!("create_substs_for_ast_path(decl_generics={:?}, self_ty={:?}, \
            types_provided={:?}, region_substs={:?})",
@@ -414,16 +423,15 @@ fn create_substs_for_ast_path<'tcx>(
                                                .take_while(|x| x.default.is_none())
                                                .count();
 
-    let mut type_substs = get_type_substs_for_defs(this,
-                                                   span,
-                                                   types_provided,
-                                                   param_mode,
-                                                   ty_param_defs,
-                                                   region_substs.clone(),
-                                                   self_ty);
+    let mut type_substs = self.get_type_substs_for_defs(span,
+                                                        types_provided,
+                                                        param_mode,
+                                                        ty_param_defs,
+                                                        region_substs.clone(),
+                                                        self_ty);
 
     let supplied_ty_param_count = type_substs.len();
-    check_type_argument_count(this.tcx(), span, supplied_ty_param_count,
+    check_type_argument_count(self.tcx(), span, supplied_ty_param_count,
                               required_ty_param_count, formal_ty_param_count);
 
     if supplied_ty_param_count < required_ty_param_count {
@@ -489,14 +497,14 @@ fn create_substs_for_ast_path<'tcx>(
 
 /// Returns types_provided if it is not empty, otherwise populating the
 /// type parameters with inference variables as appropriate.
-fn get_type_substs_for_defs<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                  span: Span,
-                                  types_provided: Vec<Ty<'tcx>>,
-                                  param_mode: PathParamMode,
-                                  ty_param_defs: &[ty::TypeParameterDef<'tcx>],
-                                  mut substs: Substs<'tcx>,
-                                  self_ty: Option<Ty<'tcx>>)
-                                  -> Vec<Ty<'tcx>>
+fn get_type_substs_for_defs(&self,
+                            span: Span,
+                            types_provided: Vec<Ty<'tcx>>,
+                            param_mode: PathParamMode,
+                            ty_param_defs: &[ty::TypeParameterDef<'tcx>],
+                            mut substs: Substs<'tcx>,
+                            self_ty: Option<Ty<'tcx>>)
+                            -> Vec<Ty<'tcx>>
 {
     fn default_type_parameter<'tcx>(p: &ty::TypeParameterDef<'tcx>, self_ty: Option<Ty<'tcx>>)
                                     -> Option<ty::TypeParameterDef<'tcx>>
@@ -515,7 +523,7 @@ fn get_type_substs_for_defs<'tcx>(this: &AstConv<'tcx, 'tcx>,
     if param_mode == PathParamMode::Optional && types_provided.is_empty() {
         ty_param_defs
             .iter()
-            .map(|p| this.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs),
+            .map(|p| self.ty_infer(default_type_parameter(p, self_ty), Some(&mut substs),
                                    Some(TypeSpace), span))
             .collect()
     } else {
@@ -523,40 +531,34 @@ fn get_type_substs_for_defs<'tcx>(this: &AstConv<'tcx, 'tcx>,
     }
 }
 
-struct ConvertedBinding<'tcx> {
-    item_name: ast::Name,
-    ty: Ty<'tcx>,
-    span: Span,
-}
-
-fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                            rscope: &RegionScope,
-                                            span: Span,
-                                            decl_generics: &ty::Generics<'tcx>,
-                                            data: &hir::AngleBracketedParameterData)
-                                            -> (Substs<'tcx>,
-                                                Vec<Ty<'tcx>>,
-                                                Vec<ConvertedBinding<'tcx>>)
+fn convert_angle_bracketed_parameters(&self,
+                                      rscope: &RegionScope,
+                                      span: Span,
+                                      decl_generics: &ty::Generics<'tcx>,
+                                      data: &hir::AngleBracketedParameterData)
+                                      -> (Substs<'tcx>,
+                                          Vec<Ty<'tcx>>,
+                                          Vec<ConvertedBinding<'tcx>>)
 {
     let regions: Vec<_> =
         data.lifetimes.iter()
-                      .map(|l| ast_region_to_region(this.tcx(), l))
+                      .map(|l| ast_region_to_region(self.tcx(), l))
                       .collect();
 
     let region_substs =
-        create_region_substs(this, rscope, span, decl_generics, regions);
+        self.create_region_substs(rscope, span, decl_generics, regions);
 
     let types: Vec<_> =
         data.types.iter()
                   .enumerate()
-                  .map(|(i,t)| ast_ty_arg_to_ty(this, rscope, decl_generics,
-                                                i, &region_substs, t))
+                  .map(|(i,t)| self.ast_ty_arg_to_ty(rscope, decl_generics,
+                                                     i, &region_substs, t))
                   .collect();
 
     let assoc_bindings: Vec<_> =
         data.bindings.iter()
                      .map(|b| ConvertedBinding { item_name: b.name,
-                                                 ty: ast_ty_to_ty(this, rscope, &b.ty),
+                                                 ty: self.ast_ty_to_ty(rscope, &b.ty),
                                                  span: b.span })
                      .collect();
 
@@ -566,11 +568,11 @@ fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx, '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>(this: &AstConv<'tcx, 'tcx>,
-                                    input_tys: &[Ty<'tcx>],
-                                    input_pats: Vec<String>) -> ElidedLifetime
+fn find_implied_output_region(&self,
+                              input_tys: &[Ty<'tcx>],
+                              input_pats: Vec<String>) -> ElidedLifetime
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
     let mut lifetimes_for_params = Vec::new();
     let mut possible_implied_output_region = None;
 
@@ -602,59 +604,57 @@ fn find_implied_output_region<'tcx>(this: &AstConv<'tcx, 'tcx>,
     }
 }
 
-fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                          elided_lifetime: ElidedLifetime,
-                                          ty: &hir::Ty)
-                                          -> Ty<'tcx>
+fn convert_ty_with_lifetime_elision(&self,
+                                    elided_lifetime: ElidedLifetime,
+                                    ty: &hir::Ty)
+                                    -> Ty<'tcx>
 {
     match elided_lifetime {
         Ok(implied_output_region) => {
             let rb = ElidableRscope::new(implied_output_region);
-            ast_ty_to_ty(this, &rb, ty)
+            self.ast_ty_to_ty(&rb, ty)
         }
         Err(param_lifetimes) => {
             // All regions must be explicitly specified in the output
             // if the lifetime elision rules do not apply. This saves
             // the user from potentially-confusing errors.
             let rb = UnelidableRscope::new(param_lifetimes);
-            ast_ty_to_ty(this, &rb, ty)
+            self.ast_ty_to_ty(&rb, ty)
         }
     }
 }
 
-fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                          rscope: &RegionScope,
-                                          span: Span,
-                                          decl_generics: &ty::Generics<'tcx>,
-                                          data: &hir::ParenthesizedParameterData)
-                                          -> (Substs<'tcx>,
-                                              Vec<Ty<'tcx>>,
-                                              Vec<ConvertedBinding<'tcx>>)
+fn convert_parenthesized_parameters(&self,
+                                    rscope: &RegionScope,
+                                    span: Span,
+                                    decl_generics: &ty::Generics<'tcx>,
+                                    data: &hir::ParenthesizedParameterData)
+                                    -> (Substs<'tcx>,
+                                        Vec<Ty<'tcx>>,
+                                        Vec<ConvertedBinding<'tcx>>)
 {
     let region_substs =
-        create_region_substs(this, rscope, span, decl_generics, Vec::new());
+        self.create_region_substs(rscope, span, decl_generics, Vec::new());
 
     let binding_rscope = BindingRscope::new();
     let inputs =
         data.inputs.iter()
-                   .map(|a_t| ast_ty_arg_to_ty(this, &binding_rscope, decl_generics,
-                                               0, &region_substs, a_t))
+                   .map(|a_t| self.ast_ty_arg_to_ty(&binding_rscope, decl_generics,
+                                                    0, &region_substs, a_t))
                    .collect::<Vec<Ty<'tcx>>>();
 
     let input_params = vec![String::new(); inputs.len()];
-    let implied_output_region = find_implied_output_region(this, &inputs, input_params);
+    let implied_output_region = self.find_implied_output_region(&inputs, input_params);
 
-    let input_ty = this.tcx().mk_tup(inputs);
+    let input_ty = self.tcx().mk_tup(inputs);
 
     let (output, output_span) = match data.output {
         Some(ref output_ty) => {
-            (convert_ty_with_lifetime_elision(this,
-                                              implied_output_region,
-                                              &output_ty),
+            (self.convert_ty_with_lifetime_elision(implied_output_region, &output_ty),
              output_ty.span)
         }
         None => {
-            (this.tcx().mk_nil(), data.span)
+            (self.tcx().mk_nil(), data.span)
         }
     };
 
@@ -667,8 +667,7 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx, 'tcx>,
     (region_substs, vec![input_ty], vec![output_binding])
 }
 
-pub fn instantiate_poly_trait_ref<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+pub fn instantiate_poly_trait_ref(&self,
     rscope: &RegionScope,
     ast_trait_ref: &hir::PolyTraitRef,
     self_ty: Option<Ty<'tcx>>,
@@ -676,15 +675,14 @@ pub fn instantiate_poly_trait_ref<'tcx>(
     -> ty::PolyTraitRef<'tcx>
 {
     let trait_ref = &ast_trait_ref.trait_ref;
-    let trait_def_id = trait_def_id(this, trait_ref);
-    ast_path_to_poly_trait_ref(this,
-                               rscope,
-                               trait_ref.path.span,
-                               PathParamMode::Explicit,
-                               trait_def_id,
-                               self_ty,
-                               trait_ref.path.segments.last().unwrap(),
-                               poly_projections)
+    let trait_def_id = self.trait_def_id(trait_ref);
+    self.ast_path_to_poly_trait_ref(rscope,
+                                    trait_ref.path.span,
+                                    PathParamMode::Explicit,
+                                    trait_def_id,
+                                    self_ty,
+                                    trait_ref.path.segments.last().unwrap(),
+                                    poly_projections)
 }
 
 /// Instantiates the path for the given trait reference, assuming that it's
@@ -693,39 +691,36 @@ pub fn instantiate_poly_trait_ref<'tcx>(
 ///
 /// If the `projections` argument is `None`, then assoc type bindings like `Foo<T=X>`
 /// are disallowed. Otherwise, they are pushed onto the vector given.
-pub fn instantiate_mono_trait_ref<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+pub fn instantiate_mono_trait_ref(&self,
     rscope: &RegionScope,
     trait_ref: &hir::TraitRef,
     self_ty: Option<Ty<'tcx>>)
     -> ty::TraitRef<'tcx>
 {
-    let trait_def_id = trait_def_id(this, trait_ref);
-    ast_path_to_mono_trait_ref(this,
-                               rscope,
-                               trait_ref.path.span,
-                               PathParamMode::Explicit,
-                               trait_def_id,
-                               self_ty,
-                               trait_ref.path.segments.last().unwrap())
+    let trait_def_id = self.trait_def_id(trait_ref);
+    self.ast_path_to_mono_trait_ref(rscope,
+                                    trait_ref.path.span,
+                                    PathParamMode::Explicit,
+                                    trait_def_id,
+                                    self_ty,
+                                    trait_ref.path.segments.last().unwrap())
 }
 
-fn trait_def_id<'tcx>(this: &AstConv<'tcx, 'tcx>, trait_ref: &hir::TraitRef) -> DefId {
+fn trait_def_id(&self, trait_ref: &hir::TraitRef) -> DefId {
     let path = &trait_ref.path;
-    match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
+    match ::lookup_full_def(self.tcx(), path.span, trait_ref.ref_id) {
         Def::Trait(trait_def_id) => trait_def_id,
         Def::Err => {
-            this.tcx().sess.fatal("cannot continue compilation due to previous error");
+            self.tcx().sess.fatal("cannot continue compilation due to previous error");
         }
         _ => {
-            span_fatal!(this.tcx().sess, path.span, E0245, "`{}` is not a trait",
+            span_fatal!(self.tcx().sess, path.span, E0245, "`{}` is not a trait",
                         path);
         }
     }
 }
 
-fn object_path_to_poly_trait_ref<'a,'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn object_path_to_poly_trait_ref(&self,
     rscope: &RegionScope,
     span: Span,
     param_mode: PathParamMode,
@@ -734,18 +729,16 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
     mut projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
     -> ty::PolyTraitRef<'tcx>
 {
-    ast_path_to_poly_trait_ref(this,
-                               rscope,
-                               span,
-                               param_mode,
-                               trait_def_id,
-                               None,
-                               trait_segment,
-                               projections)
+    self.ast_path_to_poly_trait_ref(rscope,
+                                    span,
+                                    param_mode,
+                                    trait_def_id,
+                                    None,
+                                    trait_segment,
+                                    projections)
 }
 
-fn ast_path_to_poly_trait_ref<'a,'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn ast_path_to_poly_trait_ref(&self,
     rscope: &RegionScope,
     span: Span,
     param_mode: PathParamMode,
@@ -764,13 +757,12 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
     let shifted_rscope = &ShiftedRscope::new(rscope);
 
     let (substs, assoc_bindings) =
-        create_substs_for_ast_trait_ref(this,
-                                        shifted_rscope,
-                                        span,
-                                        param_mode,
-                                        trait_def_id,
-                                        self_ty,
-                                        trait_segment);
+        self.create_substs_for_ast_trait_ref(shifted_rscope,
+                                             span,
+                                             param_mode,
+                                             trait_def_id,
+                                             self_ty,
+                                             trait_segment);
     let poly_trait_ref = ty::Binder(ty::TraitRef::new(trait_def_id, substs));
 
     {
@@ -780,10 +772,9 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
             .filter_map(|binding| {
                 // specify type to assert that error was already reported in Err case:
                 let predicate: Result<_, ErrorReported> =
-                    ast_type_binding_to_poly_projection_predicate(this,
-                                                                  poly_trait_ref.clone(),
-                                                                  self_ty,
-                                                                  binding);
+                    self.ast_type_binding_to_poly_projection_predicate(poly_trait_ref.clone(),
+                                                                       self_ty,
+                                                                       binding);
                 predicate.ok() // ok to ignore Err() because ErrorReported (see above)
             });
         poly_projections.extend(converted_bindings);
@@ -794,44 +785,43 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
     poly_trait_ref
 }
 
-fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                       rscope: &RegionScope,
-                                       span: Span,
-                                       param_mode: PathParamMode,
-                                       trait_def_id: DefId,
-                                       self_ty: Option<Ty<'tcx>>,
-                                       trait_segment: &hir::PathSegment)
-                                       -> ty::TraitRef<'tcx>
+fn ast_path_to_mono_trait_ref(&self,
+                              rscope: &RegionScope,
+                              span: Span,
+                              param_mode: PathParamMode,
+                              trait_def_id: DefId,
+                              self_ty: Option<Ty<'tcx>>,
+                              trait_segment: &hir::PathSegment)
+                              -> ty::TraitRef<'tcx>
 {
     let (substs, assoc_bindings) =
-        create_substs_for_ast_trait_ref(this,
-                                        rscope,
-                                        span,
-                                        param_mode,
-                                        trait_def_id,
-                                        self_ty,
-                                        trait_segment);
-    assoc_bindings.first().map(|b| this.tcx().prohibit_projection(b.span));
+        self.create_substs_for_ast_trait_ref(rscope,
+                                             span,
+                                             param_mode,
+                                             trait_def_id,
+                                             self_ty,
+                                             trait_segment);
+    assoc_bindings.first().map(|b| self.tcx().prohibit_projection(b.span));
     ty::TraitRef::new(trait_def_id, substs)
 }
 
-fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                            rscope: &RegionScope,
-                                            span: Span,
-                                            param_mode: PathParamMode,
-                                            trait_def_id: DefId,
-                                            self_ty: Option<Ty<'tcx>>,
-                                            trait_segment: &hir::PathSegment)
-                                            -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
+fn create_substs_for_ast_trait_ref(&self,
+                                   rscope: &RegionScope,
+                                   span: Span,
+                                   param_mode: PathParamMode,
+                                   trait_def_id: DefId,
+                                   self_ty: Option<Ty<'tcx>>,
+                                   trait_segment: &hir::PathSegment)
+                                   -> (&'tcx Substs<'tcx>, Vec<ConvertedBinding<'tcx>>)
 {
     debug!("create_substs_for_ast_trait_ref(trait_segment={:?})",
            trait_segment);
 
-    let trait_def = match this.get_trait_def(span, trait_def_id) {
+    let trait_def = match self.get_trait_def(span, trait_def_id) {
         Ok(trait_def) => trait_def,
         Err(ErrorReported) => {
             // No convenient way to recover from a cycle here. Just bail. Sorry!
-            this.tcx().sess.abort_if_errors();
+            self.tcx().sess.abort_if_errors();
             bug!("ErrorReported returned, but no errors reports?")
         }
     };
@@ -840,49 +830,47 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx, 'tcx>,
         hir::AngleBracketedParameters(ref data) => {
             // For now, require that parenthetical notation be used
             // only with `Fn()` etc.
-            if !this.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
-                emit_feature_err(&this.tcx().sess.parse_sess.span_diagnostic,
+            if !self.tcx().sess.features.borrow().unboxed_closures && trait_def.paren_sugar {
+                emit_feature_err(&self.tcx().sess.parse_sess.span_diagnostic,
                                  "unboxed_closures", span, GateIssue::Language,
                                  "\
                     the precise format of `Fn`-family traits' type parameters is \
                     subject to change. Use parenthetical notation (Fn(Foo, Bar) -> Baz) instead");
             }
 
-            convert_angle_bracketed_parameters(this, rscope, span, &trait_def.generics, data)
+            self.convert_angle_bracketed_parameters(rscope, span, &trait_def.generics, data)
         }
         hir::ParenthesizedParameters(ref data) => {
             // For now, require that parenthetical notation be used
             // only with `Fn()` etc.
-            if !this.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
-                emit_feature_err(&this.tcx().sess.parse_sess.span_diagnostic,
+            if !self.tcx().sess.features.borrow().unboxed_closures && !trait_def.paren_sugar {
+                emit_feature_err(&self.tcx().sess.parse_sess.span_diagnostic,
                                  "unboxed_closures", span, GateIssue::Language,
                                  "\
                     parenthetical notation is only stable when used with `Fn`-family traits");
             }
 
-            convert_parenthesized_parameters(this, rscope, span, &trait_def.generics, data)
+            self.convert_parenthesized_parameters(rscope, span, &trait_def.generics, data)
         }
     };
 
-    let substs = create_substs_for_ast_path(this,
-                                            span,
-                                            param_mode,
-                                            &trait_def.generics,
-                                            self_ty,
-                                            types,
-                                            regions);
+    let substs = self.create_substs_for_ast_path(span,
+                                                 param_mode,
+                                                 &trait_def.generics,
+                                                 self_ty,
+                                                 types,
+                                                 regions);
 
-    (this.tcx().mk_substs(substs), assoc_bindings)
+    (self.tcx().mk_substs(substs), assoc_bindings)
 }
 
-fn ast_type_binding_to_poly_projection_predicate<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn ast_type_binding_to_poly_projection_predicate(&self,
     mut trait_ref: ty::PolyTraitRef<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     binding: &ConvertedBinding<'tcx>)
     -> Result<ty::PolyProjectionPredicate<'tcx>, ErrorReported>
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
     // Given something like `U : SomeTrait<T=X>`, we want to produce a
     // predicate like `<U as SomeTrait>::T = X`. This is somewhat
@@ -901,7 +889,7 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
     // We want to produce `<B as SuperTrait<int>>::T == foo`.
 
     // Simple case: X is defined in the current trait.
-    if this.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
+    if self.trait_defines_associated_type_named(trait_ref.def_id(), binding.item_name) {
         return Ok(ty::Binder(ty::ProjectionPredicate {      // <-------------------+
             projection_ty: ty::ProjectionTy {               //                     |
                 trait_ref: trait_ref.skip_binder().clone(), // Binder moved here --+
@@ -928,11 +916,11 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
                                                  tcx.mk_substs(dummy_substs)));
     }
 
-    this.ensure_super_predicates(binding.span, trait_ref.def_id())?;
+    self.ensure_super_predicates(binding.span, trait_ref.def_id())?;
 
     let mut candidates: Vec<ty::PolyTraitRef> =
         traits::supertraits(tcx, trait_ref.clone())
-        .filter(|r| this.trait_defines_associated_type_named(r.def_id(), binding.item_name))
+        .filter(|r| self.trait_defines_associated_type_named(r.def_id(), binding.item_name))
         .collect();
 
     // If converting for an object type, then remove the dummy-ty from `Self` now.
@@ -947,11 +935,10 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
         }
     }
 
-    let candidate = one_bound_for_assoc_type(this,
-                                             candidates,
-                                             &trait_ref.to_string(),
-                                             &binding.item_name.as_str(),
-                                             binding.span)?;
+    let candidate = self.one_bound_for_assoc_type(candidates,
+                                                  &trait_ref.to_string(),
+                                                  &binding.item_name.as_str(),
+                                                  binding.span)?;
 
     Ok(ty::Binder(ty::ProjectionPredicate {             // <-------------------------+
         projection_ty: ty::ProjectionTy {               //                           |
@@ -962,8 +949,7 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
     }))
 }
 
-fn ast_path_to_ty<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn ast_path_to_ty(&self,
     rscope: &RegionScope,
     span: Span,
     param_mode: PathParamMode,
@@ -971,8 +957,8 @@ fn ast_path_to_ty<'tcx>(
     item_segment: &hir::PathSegment)
     -> Ty<'tcx>
 {
-    let tcx = this.tcx();
-    let (generics, decl_ty) = match this.get_item_type_scheme(span, did) {
+    let tcx = self.tcx();
+    let (generics, decl_ty) = match self.get_item_type_scheme(span, did) {
         Ok(ty::TypeScheme { generics,  ty: decl_ty }) => {
             (generics, decl_ty)
         }
@@ -981,29 +967,26 @@ fn ast_path_to_ty<'tcx>(
         }
     };
 
-    let substs = ast_path_substs_for_ty(this,
-                                        rscope,
-                                        span,
-                                        param_mode,
-                                        &generics,
-                                        item_segment);
+    let substs = self.ast_path_substs_for_ty(rscope,
+                                             span,
+                                             param_mode,
+                                             &generics,
+                                             item_segment);
 
     // FIXME(#12938): This is a hack until we have full support for DST.
-    if Some(did) == this.tcx().lang_items.owned_box() {
+    if Some(did) == self.tcx().lang_items.owned_box() {
         assert_eq!(substs.types.len(TypeSpace), 1);
-        return this.tcx().mk_box(*substs.types.get(TypeSpace, 0));
+        return self.tcx().mk_box(*substs.types.get(TypeSpace, 0));
     }
 
-    decl_ty.subst(this.tcx(), &substs)
+    decl_ty.subst(self.tcx(), &substs)
 }
 
-type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
-
-fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                             rscope: &RegionScope,
-                             ty: &hir::Ty,
-                             bounds: &[hir::TyParamBound])
-                             -> Result<TraitAndProjections<'tcx>, ErrorReported>
+fn ast_ty_to_trait_ref(&self,
+                       rscope: &RegionScope,
+                       ty: &hir::Ty,
+                       bounds: &[hir::TyParamBound])
+                       -> Result<TraitAndProjections<'tcx>, ErrorReported>
 {
     /*!
      * In a type like `Foo + Send`, we want to wait to collect the
@@ -1018,30 +1001,30 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx, 'tcx>,
 
     match ty.node {
         hir::TyPath(None, ref path) => {
-            let def = match this.tcx().def_map.borrow().get(&ty.id) {
+            let def = match self.tcx().def_map.borrow().get(&ty.id) {
                 Some(&def::PathResolution { base_def, depth: 0, .. }) => Some(base_def),
                 _ => None
             };
             match def {
                 Some(Def::Trait(trait_def_id)) => {
                     let mut projection_bounds = Vec::new();
-                    let trait_ref = object_path_to_poly_trait_ref(this,
-                                                                  rscope,
-                                                                  path.span,
-                                                                  PathParamMode::Explicit,
-                                                                  trait_def_id,
-                                                                  path.segments.last().unwrap(),
-                                                                  &mut projection_bounds);
+                    let trait_ref =
+                        self.object_path_to_poly_trait_ref(rscope,
+                                                           path.span,
+                                                           PathParamMode::Explicit,
+                                                           trait_def_id,
+                                                           path.segments.last().unwrap(),
+                                                           &mut projection_bounds);
                     Ok((trait_ref, projection_bounds))
                 }
                 _ => {
-                    span_err!(this.tcx().sess, ty.span, E0172, "expected a reference to a trait");
+                    span_err!(self.tcx().sess, ty.span, E0172, "expected a reference to a trait");
                     Err(ErrorReported)
                 }
             }
         }
         _ => {
-            let mut err = struct_span_err!(this.tcx().sess, ty.span, E0178,
+            let mut err = struct_span_err!(self.tcx().sess, ty.span, E0178,
                                            "expected a path on the left-hand side of `+`, not `{}`",
                                            pprust::ty_to_string(ty));
             let hi = bounds.iter().map(|x| match *x {
@@ -1083,34 +1066,33 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx, 'tcx>,
     }
 }
 
-fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                  rscope: &RegionScope,
-                                  span: Span,
-                                  trait_ref: ty::PolyTraitRef<'tcx>,
-                                  projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
-                                  bounds: &[hir::TyParamBound])
-                                  -> Ty<'tcx>
+fn trait_ref_to_object_type(&self,
+                            rscope: &RegionScope,
+                            span: Span,
+                            trait_ref: ty::PolyTraitRef<'tcx>,
+                            projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
+                            bounds: &[hir::TyParamBound])
+                            -> Ty<'tcx>
 {
-    let existential_bounds = conv_existential_bounds(this,
-                                                     rscope,
-                                                     span,
-                                                     trait_ref.clone(),
-                                                     projection_bounds,
-                                                     bounds);
-
-    let result = make_object_type(this, span, trait_ref, existential_bounds);
+    let existential_bounds = self.conv_existential_bounds(rscope,
+                                                          span,
+                                                          trait_ref.clone(),
+                                                          projection_bounds,
+                                                          bounds);
+
+    let result = self.make_object_type(span, trait_ref, existential_bounds);
     debug!("trait_ref_to_object_type: result={:?}",
            result);
 
     result
 }
 
-fn make_object_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                          span: Span,
-                          principal: ty::PolyTraitRef<'tcx>,
-                          bounds: ty::ExistentialBounds<'tcx>)
-                          -> Ty<'tcx> {
-    let tcx = this.tcx();
+fn make_object_type(&self,
+                    span: Span,
+                    principal: ty::PolyTraitRef<'tcx>,
+                    bounds: ty::ExistentialBounds<'tcx>)
+                    -> Ty<'tcx> {
+    let tcx = self.tcx();
     let object = ty::TraitTy {
         principal: principal,
         bounds: bounds
@@ -1119,7 +1101,7 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
         object.principal_trait_ref_with_self_ty(tcx, tcx.types.err);
 
     // ensure the super predicates and stop if we encountered an error
-    if this.ensure_super_predicates(span, principal.def_id()).is_err() {
+    if self.ensure_super_predicates(span, principal.def_id()).is_err() {
         return tcx.types.err;
     }
 
@@ -1162,12 +1144,12 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
     tcx.mk_trait(object.principal, object.bounds)
 }
 
-fn report_ambiguous_associated_type(tcx: TyCtxt,
+fn report_ambiguous_associated_type(&self,
                                     span: Span,
                                     type_str: &str,
                                     trait_str: &str,
                                     name: &str) {
-    span_err!(tcx.sess, span, E0223,
+    span_err!(self.tcx().sess, span, E0223,
               "ambiguous associated type; specify the type using the syntax \
                `<{} as {}>::{}`",
               type_str, trait_str, name);
@@ -1178,16 +1160,16 @@ fn report_ambiguous_associated_type(tcx: TyCtxt,
 // (which might be `Self`, but only if it is the `Self` of a trait, not an
 // impl). This function will fail if there are no suitable bounds or there is
 // any ambiguity.
-fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                   ty_param_node_id: ast::NodeId,
-                                   ty_param_name: ast::Name,
-                                   assoc_name: ast::Name,
-                                   span: Span)
-                                   -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
+fn find_bound_for_assoc_item(&self,
+                             ty_param_node_id: ast::NodeId,
+                             ty_param_name: ast::Name,
+                             assoc_name: ast::Name,
+                             span: Span)
+                             -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
-    let bounds = match this.get_type_parameter_bounds(span, ty_param_node_id) {
+    let bounds = match self.get_type_parameter_bounds(span, ty_param_node_id) {
         Ok(v) => v,
         Err(ErrorReported) => {
             return Err(ErrorReported);
@@ -1195,7 +1177,7 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx, 'tcx>,
     };
 
     // Ensure the super predicates and stop if we encountered an error.
-    if bounds.iter().any(|b| this.ensure_super_predicates(span, b.def_id()).is_err()) {
+    if bounds.iter().any(|b| self.ensure_super_predicates(span, b.def_id()).is_err()) {
         return Err(ErrorReported);
     }
 
@@ -1203,28 +1185,27 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx, 'tcx>,
     // correct name.
     let suitable_bounds: Vec<_> =
         traits::transitive_bounds(tcx, &bounds)
-        .filter(|b| this.trait_defines_associated_type_named(b.def_id(), assoc_name))
+        .filter(|b| self.trait_defines_associated_type_named(b.def_id(), assoc_name))
         .collect();
 
-    one_bound_for_assoc_type(this,
-                             suitable_bounds,
-                             &ty_param_name.as_str(),
-                             &assoc_name.as_str(),
-                             span)
+    self.one_bound_for_assoc_type(suitable_bounds,
+                                  &ty_param_name.as_str(),
+                                  &assoc_name.as_str(),
+                                  span)
 }
 
 
 // Checks that bounds contains exactly one element and reports appropriate
 // errors otherwise.
-fn one_bound_for_assoc_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                  bounds: Vec<ty::PolyTraitRef<'tcx>>,
-                                  ty_param_name: &str,
-                                  assoc_name: &str,
-                                  span: Span)
+fn one_bound_for_assoc_type(&self,
+                            bounds: Vec<ty::PolyTraitRef<'tcx>>,
+                            ty_param_name: &str,
+                            assoc_name: &str,
+                            span: Span)
     -> Result<ty::PolyTraitRef<'tcx>, ErrorReported>
 {
     if bounds.is_empty() {
-        span_err!(this.tcx().sess, span, E0220,
+        span_err!(self.tcx().sess, span, E0220,
                   "associated type `{}` not found for `{}`",
                   assoc_name,
                   ty_param_name);
@@ -1232,7 +1213,7 @@ fn one_bound_for_assoc_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
     }
 
     if bounds.len() > 1 {
-        let mut err = struct_span_err!(this.tcx().sess, span, E0221,
+        let mut err = struct_span_err!(self.tcx().sess, span, E0221,
                                        "ambiguous associated type `{}` in bounds of `{}`",
                                        assoc_name,
                                        ty_param_name);
@@ -1255,14 +1236,14 @@ fn one_bound_for_assoc_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
 // the whole path.
 // Will fail except for T::A and Self::A; i.e., if ty/ty_path_def are not a type
 // parameter or Self.
-fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                   span: Span,
-                                   ty: Ty<'tcx>,
-                                   ty_path_def: Def,
-                                   item_segment: &hir::PathSegment)
-                                   -> (Ty<'tcx>, Def)
+fn associated_path_def_to_ty(&self,
+                             span: Span,
+                             ty: Ty<'tcx>,
+                             ty_path_def: Def,
+                             item_segment: &hir::PathSegment)
+                             -> (Ty<'tcx>, Def)
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
     let assoc_name = item_segment.identifier.name;
 
     debug!("associated_path_def_to_ty: {:?}::{}", ty, assoc_name);
@@ -1276,65 +1257,61 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
             // `Self` in an impl of a trait - we have a concrete self type and a
             // trait reference.
             let trait_ref = tcx.impl_trait_ref(tcx.map.local_def_id(impl_id)).unwrap();
-            let trait_ref = if let Some(free_substs) = this.get_free_substs() {
+            let trait_ref = if let Some(free_substs) = self.get_free_substs() {
                 trait_ref.subst(tcx, free_substs)
             } else {
                 trait_ref
             };
 
-            if this.ensure_super_predicates(span, trait_did).is_err() {
+            if self.ensure_super_predicates(span, trait_did).is_err() {
                 return (tcx.types.err, ty_path_def);
             }
 
             let candidates: Vec<ty::PolyTraitRef> =
                 traits::supertraits(tcx, ty::Binder(trait_ref))
-                .filter(|r| this.trait_defines_associated_type_named(r.def_id(),
+                .filter(|r| self.trait_defines_associated_type_named(r.def_id(),
                                                                      assoc_name))
                 .collect();
 
-            match one_bound_for_assoc_type(this,
-                                           candidates,
-                                           "Self",
-                                           &assoc_name.as_str(),
-                                           span) {
+            match self.one_bound_for_assoc_type(candidates,
+                                                "Self",
+                                                &assoc_name.as_str(),
+                                                span) {
                 Ok(bound) => bound,
                 Err(ErrorReported) => return (tcx.types.err, ty_path_def),
             }
         }
         (&ty::TyParam(_), Def::SelfTy(Some(trait_did), None)) => {
             let trait_node_id = tcx.map.as_local_node_id(trait_did).unwrap();
-            match find_bound_for_assoc_item(this,
-                                            trait_node_id,
-                                            keywords::SelfType.name(),
-                                            assoc_name,
-                                            span) {
+            match self.find_bound_for_assoc_item(trait_node_id,
+                                                 keywords::SelfType.name(),
+                                                 assoc_name,
+                                                 span) {
                 Ok(bound) => bound,
                 Err(ErrorReported) => return (tcx.types.err, ty_path_def),
             }
         }
         (&ty::TyParam(_), Def::TyParam(_, _, param_did, param_name)) => {
             let param_node_id = tcx.map.as_local_node_id(param_did).unwrap();
-            match find_bound_for_assoc_item(this,
-                                            param_node_id,
-                                            param_name,
-                                            assoc_name,
-                                            span) {
+            match self.find_bound_for_assoc_item(param_node_id,
+                                                 param_name,
+                                                 assoc_name,
+                                                 span) {
                 Ok(bound) => bound,
                 Err(ErrorReported) => return (tcx.types.err, ty_path_def),
             }
         }
         _ => {
-            report_ambiguous_associated_type(tcx,
-                                             span,
-                                             &ty.to_string(),
-                                             "Trait",
-                                             &assoc_name.as_str());
+            self.report_ambiguous_associated_type(span,
+                                                  &ty.to_string(),
+                                                  "Trait",
+                                                  &assoc_name.as_str());
             return (tcx.types.err, ty_path_def);
         }
     };
 
     let trait_did = bound.0.def_id;
-    let ty = this.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
+    let ty = self.projected_ty_from_poly_trait_ref(span, bound, assoc_name);
 
     let item_did = if let Some(trait_id) = tcx.map.as_local_node_id(trait_did) {
         // `ty::trait_items` used below requires information generated
@@ -1357,17 +1334,17 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
     (ty, Def::AssociatedTy(trait_did, item_did))
 }
 
-fn qpath_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                     rscope: &RegionScope,
-                     span: Span,
-                     param_mode: PathParamMode,
-                     opt_self_ty: Option<Ty<'tcx>>,
-                     trait_def_id: DefId,
-                     trait_segment: &hir::PathSegment,
-                     item_segment: &hir::PathSegment)
-                     -> Ty<'tcx>
+fn qpath_to_ty(&self,
+               rscope: &RegionScope,
+               span: Span,
+               param_mode: PathParamMode,
+               opt_self_ty: Option<Ty<'tcx>>,
+               trait_def_id: DefId,
+               trait_segment: &hir::PathSegment,
+               item_segment: &hir::PathSegment)
+               -> Ty<'tcx>
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
     tcx.prohibit_type_params(slice::ref_slice(item_segment));
 
@@ -1375,27 +1352,25 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
         ty
     } else {
         let path_str = tcx.item_path_str(trait_def_id);
-        report_ambiguous_associated_type(tcx,
-                                         span,
-                                         "Type",
-                                         &path_str,
-                                         &item_segment.identifier.name.as_str());
+        self.report_ambiguous_associated_type(span,
+                                              "Type",
+                                              &path_str,
+                                              &item_segment.identifier.name.as_str());
         return tcx.types.err;
     };
 
     debug!("qpath_to_ty: self_type={:?}", self_ty);
 
-    let trait_ref = ast_path_to_mono_trait_ref(this,
-                                               rscope,
-                                               span,
-                                               param_mode,
-                                               trait_def_id,
-                                               Some(self_ty),
-                                               trait_segment);
+    let trait_ref = self.ast_path_to_mono_trait_ref(rscope,
+                                                    span,
+                                                    param_mode,
+                                                    trait_def_id,
+                                                    Some(self_ty),
+                                                    trait_segment);
 
     debug!("qpath_to_ty: trait_ref={:?}", trait_ref);
 
-    this.projected_ty(span, trait_ref, item_segment.identifier.name)
+    self.projected_ty(span, trait_ref, item_segment.identifier.name)
 }
 
 /// Convert a type supplied as value for a type argument from AST into our
@@ -1412,37 +1387,37 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
 /// * `region_substs`: a partial substitution consisting of
 ///   only the region type parameters being supplied to this type.
 /// * `ast_ty`: the ast representation of the type being supplied
-pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                              rscope: &RegionScope,
-                              decl_generics: &ty::Generics<'tcx>,
-                              index: usize,
-                              region_substs: &Substs<'tcx>,
-                              ast_ty: &hir::Ty)
-                              -> Ty<'tcx>
+pub fn ast_ty_arg_to_ty(&self,
+                        rscope: &RegionScope,
+                        decl_generics: &ty::Generics<'tcx>,
+                        index: usize,
+                        region_substs: &Substs<'tcx>,
+                        ast_ty: &hir::Ty)
+                        -> Ty<'tcx>
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
     if let Some(def) = decl_generics.types.opt_get(TypeSpace, index) {
         let object_lifetime_default = def.object_lifetime_default.subst(tcx, region_substs);
         let rscope1 = &ObjectLifetimeDefaultRscope::new(rscope, object_lifetime_default);
-        ast_ty_to_ty(this, rscope1, ast_ty)
+        self.ast_ty_to_ty(rscope1, ast_ty)
     } else {
-        ast_ty_to_ty(this, rscope, ast_ty)
+        self.ast_ty_to_ty(rscope, ast_ty)
     }
 }
 
 // Check the base def in a PathResolution and convert it to a Ty. If there are
 // associated types in the PathResolution, these will need to be separately
 // resolved.
-fn base_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                        rscope: &RegionScope,
-                        span: Span,
-                        param_mode: PathParamMode,
-                        def: &Def,
-                        opt_self_ty: Option<Ty<'tcx>>,
-                        base_segments: &[hir::PathSegment])
-                        -> Ty<'tcx> {
-    let tcx = this.tcx();
+fn base_def_to_ty(&self,
+                  rscope: &RegionScope,
+                  span: Span,
+                  param_mode: PathParamMode,
+                  def: &Def,
+                  opt_self_ty: Option<Ty<'tcx>>,
+                  base_segments: &[hir::PathSegment])
+                  -> Ty<'tcx> {
+    let tcx = self.tcx();
 
     match *def {
         Def::Trait(trait_def_id) => {
@@ -1450,30 +1425,28 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
             // TyObjectSum, see that fn for details
             let mut projection_bounds = Vec::new();
 
-            let trait_ref = object_path_to_poly_trait_ref(this,
-                                                          rscope,
-                                                          span,
-                                                          param_mode,
-                                                          trait_def_id,
-                                                          base_segments.last().unwrap(),
-                                                          &mut projection_bounds);
+            let trait_ref =
+                self.object_path_to_poly_trait_ref(rscope,
+                                                   span,
+                                                   param_mode,
+                                                   trait_def_id,
+                                                   base_segments.last().unwrap(),
+                                                   &mut projection_bounds);
 
             tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
-            trait_ref_to_object_type(this,
-                                     rscope,
-                                     span,
-                                     trait_ref,
-                                     projection_bounds,
-                                     &[])
+            self.trait_ref_to_object_type(rscope,
+                                          span,
+                                          trait_ref,
+                                          projection_bounds,
+                                          &[])
         }
         Def::Enum(did) | Def::TyAlias(did) | Def::Struct(did) => {
             tcx.prohibit_type_params(base_segments.split_last().unwrap().1);
-            ast_path_to_ty(this,
-                           rscope,
-                           span,
-                           param_mode,
-                           did,
-                           base_segments.last().unwrap())
+            self.ast_path_to_ty(rscope,
+                                span,
+                                param_mode,
+                                did,
+                                base_segments.last().unwrap())
         }
         Def::TyParam(space, index, _, name) => {
             tcx.prohibit_type_params(base_segments);
@@ -1483,7 +1456,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
             // Self in impl (we know the concrete type).
             tcx.prohibit_type_params(base_segments);
             let ty = tcx.node_id_to_type(impl_id);
-            if let Some(free_substs) = this.get_free_substs() {
+            if let Some(free_substs) = self.get_free_substs() {
                 ty.subst(tcx, free_substs)
             } else {
                 ty
@@ -1496,14 +1469,13 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
         }
         Def::AssociatedTy(trait_did, _) => {
             tcx.prohibit_type_params(&base_segments[..base_segments.len()-2]);
-            qpath_to_ty(this,
-                        rscope,
-                        span,
-                        param_mode,
-                        opt_self_ty,
-                        trait_did,
-                        &base_segments[base_segments.len()-2],
-                        base_segments.last().unwrap())
+            self.qpath_to_ty(rscope,
+                             span,
+                             param_mode,
+                             opt_self_ty,
+                             trait_did,
+                             &base_segments[base_segments.len()-2],
+                             base_segments.last().unwrap())
         }
         Def::Mod(..) => {
             // Used as sentinel by callers to indicate the `<T>::A::B::C` form.
@@ -1522,36 +1494,35 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
             tcx.prim_ty_to_ty(base_segments, prim_ty)
         }
         Def::Err => {
-            this.set_tainted_by_errors();
-            return this.tcx().types.err;
+            self.set_tainted_by_errors();
+            return self.tcx().types.err;
         }
         _ => {
             span_err!(tcx.sess, span, E0248,
                       "found value `{}` used as a type",
                       tcx.item_path_str(def.def_id()));
-            return this.tcx().types.err;
+            return self.tcx().types.err;
         }
     }
 }
 
 // Note that both base_segments and assoc_segments may be empty, although not at
 // the same time.
-pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                        rscope: &RegionScope,
-                                        span: Span,
-                                        param_mode: PathParamMode,
-                                        def: &Def,
-                                        opt_self_ty: Option<Ty<'tcx>>,
-                                        base_segments: &[hir::PathSegment],
-                                        assoc_segments: &[hir::PathSegment])
-                                        -> Ty<'tcx> {
-    let mut ty = base_def_to_ty(this,
-                                rscope,
-                                span,
-                                param_mode,
-                                def,
-                                opt_self_ty,
-                                base_segments);
+pub fn finish_resolving_def_to_ty(&self,
+                                  rscope: &RegionScope,
+                                  span: Span,
+                                  param_mode: PathParamMode,
+                                  def: &Def,
+                                  opt_self_ty: Option<Ty<'tcx>>,
+                                  base_segments: &[hir::PathSegment],
+                                  assoc_segments: &[hir::PathSegment])
+                                  -> Ty<'tcx> {
+    let mut ty = self.base_def_to_ty(rscope,
+                                     span,
+                                     param_mode,
+                                     def,
+                                     opt_self_ty,
+                                     base_segments);
     let mut def = *def;
     // If any associated type segments remain, attempt to resolve them.
     for segment in assoc_segments {
@@ -1559,11 +1530,10 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
             break;
         }
         // This is pretty bad (it will fail except for T::A and Self::A).
-        let (a_ty, a_def) = associated_path_def_to_ty(this,
-                                                      span,
-                                                      ty,
-                                                      def,
-                                                      segment);
+        let (a_ty, a_def) = self.associated_path_def_to_ty(span,
+                                                           ty,
+                                                           def,
+                                                           segment);
         ty = a_ty;
         def = a_def;
     }
@@ -1572,63 +1542,58 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
 
 /// Parses the programmer's textual representation of a type into our
 /// internal notion of a type.
-pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                          rscope: &RegionScope,
-                          ast_ty: &hir::Ty)
-                          -> Ty<'tcx>
-{
+pub fn ast_ty_to_ty(&self, rscope: &RegionScope, ast_ty: &hir::Ty) -> Ty<'tcx> {
     debug!("ast_ty_to_ty(id={:?}, ast_ty={:?})",
            ast_ty.id, ast_ty);
 
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
     match ast_ty.node {
         hir::TyVec(ref ty) => {
-            tcx.mk_slice(ast_ty_to_ty(this, rscope, &ty))
+            tcx.mk_slice(self.ast_ty_to_ty(rscope, &ty))
         }
         hir::TyObjectSum(ref ty, ref bounds) => {
-            match ast_ty_to_trait_ref(this, rscope, &ty, bounds) {
+            match self.ast_ty_to_trait_ref(rscope, &ty, bounds) {
                 Ok((trait_ref, projection_bounds)) => {
-                    trait_ref_to_object_type(this,
-                                             rscope,
-                                             ast_ty.span,
-                                             trait_ref,
-                                             projection_bounds,
-                                             bounds)
+                    self.trait_ref_to_object_type(rscope,
+                                                  ast_ty.span,
+                                                  trait_ref,
+                                                  projection_bounds,
+                                                  bounds)
                 }
                 Err(ErrorReported) => {
-                    this.tcx().types.err
+                    self.tcx().types.err
                 }
             }
         }
         hir::TyPtr(ref mt) => {
             tcx.mk_ptr(ty::TypeAndMut {
-                ty: ast_ty_to_ty(this, rscope, &mt.ty),
+                ty: self.ast_ty_to_ty(rscope, &mt.ty),
                 mutbl: mt.mutbl
             })
         }
         hir::TyRptr(ref region, ref mt) => {
-            let r = opt_ast_region_to_region(this, rscope, ast_ty.span, region);
+            let r = self.opt_ast_region_to_region(rscope, ast_ty.span, region);
             debug!("TyRef r={:?}", r);
             let rscope1 =
                 &ObjectLifetimeDefaultRscope::new(
                     rscope,
                     ty::ObjectLifetimeDefault::Specific(r));
-            let t = ast_ty_to_ty(this, rscope1, &mt.ty);
+            let t = self.ast_ty_to_ty(rscope1, &mt.ty);
             tcx.mk_ref(tcx.mk_region(r), ty::TypeAndMut {ty: t, mutbl: mt.mutbl})
         }
         hir::TyTup(ref fields) => {
             let flds = fields.iter()
-                             .map(|t| ast_ty_to_ty(this, rscope, &t))
+                             .map(|t| self.ast_ty_to_ty(rscope, &t))
                              .collect();
             tcx.mk_tup(flds)
         }
         hir::TyBareFn(ref bf) => {
             require_c_abi_if_variadic(tcx, &bf.decl, bf.abi, ast_ty.span);
-            tcx.mk_fn_ptr(ty_of_bare_fn(this, bf.unsafety, bf.abi, &bf.decl))
+            tcx.mk_fn_ptr(self.ty_of_bare_fn(bf.unsafety, bf.abi, &bf.decl))
         }
         hir::TyPolyTraitRef(ref bounds) => {
-            conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
+            self.conv_ty_poly_trait_ref(rscope, ast_ty.span, bounds)
         }
         hir::TyPath(ref maybe_qself, ref path) => {
             let path_res = if let Some(&d) = tcx.def_map.borrow().get(&ast_ty.id) {
@@ -1645,16 +1610,15 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
             let def = path_res.base_def;
             let base_ty_end = path.segments.len() - path_res.depth;
             let opt_self_ty = maybe_qself.as_ref().map(|qself| {
-                ast_ty_to_ty(this, rscope, &qself.ty)
+                self.ast_ty_to_ty(rscope, &qself.ty)
             });
-            let ty = finish_resolving_def_to_ty(this,
-                                                rscope,
-                                                ast_ty.span,
-                                                PathParamMode::Explicit,
-                                                &def,
-                                                opt_self_ty,
-                                                &path.segments[..base_ty_end],
-                                                &path.segments[base_ty_end..]);
+            let ty = self.finish_resolving_def_to_ty(rscope,
+                                                     ast_ty.span,
+                                                     PathParamMode::Explicit,
+                                                     &def,
+                                                     opt_self_ty,
+                                                     &path.segments[..base_ty_end],
+                                                     &path.segments[base_ty_end..]);
 
             if path_res.depth != 0 && ty.sty != ty::TyError {
                 // Write back the new resolution.
@@ -1668,16 +1632,16 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
         }
         hir::TyFixedLengthVec(ref ty, ref e) => {
             let hint = UncheckedExprHint(tcx.types.usize);
-            match eval_const_expr_partial(tcx, &e, hint, None) {
+            match eval_const_expr_partial(tcx.global_tcx(), &e, hint, None) {
                 Ok(ConstVal::Integral(ConstInt::Usize(i))) => {
                     let i = i.as_u64(tcx.sess.target.uint_type);
                     assert_eq!(i as usize as u64, i);
-                    tcx.mk_array(ast_ty_to_ty(this, rscope, &ty), i as usize)
+                    tcx.mk_array(self.ast_ty_to_ty(rscope, &ty), i as usize)
                 },
                 Ok(val) => {
                     span_err!(tcx.sess, ast_ty.span, E0249,
                               "expected usize value for array length, got {}", val.description());
-                    this.tcx().types.err
+                    self.tcx().types.err
                 },
                 // array length errors happen before the global constant check
                 // so we need to report the real error
@@ -1690,7 +1654,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
                         span_note!(&mut err, ast_ty.span, "for array length here")
                     }
                     err.emit();
-                    this.tcx().types.err
+                    self.tcx().types.err
                 }
             }
         }
@@ -1704,61 +1668,55 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
             // values in a ExprClosure, or as
             // the type of local variables. Both of these cases are
             // handled specially and will not descend into this routine.
-            this.ty_infer(None, None, None, ast_ty.span)
+            self.ty_infer(None, None, None, ast_ty.span)
         }
     }
 }
 
-pub fn ty_of_arg<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                       rscope: &RegionScope,
-                       a: &hir::Arg,
-                       expected_ty: Option<Ty<'tcx>>)
-                       -> Ty<'tcx>
+pub fn ty_of_arg(&self,
+                 rscope: &RegionScope,
+                 a: &hir::Arg,
+                 expected_ty: Option<Ty<'tcx>>)
+                 -> Ty<'tcx>
 {
     match a.ty.node {
         hir::TyInfer if expected_ty.is_some() => expected_ty.unwrap(),
-        hir::TyInfer => this.ty_infer(None, None, None, a.ty.span),
-        _ => ast_ty_to_ty(this, rscope, &a.ty),
+        hir::TyInfer => self.ty_infer(None, None, None, a.ty.span),
+        _ => self.ast_ty_to_ty(rscope, &a.ty),
     }
 }
 
-struct SelfInfo<'a, 'tcx> {
-    untransformed_self_ty: Ty<'tcx>,
-    explicit_self: &'a hir::ExplicitSelf,
-}
-
-pub fn ty_of_method<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                          sig: &hir::MethodSig,
-                          untransformed_self_ty: Ty<'tcx>)
-                          -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
+pub fn ty_of_method(&self,
+                    sig: &hir::MethodSig,
+                    untransformed_self_ty: Ty<'tcx>)
+                    -> (&'tcx ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
     let self_info = Some(SelfInfo {
         untransformed_self_ty: untransformed_self_ty,
         explicit_self: &sig.explicit_self,
     });
     let (bare_fn_ty, optional_explicit_self_category) =
-        ty_of_method_or_bare_fn(this,
-                                sig.unsafety,
-                                sig.abi,
-                                self_info,
-                                &sig.decl);
+        self.ty_of_method_or_bare_fn(sig.unsafety,
+                                     sig.abi,
+                                     self_info,
+                                     &sig.decl);
     (bare_fn_ty, optional_explicit_self_category.unwrap())
 }
 
-pub fn ty_of_bare_fn<'tcx>(this: &AstConv<'tcx, 'tcx>,
-                           unsafety: hir::Unsafety, abi: abi::Abi,
-                           decl: &hir::FnDecl)
-                           -> &'tcx ty::BareFnTy<'tcx> {
-    let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl);
+pub fn ty_of_bare_fn(&self,
+                     unsafety: hir::Unsafety, abi: abi::Abi,
+                     decl: &hir::FnDecl)
+                     -> &'tcx ty::BareFnTy<'tcx> {
+    let (bare_fn_ty, _) = self.ty_of_method_or_bare_fn(unsafety, abi, None, decl);
     bare_fn_ty
 }
 
-fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                     unsafety: hir::Unsafety,
-                                     abi: abi::Abi,
-                                     opt_self_info: Option<SelfInfo<'a, 'tcx>>,
-                                     decl: &hir::FnDecl)
-                                     -> (&'tcx ty::BareFnTy<'tcx>,
-                                         Option<ty::ExplicitSelfCategory>)
+fn ty_of_method_or_bare_fn<'a>(&self,
+                               unsafety: hir::Unsafety,
+                               abi: abi::Abi,
+                               opt_self_info: Option<SelfInfo<'a, 'tcx>>,
+                               decl: &hir::FnDecl)
+                               -> (&'tcx ty::BareFnTy<'tcx>,
+                                   Option<ty::ExplicitSelfCategory>)
 {
     debug!("ty_of_method_or_bare_fn");
 
@@ -1773,7 +1731,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
     // region of the self parameter.
     let (self_ty, explicit_self_category) = match opt_self_info {
         None => (None, None),
-        Some(self_info) => determine_self_type(this, &rb, self_info)
+        Some(self_info) => self.determine_self_type(&rb, self_info)
     };
 
     // HACK(eddyb) replace the fake self type in the AST with the actual type.
@@ -1783,7 +1741,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
         &decl.inputs[..]
     };
     let arg_tys: Vec<Ty> =
-        arg_params.iter().map(|a| ty_of_arg(this, &rb, a, None)).collect();
+        arg_params.iter().map(|a| self.ty_of_arg(&rb, a, None)).collect();
     let arg_pats: Vec<String> =
         arg_params.iter().map(|a| pprust::pat_to_string(&a.pat)).collect();
 
@@ -1792,19 +1750,18 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
     // have that lifetime.
     let implied_output_region = match explicit_self_category {
         Some(ty::ExplicitSelfCategory::ByReference(region, _)) => Ok(region),
-        _ => find_implied_output_region(this, &arg_tys, arg_pats)
+        _ => self.find_implied_output_region(&arg_tys, arg_pats)
     };
 
     let output_ty = match decl.output {
         hir::Return(ref output) =>
-            ty::FnConverging(convert_ty_with_lifetime_elision(this,
-                                                              implied_output_region,
-                                                              &output)),
-        hir::DefaultReturn(..) => ty::FnConverging(this.tcx().mk_nil()),
+            ty::FnConverging(self.convert_ty_with_lifetime_elision(implied_output_region,
+                                                                   &output)),
+        hir::DefaultReturn(..) => ty::FnConverging(self.tcx().mk_nil()),
         hir::NoReturn(..) => ty::FnDiverging
     };
 
-    (this.tcx().mk_bare_fn(ty::BareFnTy {
+    (self.tcx().mk_bare_fn(ty::BareFnTy {
         unsafety: unsafety,
         abi: abi,
         sig: ty::Binder(ty::FnSig {
@@ -1815,10 +1772,10 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
     }), explicit_self_category)
 }
 
-fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
-                                 rscope: &RegionScope,
-                                 self_info: SelfInfo<'a, 'tcx>)
-                                 -> (Option<Ty<'tcx>>, Option<ty::ExplicitSelfCategory>)
+fn determine_self_type<'a>(&self,
+                           rscope: &RegionScope,
+                           self_info: SelfInfo<'a, 'tcx>)
+                           -> (Option<Ty<'tcx>>, Option<ty::ExplicitSelfCategory>)
 {
     let self_ty = self_info.untransformed_self_ty;
     return match self_info.explicit_self.node {
@@ -1828,12 +1785,11 @@ fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
         }
         hir::SelfRegion(ref lifetime, mutability, _) => {
             let region =
-                opt_ast_region_to_region(this,
-                                         rscope,
-                                         self_info.explicit_self.span,
-                                         lifetime);
-            (Some(this.tcx().mk_ref(
-                this.tcx().mk_region(region),
+                self.opt_ast_region_to_region(rscope,
+                                              self_info.explicit_self.span,
+                                              lifetime);
+            (Some(self.tcx().mk_ref(
+                self.tcx().mk_region(region),
                 ty::TypeAndMut {
                     ty: self_ty,
                     mutbl: mutability
@@ -1841,7 +1797,7 @@ fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
              Some(ty::ExplicitSelfCategory::ByReference(region, mutability)))
         }
         hir::SelfExplicit(ref ast_type, _) => {
-            let explicit_type = ast_ty_to_ty(this, rscope, &ast_type);
+            let explicit_type = self.ast_ty_to_ty(rscope, &ast_type);
 
             // We wish to (for now) categorize an explicit self
             // declaration like `self: SomeType` into either `self`,
@@ -1906,8 +1862,7 @@ fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
     }
 }
 
-pub fn ty_of_closure<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+pub fn ty_of_closure(&self,
     unsafety: hir::Unsafety,
     decl: &hir::FnDecl,
     abi: abi::Abi,
@@ -1931,7 +1886,7 @@ pub fn ty_of_closure<'tcx>(
                 None
             }
         });
-        ty_of_arg(this, &rb, a, expected_arg_ty)
+        self.ty_of_arg(&rb, a, expected_arg_ty)
     }).collect();
 
     let expected_ret_ty = expected_sig.map(|e| e.output);
@@ -1946,9 +1901,9 @@ pub fn ty_of_closure<'tcx>(
         _ if is_infer && expected_ret_ty.is_some() =>
             expected_ret_ty.unwrap(),
         _ if is_infer =>
-            ty::FnConverging(this.ty_infer(None, None, None, decl.output.span())),
+            ty::FnConverging(self.ty_infer(None, None, None, decl.output.span())),
         hir::Return(ref output) =>
-            ty::FnConverging(ast_ty_to_ty(this, &rb, &output)),
+            ty::FnConverging(self.ast_ty_to_ty(&rb, &output)),
         hir::DefaultReturn(..) => bug!(),
         hir::NoReturn(..) => ty::FnDiverging
     };
@@ -1969,8 +1924,7 @@ pub fn ty_of_closure<'tcx>(
 /// `ExistentialBounds` struct. The `main_trait_refs` argument specifies the `Foo` -- it is absent
 /// for closures. Eventually this should all be normalized, I think, so that there is no "main
 /// trait ref" and instead we just have a flat list of bounds as the existential type.
-fn conv_existential_bounds<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn conv_existential_bounds(&self,
     rscope: &RegionScope,
     span: Span,
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
@@ -1979,48 +1933,44 @@ fn conv_existential_bounds<'tcx>(
     -> ty::ExistentialBounds<'tcx>
 {
     let partitioned_bounds =
-        partition_bounds(this.tcx(), span, ast_bounds);
+        partition_bounds(self.tcx(), span, ast_bounds);
 
-    conv_existential_bounds_from_partitioned_bounds(
-        this, rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
+    self.conv_existential_bounds_from_partitioned_bounds(
+        rscope, span, principal_trait_ref, projection_bounds, partitioned_bounds)
 }
 
-fn conv_ty_poly_trait_ref<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn conv_ty_poly_trait_ref(&self,
     rscope: &RegionScope,
     span: Span,
     ast_bounds: &[hir::TyParamBound])
     -> Ty<'tcx>
 {
-    let mut partitioned_bounds = partition_bounds(this.tcx(), span, &ast_bounds[..]);
+    let mut partitioned_bounds = partition_bounds(self.tcx(), span, &ast_bounds[..]);
 
     let mut projection_bounds = Vec::new();
     let main_trait_bound = if !partitioned_bounds.trait_bounds.is_empty() {
         let trait_bound = partitioned_bounds.trait_bounds.remove(0);
-        instantiate_poly_trait_ref(this,
-                                   rscope,
-                                   trait_bound,
-                                   None,
-                                   &mut projection_bounds)
+        self.instantiate_poly_trait_ref(rscope,
+                                        trait_bound,
+                                        None,
+                                        &mut projection_bounds)
     } else {
-        span_err!(this.tcx().sess, span, E0224,
+        span_err!(self.tcx().sess, span, E0224,
                   "at least one non-builtin trait is required for an object type");
-        return this.tcx().types.err;
+        return self.tcx().types.err;
     };
 
     let bounds =
-        conv_existential_bounds_from_partitioned_bounds(this,
-                                                        rscope,
-                                                        span,
-                                                        main_trait_bound.clone(),
-                                                        projection_bounds,
-                                                        partitioned_bounds);
-
-    make_object_type(this, span, main_trait_bound, bounds)
+        self.conv_existential_bounds_from_partitioned_bounds(rscope,
+                                                             span,
+                                                             main_trait_bound.clone(),
+                                                             projection_bounds,
+                                                             partitioned_bounds);
+
+    self.make_object_type(span, main_trait_bound, bounds)
 }
 
-pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+pub fn conv_existential_bounds_from_partitioned_bounds(&self,
     rscope: &RegionScope,
     span: Span,
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
@@ -2035,16 +1985,15 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
 
     if !trait_bounds.is_empty() {
         let b = &trait_bounds[0];
-        span_err!(this.tcx().sess, b.trait_ref.path.span, E0225,
+        span_err!(self.tcx().sess, b.trait_ref.path.span, E0225,
                   "only the builtin traits can be used as closure or object bounds");
     }
 
     let region_bound =
-        compute_object_lifetime_bound(this,
-                                      span,
-                                      &region_bounds,
-                                      principal_trait_ref,
-                                      builtin_bounds);
+        self.compute_object_lifetime_bound(span,
+                                           &region_bounds,
+                                           principal_trait_ref,
+                                           builtin_bounds);
 
     let region_bound = match region_bound {
         Some(r) => r,
@@ -2052,7 +2001,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
             match rscope.object_lifetime_default(span) {
                 Some(r) => r,
                 None => {
-                    span_err!(this.tcx().sess, span, E0228,
+                    span_err!(self.tcx().sess, span, E0228,
                               "the lifetime bound for this object type cannot be deduced \
                                from context; please supply an explicit bound");
                     ty::ReStatic
@@ -2070,15 +2019,14 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
 /// (if any) we can use to summarize this type. The basic idea is that we will use the bound the
 /// user provided, if they provided one, and otherwise search the supertypes of trait bounds for
 /// region bounds. It may be that we can derive no bound at all, in which case we return `None`.
-fn compute_object_lifetime_bound<'tcx>(
-    this: &AstConv<'tcx, 'tcx>,
+fn compute_object_lifetime_bound(&self,
     span: Span,
     explicit_region_bounds: &[&hir::Lifetime],
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
     builtin_bounds: ty::BuiltinBounds)
     -> Option<ty::Region> // if None, use the default
 {
-    let tcx = this.tcx();
+    let tcx = self.tcx();
 
     debug!("compute_opt_region_bound(explicit_region_bounds={:?}, \
            principal_trait_ref={:?}, builtin_bounds={:?})",
@@ -2097,7 +2045,7 @@ fn compute_object_lifetime_bound<'tcx>(
         return Some(ast_region_to_region(tcx, r));
     }
 
-    if let Err(ErrorReported) = this.ensure_super_predicates(span,principal_trait_ref.def_id()) {
+    if let Err(ErrorReported) = self.ensure_super_predicates(span,principal_trait_ref.def_id()) {
         return Some(ty::ReStatic);
     }
 
@@ -2128,6 +2076,7 @@ fn compute_object_lifetime_bound<'tcx>(
     }
     return Some(r);
 }
+}
 
 pub struct PartitionedBounds<'a> {
     pub builtin_bounds: ty::BuiltinBounds,
@@ -2137,10 +2086,10 @@ pub struct PartitionedBounds<'a> {
 
 /// Divides a list of bounds from the AST into three groups: builtin bounds (Copy, Sized etc),
 /// general trait bounds, and region bounds.
-pub fn partition_bounds<'a, 'b, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
-                                      _span: Span,
-                                      ast_bounds: &'b [hir::TyParamBound])
-                                      -> PartitionedBounds<'b>
+pub fn partition_bounds<'a, 'b, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                            _span: Span,
+                                            ast_bounds: &'b [hir::TyParamBound])
+                                            -> PartitionedBounds<'b>
 {
     let mut builtin_bounds = ty::BuiltinBounds::empty();
     let mut region_bounds = Vec::new();
@@ -2227,8 +2176,8 @@ pub struct Bounds<'tcx> {
     pub projection_bounds: Vec<ty::PolyProjectionPredicate<'tcx>>,
 }
 
-impl<'a, 'tcx> Bounds<'tcx> {
-    pub fn predicates(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, param_ty: Ty<'tcx>)
+impl<'a, 'gcx, 'tcx> Bounds<'tcx> {
+    pub fn predicates(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>, param_ty: Ty<'tcx>)
                       -> Vec<ty::Predicate<'tcx>>
     {
         let mut vec = Vec::new();
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index 394ecf5fbef..899e4f62cc3 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -16,7 +16,6 @@ use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TypeFoldable, LvaluePreference};
 use check::{FnCtxt, Expectation};
 use lint;
-use require_same_types;
 use util::nodemap::FnvHashMap;
 use session::Session;
 
@@ -56,8 +55,8 @@ fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: b
     }
 }
 
-impl<'a, 'tcx> PatCtxt<'a, 'tcx, 'tcx> {
-pub fn check_pat(&self, pat: &'tcx hir::Pat, expected: Ty<'tcx>) {
+impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
+pub fn check_pat(&self, pat: &'gcx hir::Pat, expected: Ty<'tcx>) {
     let tcx = self.tcx;
 
     debug!("check_pat(pat={:?},expected={:?})", pat, expected);
@@ -133,10 +132,8 @@ pub fn check_pat(&self, pat: &'tcx hir::Pat, expected: Ty<'tcx>) {
             }
 
             // Check that the types of the end-points can be unified.
-            let types_unify = require_same_types(
-                self.ccx, Some(self), pat.span, rhs_ty, lhs_ty,
-                "mismatched types in range",
-            );
+            let types_unify = self.require_same_types(pat.span, rhs_ty, lhs_ty,
+                                                      "mismatched types in range");
 
             // It's ok to return without a message as `require_same_types` prints an error.
             if !types_unify {
@@ -455,11 +452,11 @@ pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::
 }
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 pub fn check_match(&self,
-                   expr: &'tcx hir::Expr,
-                   discrim: &'tcx hir::Expr,
-                   arms: &'tcx [hir::Arm],
+                   expr: &'gcx hir::Expr,
+                   discrim: &'gcx hir::Expr,
+                   arms: &'gcx [hir::Arm],
                    expected: Expectation<'tcx>,
                    match_src: hir::MatchSource) {
     let tcx = self.tcx;
@@ -578,9 +575,9 @@ pub fn check_match(&self,
 }
 }
 
-impl<'a, 'tcx> PatCtxt<'a, 'tcx, 'tcx> {
-pub fn check_pat_struct(&self, pat: &'tcx hir::Pat,
-                        path: &hir::Path, fields: &'tcx [Spanned<hir::FieldPat>],
+impl<'a, 'gcx, 'tcx> PatCtxt<'a, 'gcx, 'tcx> {
+pub fn check_pat_struct(&self, pat: &'gcx hir::Pat,
+                        path: &hir::Path, fields: &'gcx [Spanned<hir::FieldPat>],
                         etc: bool, expected: Ty<'tcx>) {
     let tcx = self.tcx;
 
@@ -617,7 +614,7 @@ pub fn check_pat_struct(&self, pat: &'tcx hir::Pat,
 fn check_pat_enum(&self,
                   pat: &hir::Pat,
                   path: &hir::Path,
-                  subpats: Option<&'tcx [P<hir::Pat>]>,
+                  subpats: Option<&'gcx [P<hir::Pat>]>,
                   expected: Ty<'tcx>,
                   is_tuple_struct_pat: bool)
 {
@@ -764,7 +761,7 @@ fn check_pat_enum(&self,
 /// `etc` is true if the pattern said '...' and false otherwise.
 pub fn check_struct_pat_fields(&self,
                                span: Span,
-                               fields: &'tcx [Spanned<hir::FieldPat>],
+                               fields: &'gcx [Spanned<hir::FieldPat>],
                                variant: ty::VariantDef<'tcx>,
                                substs: &Substs<'tcx>,
                                etc: bool) {
diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs
index fbc5a0b33aa..04b0248ccda 100644
--- a/src/librustc_typeck/check/assoc.rs
+++ b/src/librustc_typeck/check/assoc.rs
@@ -16,12 +16,13 @@ use syntax::ast;
 use syntax::codemap::Span;
 
 //FIXME(@jroesch): Ideally we should be able to drop the fulfillment_cx argument.
-pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx, 'tcx>,
-                                                fulfillment_cx: &mut FulfillmentContext<'tcx>,
-                                                span: Span,
-                                                body_id: ast::NodeId,
-                                                value: &T)
-                                                -> T
+pub fn normalize_associated_types_in<'a, 'gcx, 'tcx, T>(
+    infcx: &InferCtxt<'a, 'gcx, 'tcx>,
+    fulfillment_cx: &mut FulfillmentContext<'tcx>,
+    span: Span,
+    body_id: ast::NodeId,
+    value: &T) -> T
+
     where T : TypeFoldable<'tcx>
 {
     debug!("normalize_associated_types_in(value={:?})", value);
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index a0565a9870c..9de78168fe7 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -63,11 +63,11 @@ enum CallStep<'tcx> {
     Overloaded(ty::MethodCallee<'tcx>)
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 pub fn check_call(&self,
-                  call_expr: &'tcx hir::Expr,
-                  callee_expr: &'tcx hir::Expr,
-                  arg_exprs: &'tcx [P<hir::Expr>],
+                  call_expr: &'gcx hir::Expr,
+                  callee_expr: &'gcx hir::Expr,
+                  arg_exprs: &'gcx [P<hir::Expr>],
                   expected: Expectation<'tcx>)
 {
     self.check_expr(callee_expr);
@@ -104,8 +104,8 @@ pub fn check_call(&self,
 }
 
 fn try_overloaded_call_step(&self,
-                            call_expr: &'tcx hir::Expr,
-                            callee_expr: &'tcx hir::Expr,
+                            call_expr: &'gcx hir::Expr,
+                            callee_expr: &'gcx hir::Expr,
                             adjusted_ty: Ty<'tcx>,
                             autoderefs: usize)
                             -> Option<CallStep<'tcx>>
@@ -205,7 +205,7 @@ fn try_overloaded_call_traits(&self,
 fn confirm_builtin_call(&self,
                         call_expr: &hir::Expr,
                         callee_ty: Ty<'tcx>,
-                        arg_exprs: &'tcx [P<hir::Expr>],
+                        arg_exprs: &'gcx [P<hir::Expr>],
                         expected: Expectation<'tcx>)
 {
     let error_fn_sig;
@@ -275,7 +275,7 @@ fn confirm_builtin_call(&self,
 
 fn confirm_deferred_closure_call(&self,
                                  call_expr: &hir::Expr,
-                                 arg_exprs: &'tcx [P<hir::Expr>],
+                                 arg_exprs: &'gcx [P<hir::Expr>],
                                  expected: Expectation<'tcx>,
                                  fn_sig: ty::FnSig<'tcx>)
 {
@@ -302,8 +302,8 @@ fn confirm_deferred_closure_call(&self,
 
 fn confirm_overloaded_call(&self,
                            call_expr: &hir::Expr,
-                           callee_expr: &'tcx hir::Expr,
-                           arg_exprs: &'tcx [P<hir::Expr>],
+                           callee_expr: &'gcx hir::Expr,
+                           arg_exprs: &'gcx [P<hir::Expr>],
                            expected: Expectation<'tcx>,
                            method_callee: ty::MethodCallee<'tcx>)
 {
@@ -328,17 +328,17 @@ fn write_overloaded_call_method_map(&self,
 }
 
 #[derive(Debug)]
-struct CallResolution<'tcx> {
-    call_expr: &'tcx hir::Expr,
-    callee_expr: &'tcx hir::Expr,
+struct CallResolution<'gcx: 'tcx, 'tcx> {
+    call_expr: &'gcx hir::Expr,
+    callee_expr: &'gcx hir::Expr,
     adjusted_ty: Ty<'tcx>,
     autoderefs: usize,
     fn_sig: ty::FnSig<'tcx>,
     closure_def_id: DefId,
 }
 
-impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
-    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx, 'tcx>) {
+impl<'gcx, 'tcx> DeferredCallResolution<'gcx, 'tcx> for CallResolution<'gcx, 'tcx> {
+    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
         debug!("DeferredCallResolution::resolve() {:?}",
                self);
 
@@ -348,7 +348,7 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
 
         // We may now know enough to figure out fn vs fnmut etc.
         match fcx.try_overloaded_call_traits(self.call_expr, self.callee_expr,
-                                         self.adjusted_ty, self.autoderefs) {
+                                             self.adjusted_ty, self.autoderefs) {
             Some(method_callee) => {
                 // One problem is that when we get here, we are going
                 // to have a newly instantiated function signature
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index ad92c3fb072..bdf26eab20f 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -72,7 +72,7 @@ enum UnsizeKind<'tcx> {
     OfParam(&'tcx ty::ParamTy)
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 /// Returns the kind of unsize information of t, or None
 /// if t is sized or it is unknown.
 fn unsize_kind(&self, t: Ty<'tcx>) -> Option<UnsizeKind<'tcx>> {
@@ -109,8 +109,8 @@ enum CastError {
     NonScalar,
 }
 
-impl<'a, 'tcx> CastCheck<'tcx> {
-    pub fn new(fcx: &FnCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> CastCheck<'tcx> {
+    pub fn new(fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                expr: &'tcx hir::Expr,
                expr_ty: Ty<'tcx>,
                cast_ty: Ty<'tcx>,
@@ -139,7 +139,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         }
     }
 
-    fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>, e: CastError) {
+    fn report_cast_error(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>, e: CastError) {
         match e {
             CastError::NeedViaPtr |
             CastError::NeedViaThinPtr |
@@ -202,7 +202,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         }
     }
 
-    fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) {
+    fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
         if
             self.cast_ty.references_error() ||
             self.expr_ty.references_error()
@@ -256,7 +256,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         err.emit();
     }
 
-    fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) {
+    fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
         let t_cast = self.cast_ty;
         let t_expr = self.expr_ty;
         if t_cast.is_numeric() && t_expr.is_numeric() {
@@ -281,7 +281,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
 
     }
 
-    pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) {
+    pub fn check(mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) {
         self.expr_ty = fcx.structurally_resolved_type(self.span, self.expr_ty);
         self.cast_ty = fcx.structurally_resolved_type(self.span, self.cast_ty);
 
@@ -309,7 +309,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     /// Check a cast, and report an error if one exists. In some cases, this
     /// can return Ok and create type errors in the fcx rather than returning
     /// directly. coercion-cast is handled in check instead of here.
-    fn do_check(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Result<CastKind, CastError> {
+    fn do_check(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Result<CastKind, CastError> {
         use rustc::ty::cast::IntTy::*;
         use rustc::ty::cast::CastTy::*;
 
@@ -376,7 +376,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_ptr_ptr_cast(&self,
-                          fcx: &FnCtxt<'a, 'tcx, 'tcx>,
+                          fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                           m_expr: &'tcx ty::TypeAndMut<'tcx>,
                           m_cast: &'tcx ty::TypeAndMut<'tcx>)
                           -> Result<CastKind, CastError>
@@ -403,7 +403,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_fptr_ptr_cast(&self,
-                           fcx: &FnCtxt<'a, 'tcx, 'tcx>,
+                           fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError>
     {
@@ -417,7 +417,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_ptr_addr_cast(&self,
-                           fcx: &FnCtxt<'a, 'tcx, 'tcx>,
+                           fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                            m_expr: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError>
     {
@@ -431,7 +431,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_ref_cast(&self,
-                      fcx: &FnCtxt<'a, 'tcx, 'tcx>,
+                      fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                       m_expr: &'tcx ty::TypeAndMut<'tcx>,
                       m_cast: &'tcx ty::TypeAndMut<'tcx>)
                       -> Result<CastKind, CastError>
@@ -457,7 +457,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_addr_ptr_cast(&self,
-                           fcx: &FnCtxt<'a, 'tcx, 'tcx>,
+                           fcx: &FnCtxt<'a, 'gcx, 'tcx>,
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError>
     {
@@ -469,13 +469,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         }
     }
 
-    fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> bool {
+    fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> bool {
         fcx.try_coerce(self.expr, self.cast_ty).is_ok()
     }
 
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
     fn type_is_known_to_be_sized(&self,
                                  ty: Ty<'tcx>,
                                  span: Span)
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index c60020f51ae..43c1f9d367e 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -12,19 +12,19 @@
 
 use super::{check_fn, Expectation, FnCtxt};
 
-use astconv;
+use astconv::AstConv;
 use rustc::ty::subst;
 use rustc::ty::{self, ToPolyTraitRef, Ty};
 use std::cmp;
 use syntax::abi::Abi;
 use rustc::hir;
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 pub fn check_expr_closure(&self,
                           expr: &hir::Expr,
                           _capture: hir::CaptureClause,
-                          decl: &'tcx hir::FnDecl,
-                          body: &'tcx hir::Block,
+                          decl: &'gcx hir::FnDecl,
+                          body: &'gcx hir::Block,
                           expected: Expectation<'tcx>) {
     debug!("check_expr_closure(expr={:?},expected={:?})",
            expr,
@@ -43,8 +43,8 @@ pub fn check_expr_closure(&self,
 fn check_closure(&self,
                  expr: &hir::Expr,
                  opt_kind: Option<ty::ClosureKind>,
-                 decl: &'tcx hir::FnDecl,
-                 body: &'tcx hir::Block,
+                 decl: &'gcx hir::FnDecl,
+                 body: &'gcx hir::Block,
                  expected_sig: Option<ty::FnSig<'tcx>>) {
     let expr_def_id = self.tcx.map.local_def_id(expr.id);
 
@@ -52,7 +52,7 @@ fn check_closure(&self,
            opt_kind,
            expected_sig);
 
-    let mut fn_ty = astconv::ty_of_closure(self,
+    let mut fn_ty = AstConv::ty_of_closure(self,
                                            hir::Unsafety::Normal,
                                            decl,
                                            Abi::RustCall,
@@ -68,7 +68,7 @@ fn check_closure(&self,
            expr.id, upvar_tys);
 
     let closure_type = self.tcx.mk_closure(expr_def_id,
-        self.tcx.mk_substs(self.parameter_environment.free_substs.clone()),
+        self.parameter_environment.free_substs,
         upvar_tys);
 
     self.write_ty(expr.id, closure_type);
@@ -76,14 +76,7 @@ fn check_closure(&self,
     let fn_sig = self.tcx.liberate_late_bound_regions(
         self.tcx.region_maps.call_site_extent(expr.id, body.id), &fn_ty.sig);
 
-    check_fn(self.ccx,
-             hir::Unsafety::Normal,
-             expr.id,
-             &fn_sig,
-             decl,
-             expr.id,
-             &body,
-             self);
+    check_fn(self, hir::Unsafety::Normal, expr.id, &fn_sig, decl, expr.id, &body);
 
     // Tuple up the arguments and insert the resulting function type into
     // the `closures` table.
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 1e7a9c5b635..55786a03eeb 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -105,8 +105,8 @@ fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
     }
 }
 
-impl<'f, 'tcx> Coerce<'f, 'tcx, 'tcx> {
-    fn new(fcx: &'f FnCtxt<'f, 'tcx, 'tcx>, origin: TypeOrigin) -> Self {
+impl<'f, 'gcx, 'tcx> Coerce<'f, 'gcx, 'tcx> {
+    fn new(fcx: &'f FnCtxt<'f, 'gcx, 'tcx>, origin: TypeOrigin) -> Self {
         Coerce {
             fcx: fcx,
             origin: origin,
@@ -594,11 +594,11 @@ impl<'f, 'tcx> Coerce<'f, 'tcx, 'tcx> {
     }
 }
 
-fn apply<'a, 'b, 'tcx, E, I>(coerce: &mut Coerce<'a, 'tcx, 'tcx>,
-                             exprs: &E,
-                             a: Ty<'tcx>,
-                             b: Ty<'tcx>)
-                             -> CoerceResult<'tcx>
+fn apply<'a, 'b, 'gcx, 'tcx, E, I>(coerce: &mut Coerce<'a, 'gcx, 'tcx>,
+                                   exprs: &E,
+                                   a: Ty<'tcx>,
+                                   b: Ty<'tcx>)
+                                   -> CoerceResult<'tcx>
     where E: Fn() -> I,
           I: IntoIterator<Item=&'b hir::Expr> {
 
@@ -617,7 +617,7 @@ fn apply<'a, 'b, 'tcx, E, I>(coerce: &mut Coerce<'a, 'tcx, 'tcx>,
     Ok((ty, adjustment))
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 /// Attempt to coerce an expression to a type, and return the
 /// adjusted type of the expression, if successful.
 /// Adjustments are only recorded if the coercion succeeded.
diff --git a/src/librustc_typeck/check/demand.rs b/src/librustc_typeck/check/demand.rs
index 4f4b7fa9ef7..065425c86c7 100644
--- a/src/librustc_typeck/check/demand.rs
+++ b/src/librustc_typeck/check/demand.rs
@@ -16,7 +16,7 @@ use rustc::infer::{InferOk, TypeOrigin};
 use syntax::codemap::Span;
 use rustc::hir;
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 // Requires that the two types unify, and prints an error message if
 // they don't.
 pub fn demand_suptype(&self, sp: Span, expected: Ty<'tcx>, actual: Ty<'tcx>) {
@@ -54,4 +54,16 @@ pub fn demand_coerce(&self, expr: &hir::Expr, expected: Ty<'tcx>) {
         self.report_mismatched_types(origin, expected, expr_ty, e);
     }
 }
+
+pub fn require_same_types(&self, span: Span, t1: Ty<'tcx>, t2: Ty<'tcx>, msg: &str)
+                          -> bool {
+    if let Err(err) = self.eq_types(false, TypeOrigin::Misc(span), t1, t2) {
+        let found_ty = self.resolve_type_vars_if_possible(&t1);
+        let expected_ty = self.resolve_type_vars_if_possible(&t2);
+        ::emit_type_err(self.tcx, span, found_ty, expected_ty, &err, msg);
+        false
+    } else {
+        true
+    }
+}
 }
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index c5e7606106f..862dae4bb33 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -16,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};
+use rustc::ty::{self, Ty, TyCtxt};
 use rustc::traits::{self, ProjectionMode};
 use util::nodemap::FnvHashSet;
 
@@ -274,10 +274,12 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'a, 'tcx>(
 /// ensuring that they do not access data nor invoke methods of
 /// values that have been previously dropped).
 ///
-pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut RegionCtxt<'a, 'tcx, 'tcx>,
-                                                         typ: ty::Ty<'tcx>,
-                                                         span: Span,
-                                                         scope: region::CodeExtent) {
+pub fn check_safety_of_destructor_if_necessary<'a, 'gcx, 'tcx>(
+    rcx: &mut RegionCtxt<'a, 'gcx, 'tcx>,
+    typ: ty::Ty<'tcx>,
+    span: Span,
+    scope: region::CodeExtent)
+{
     debug!("check_safety_of_destructor_if_necessary typ: {:?} scope: {:?}",
            typ, scope);
 
@@ -354,8 +356,8 @@ struct DropckContext<'a, 'b: 'a, 'gcx: 'b+'tcx, 'tcx: 'b> {
 }
 
 // `context` is used for reporting overflow errors
-fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
-    cx: &mut DropckContext<'a, 'b, 'tcx, 'tcx>,
+fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'gcx, 'tcx>(
+    cx: &mut DropckContext<'a, 'b, 'gcx, 'tcx>,
     context: TypeContext,
     ty: Ty<'tcx>,
     depth: usize) -> Result<(), Error<'tcx>>
@@ -410,7 +412,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(cx, ty) {
+    if has_dtor_of_interest(tcx, ty) {
         debug!("iterate_over_potentially_unsafe_regions_in_type \
                 {}ty: {} - is a dtorck type!",
                (0..depth).map(|_| ' ').collect::<String>(),
@@ -500,11 +502,11 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
     }
 }
 
-fn has_dtor_of_interest<'a, 'b, 'tcx>(cx: &DropckContext<'a, 'b, 'tcx, 'tcx>,
-                                      ty: ty::Ty<'tcx>) -> bool {
+fn has_dtor_of_interest<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                        ty: Ty<'tcx>) -> bool {
     match ty.sty {
         ty::TyEnum(def, _) | ty::TyStruct(def, _) => {
-            def.is_dtorck(cx.rcx.tcx)
+            def.is_dtorck(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 6243d191dcb..c02139140ae 100644
--- a/src/librustc_typeck/check/intrinsic.rs
+++ b/src/librustc_typeck/check/intrinsic.rs
@@ -56,7 +56,6 @@ fn equate_intrinsic_type<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
              i_n_tps, n_tps);
     } else {
         require_same_types(ccx,
-                           None,
                            it.span,
                            i_ty.ty,
                            fty,
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index 47098599df2..3360f9dab78 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -52,11 +52,11 @@ struct InstantiatedMethodSig<'tcx> {
     method_predicates: ty::InstantiatedPredicates<'tcx>,
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 pub fn confirm_method(&self,
                       span: Span,
-                      self_expr: &'tcx hir::Expr,
-                      call_expr: &'tcx hir::Expr,
+                      self_expr: &'gcx hir::Expr,
+                      call_expr: &'gcx hir::Expr,
                       unadjusted_self_ty: Ty<'tcx>,
                       pick: probe::Pick<'tcx>,
                       supplied_method_types: Vec<Ty<'tcx>>)
@@ -72,12 +72,12 @@ pub fn confirm_method(&self,
 }
 }
 
-impl<'a,'tcx> ConfirmContext<'a,'tcx, 'tcx> {
-    fn new(fcx: &'a FnCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> ConfirmContext<'a, 'gcx, 'tcx> {
+    fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
            span: Span,
-           self_expr: &'tcx hir::Expr,
-           call_expr: &'tcx hir::Expr)
-           -> ConfirmContext<'a, 'tcx, 'tcx>
+           self_expr: &'gcx hir::Expr,
+           call_expr: &'gcx hir::Expr)
+           -> ConfirmContext<'a, 'gcx, 'tcx>
     {
         ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
     }
@@ -286,7 +286,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx, 'tcx> {
     }
 
     fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
-        F: FnMut(&mut ConfirmContext<'a, 'tcx, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R,
+        F: FnMut(&mut ConfirmContext<'a, 'gcx, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R,
     {
         // If we specified that this is an object method, then the
         // self-type ought to be something that can be dereferenced to
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 8d6cc217b8b..f30abbaba0e 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -78,7 +78,7 @@ pub enum CandidateSource {
     TraitSource(/* trait id */ DefId),
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 /// Determines whether the type `self_ty` supports a method name `method_name` or not.
 pub fn method_exists(&self,
                      span: Span,
@@ -116,8 +116,8 @@ pub fn lookup_method(&self,
                      method_name: ast::Name,
                      self_ty: ty::Ty<'tcx>,
                      supplied_method_types: Vec<ty::Ty<'tcx>>,
-                     call_expr: &'tcx hir::Expr,
-                     self_expr: &'tcx hir::Expr)
+                     call_expr: &'gcx hir::Expr,
+                     self_expr: &'gcx hir::Expr)
                      -> Result<ty::MethodCallee<'tcx>, MethodError<'tcx>>
 {
     debug!("lookup(method_name={}, self_ty={:?}, call_expr={:?}, self_expr={:?})",
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 6ee309516a0..8ce92892e9a 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -136,7 +136,7 @@ pub enum Mode {
     Path
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 pub fn probe_method(&self,
                     span: Span,
                     mode: Mode,
@@ -241,14 +241,14 @@ fn create_steps(&self,
 }
 }
 
-impl<'a,'tcx> ProbeContext<'a,'tcx, 'tcx> {
-    fn new(fcx: &'a FnCtxt<'a,'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> ProbeContext<'a, 'gcx, 'tcx> {
+    fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
            span: Span,
            mode: Mode,
            item_name: ast::Name,
            steps: Vec<CandidateStep<'tcx>>,
            opt_simplified_steps: Option<Vec<ty::fast_reject::SimplifiedType>>)
-           -> ProbeContext<'a,'tcx, 'tcx>
+           -> ProbeContext<'a, 'gcx, 'tcx>
     {
         ProbeContext {
             fcx: fcx,
@@ -554,7 +554,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx, 'tcx> {
         mut mk_cand: F,
     ) where
         F: for<'b> FnMut(
-            &mut ProbeContext<'b, 'tcx, 'tcx>,
+            &mut ProbeContext<'b, 'gcx, 'tcx>,
             ty::PolyTraitRef<'tcx>,
             ty::ImplOrTraitItem<'tcx>,
         ),
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index 897a588bb62..ed60f9b6e7c 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -39,7 +39,7 @@ use std::cmp::Ordering;
 use super::{MethodError, NoMatchData, CandidateSource};
 use super::probe::Mode;
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 fn is_fn_ty(&self, ty: &Ty<'tcx>, span: Span) -> bool {
     let tcx = self.tcx;
     match ty.sty {
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index edaac66763c..9e771d95bbd 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -80,7 +80,7 @@ pub use self::Expectation::*;
 pub use self::compare_method::{compare_impl_method, compare_const_impl};
 use self::TupleArgumentsFlag::*;
 
-use astconv::{self, ast_region_to_region, ast_ty_to_ty, AstConv, PathParamMode};
+use astconv::{AstConv, ast_region_to_region, PathParamMode};
 use check::_match::PatCtxt;
 use dep_graph::DepNode;
 use fmt_macros::{Parser, Piece, Position};
@@ -168,7 +168,7 @@ pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     // decision. We keep these deferred resolutions grouped by the
     // def-id of the closure, so that once we decide, we can easily go
     // back and process them.
-    deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'tcx>>>>,
+    deferred_call_resolutions: RefCell<DefIdMap<Vec<DeferredCallResolutionHandler<'gcx, 'tcx>>>>,
 
     deferred_cast_checks: RefCell<Vec<cast::CastCheck<'tcx>>>,
 }
@@ -180,11 +180,11 @@ impl<'a, 'gcx, 'tcx> Deref for Inherited<'a, 'gcx, 'tcx> {
     }
 }
 
-trait DeferredCallResolution<'tcx> {
-    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx, 'tcx>);
+trait DeferredCallResolution<'gcx, 'tcx> {
+    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a, 'gcx, 'tcx>);
 }
 
-type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
+type DeferredCallResolutionHandler<'gcx, 'tcx> = Box<DeferredCallResolution<'gcx, 'tcx>+'tcx>;
 
 /// When type-checking an expression, we propagate downward
 /// whatever type hint we are able in the form of an `Expectation`.
@@ -204,7 +204,7 @@ pub enum Expectation<'tcx> {
     ExpectRvalueLikeUnsized(Ty<'tcx>),
 }
 
-impl<'a, 'tcx> Expectation<'tcx> {
+impl<'a, 'gcx, 'tcx> Expectation<'tcx> {
     // Disregard "castable to" expectations because they
     // can lead us astray. Consider for example `if cond
     // {22} else {c} as u8` -- if we propagate the
@@ -221,7 +221,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
     // an expected type. Otherwise, we might write parts of the type
     // when checking the 'then' block which are incompatible with the
     // 'else' branch.
-    fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Expectation<'tcx> {
+    fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> {
         match *self {
             ExpectHasType(ety) => {
                 let ety = fcx.shallow_resolve(ety);
@@ -257,7 +257,7 @@ impl<'a, '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(fcx: &FnCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
+    fn rvalue_hint(fcx: &FnCtxt<'a, 'gcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
         match fcx.tcx.struct_tail(ty).sty {
             ty::TySlice(_) | ty::TyStr | ty::TyTrait(..) => {
                 ExpectRvalueLikeUnsized(ty)
@@ -269,7 +269,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
     // Resolves `expected` by a single level if it is a variable. If
     // there is no expected type or resolution is not possible (e.g.,
     // no constraints yet present), just returns `None`.
-    fn resolve(self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Expectation<'tcx> {
+    fn resolve(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Expectation<'tcx> {
         match self {
             NoExpectation => {
                 NoExpectation
@@ -286,7 +286,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
         }
     }
 
-    fn to_option(self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Option<Ty<'tcx>> {
+    fn to_option(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
         match self.resolve(fcx) {
             NoExpectation => None,
             ExpectCastableToType(ty) |
@@ -295,7 +295,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
         }
     }
 
-    fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Option<Ty<'tcx>> {
+    fn only_has_type(self, fcx: &FnCtxt<'a, 'gcx, 'tcx>) -> Option<Ty<'tcx>> {
         match self.resolve(fcx) {
             ExpectHasType(ty) => Some(ty),
             _ => None
@@ -372,7 +372,7 @@ impl<'a, 'gcx, 'tcx> Deref for FnCtxt<'a, 'gcx, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Inherited<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> Inherited<'a, 'gcx, 'tcx> {
     fn enter<F, R>(ccx: &'a CrateCtxt<'a, 'tcx>,
                    param_env: ty::ParameterEnvironment<'tcx>,
                    f: F) -> R
@@ -493,16 +493,15 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 
     Inherited::enter(ccx, param_env, |inh| {
         // Compute the fty from point of view of inside fn.
-        let fn_scope = ccx.tcx.region_maps.call_site_extent(fn_id, body.id);
+        let fn_scope = inh.tcx.region_maps.call_site_extent(fn_id, body.id);
         let fn_sig =
-            fn_ty.sig.subst(ccx.tcx, &inh.parameter_environment.free_substs);
+            fn_ty.sig.subst(inh.tcx, &inh.parameter_environment.free_substs);
         let fn_sig =
-            ccx.tcx.liberate_late_bound_regions(fn_scope, &fn_sig);
+            inh.tcx.liberate_late_bound_regions(fn_scope, &fn_sig);
         let fn_sig =
             inh.normalize_associated_types_in(body.span, body.id, &fn_sig);
 
-        let fcx = check_fn(ccx, fn_ty.unsafety, fn_id, &fn_sig,
-                           decl, fn_id, body, &inh);
+        let fcx = check_fn(&inh, fn_ty.unsafety, fn_id, &fn_sig, decl, fn_id, body);
 
         fcx.select_all_obligations_and_apply_defaults();
         fcx.closure_analyze_fn(body);
@@ -519,7 +518,7 @@ struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     fcx: &'a FnCtxt<'a, 'gcx, 'tcx>
 }
 
-impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> GatherLocalsVisitor<'a, 'gcx, 'tcx> {
     fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
         match ty_opt {
             None => {
@@ -537,9 +536,9 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> Visitor<'gcx> for GatherLocalsVisitor<'a, 'gcx, 'tcx> {
     // Add explicitly-declared locals.
-    fn visit_local(&mut self, local: &'tcx hir::Local) {
+    fn visit_local(&mut self, local: &'gcx hir::Local) {
         let o_ty = match local.ty {
             Some(ref ty) => Some(self.fcx.to_ty(&ty)),
             None => None
@@ -553,7 +552,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx, 'tcx> {
     }
 
     // Add pattern bindings.
-    fn visit_pat(&mut self, p: &'tcx hir::Pat) {
+    fn visit_pat(&mut self, p: &'gcx hir::Pat) {
         if let PatKind::Ident(_, ref path1, _) = p.node {
             if pat_util::pat_is_binding(&self.fcx.tcx.def_map.borrow(), p) {
                 let var_ty = self.assign(p.span, p.id, None);
@@ -571,7 +570,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx, 'tcx> {
         intravisit::walk_pat(self, p);
     }
 
-    fn visit_block(&mut self, b: &'tcx hir::Block) {
+    fn visit_block(&mut self, b: &'gcx hir::Block) {
         // non-obvious: the `blk` variable maps to region lb, so
         // we have to keep this up-to-date.  This
         // is... unfortunate.  It'd be nice to not need this.
@@ -580,7 +579,7 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx, 'tcx> {
 
     // Since an expr occurs as part of the type fixed size arrays we
     // need to record the type for that node
-    fn visit_ty(&mut self, t: &'tcx hir::Ty) {
+    fn visit_ty(&mut self, t: &'gcx hir::Ty) {
         match t.node {
             hir::TyFixedLengthVec(ref ty, ref count_expr) => {
                 self.visit_ty(&ty);
@@ -595,8 +594,8 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx, 'tcx> {
     }
 
     // Don't descend into the bodies of nested closures
-    fn visit_fn(&mut self, _: intravisit::FnKind<'tcx>, _: &'tcx hir::FnDecl,
-                _: &'tcx hir::Block, _: Span, _: ast::NodeId) { }
+    fn visit_fn(&mut self, _: intravisit::FnKind<'gcx>, _: &'gcx hir::FnDecl,
+                _: &'gcx hir::Block, _: Span, _: ast::NodeId) { }
 }
 
 /// Helper used by check_bare_fn and check_expr_fn. Does the grungy work of checking a function
@@ -605,17 +604,16 @@ impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx, 'tcx> {
 ///
 /// * ...
 /// * inherited: other fields inherited from the enclosing fn (if any)
-fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
-                      unsafety: hir::Unsafety,
-                      unsafety_id: ast::NodeId,
-                      fn_sig: &ty::FnSig<'tcx>,
-                      decl: &'tcx hir::FnDecl,
-                      fn_id: ast::NodeId,
-                      body: &'tcx hir::Block,
-                      inherited: &'a Inherited<'a, 'tcx, 'tcx>)
-                      -> FnCtxt<'a, 'tcx, 'tcx>
+fn check_fn<'a, 'gcx, 'tcx>(inherited: &'a Inherited<'a, 'gcx, 'tcx>,
+                            unsafety: hir::Unsafety,
+                            unsafety_id: ast::NodeId,
+                            fn_sig: &ty::FnSig<'tcx>,
+                            decl: &'gcx hir::FnDecl,
+                            fn_id: ast::NodeId,
+                            body: &'gcx hir::Block)
+                            -> FnCtxt<'a, 'gcx, 'tcx>
 {
-    let tcx = ccx.tcx;
+    let tcx = inherited.tcx;
 
     let arg_tys = &fn_sig.inputs;
     let ret_ty = fn_sig.output;
@@ -1244,8 +1242,8 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     check_representable(ccx.tcx, sp, id, "enum");
 }
 
-impl<'a, 'tcx> AstConv<'tcx, 'tcx> for FnCtxt<'a, 'tcx, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx }
+impl<'a, 'gcx, 'tcx> AstConv<'gcx, 'tcx> for FnCtxt<'a, 'gcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'gcx, 'tcx> { self.tcx }
 
     fn get_item_type_scheme(&self, _: Span, id: DefId)
                             -> Result<ty::TypeScheme<'tcx>, ErrorReported>
@@ -1356,7 +1354,7 @@ impl<'a, 'tcx> AstConv<'tcx, 'tcx> for FnCtxt<'a, 'tcx, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> RegionScope for FnCtxt<'a, 'gcx, 'tcx> {
     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
         Some(self.base_object_lifetime_default(span))
     }
@@ -1413,11 +1411,11 @@ enum TupleArgumentsFlag {
     TupleArguments,
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
-    pub fn new(inh: &'a Inherited<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
+    pub fn new(inh: &'a Inherited<'a, 'gcx, 'tcx>,
                rty: ty::FnOutput<'tcx>,
                body_id: ast::NodeId)
-               -> FnCtxt<'a, 'tcx, 'tcx> {
+               -> FnCtxt<'a, 'gcx, 'tcx> {
         FnCtxt {
             body_id: body_id,
             writeback_errors: Cell::new(false),
@@ -1473,14 +1471,14 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 
     fn record_deferred_call_resolution(&self,
                                        closure_def_id: DefId,
-                                       r: DeferredCallResolutionHandler<'tcx>) {
+                                       r: DeferredCallResolutionHandler<'gcx, 'tcx>) {
         let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut();
         deferred_call_resolutions.entry(closure_def_id).or_insert(vec![]).push(r);
     }
 
     fn remove_deferred_call_resolutions(&self,
                                         closure_def_id: DefId)
-                                        -> Vec<DeferredCallResolutionHandler<'tcx>>
+                                        -> Vec<DeferredCallResolutionHandler<'gcx, 'tcx>>
     {
         let mut deferred_call_resolutions = self.deferred_call_resolutions.borrow_mut();
         deferred_call_resolutions.remove(&closure_def_id).unwrap_or(Vec::new())
@@ -1619,7 +1617,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
             self.tcx.lookup_item_type(did);
         let type_predicates =
             self.tcx.lookup_predicates(did);
-        let substs = astconv::ast_path_substs_for_ty(self, self,
+        let substs = AstConv::ast_path_substs_for_ty(self, self,
                                                      path.span,
                                                      PathParamMode::Optional,
                                                      &type_scheme.generics,
@@ -1723,7 +1721,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
     }
 
     pub fn to_ty(&self, ast_t: &hir::Ty) -> Ty<'tcx> {
-        let t = ast_ty_to_ty(self, self, ast_t);
+        let t = AstConv::ast_ty_to_ty(self, self, ast_t);
         self.register_wf_obligation(t, ast_t.span, traits::MiscObligation);
         t
     }
@@ -2325,7 +2323,7 @@ fn make_overloaded_lvalue_return_type(&self,
 
 fn lookup_indexing(&self,
                    expr: &hir::Expr,
-                   base_expr: &'tcx hir::Expr,
+                   base_expr: &'gcx hir::Expr,
                    base_ty: Ty<'tcx>,
                    idx_ty: Ty<'tcx>,
                    lvalue_pref: LvaluePreference)
@@ -2367,7 +2365,7 @@ fn lookup_indexing(&self,
 fn try_index_step(&self,
                   method_call: MethodCall,
                   expr: &hir::Expr,
-                  base_expr: &'tcx hir::Expr,
+                  base_expr: &'gcx hir::Expr,
                   adjusted_ty: Ty<'tcx>,
                   autoderefs: usize,
                   unsize: bool,
@@ -2442,8 +2440,8 @@ fn try_index_step(&self,
 fn check_method_argument_types(&self,
                                sp: Span,
                                method_fn_ty: Ty<'tcx>,
-                               callee_expr: &'tcx hir::Expr,
-                               args_no_rcvr: &'tcx [P<hir::Expr>],
+                               callee_expr: &'gcx hir::Expr,
+                               args_no_rcvr: &'gcx [P<hir::Expr>],
                                tuple_arguments: TupleArgumentsFlag,
                                expected: Expectation<'tcx>)
                                -> ty::FnOutput<'tcx> {
@@ -2482,7 +2480,7 @@ fn check_argument_types(&self,
                         sp: Span,
                         fn_inputs: &[Ty<'tcx>],
                         expected_arg_tys: &[Ty<'tcx>],
-                        args: &'tcx [P<hir::Expr>],
+                        args: &'gcx [P<hir::Expr>],
                         variadic: bool,
                         tuple_arguments: TupleArgumentsFlag) {
     let tcx = self.tcx;
@@ -2756,42 +2754,42 @@ fn check_lit(&self,
 }
 
 fn check_expr_eq_type(&self,
-                      expr: &'tcx hir::Expr,
+                      expr: &'gcx hir::Expr,
                       expected: Ty<'tcx>) {
     self.check_expr_with_hint(expr, expected);
     self.demand_eqtype(expr.span, expected, self.expr_ty(expr));
 }
 
 pub fn check_expr_has_type(&self,
-                           expr: &'tcx hir::Expr,
+                           expr: &'gcx hir::Expr,
                            expected: Ty<'tcx>) {
     self.check_expr_with_hint(expr, expected);
     self.demand_suptype(expr.span, expected, self.expr_ty(expr));
 }
 
 fn check_expr_coercable_to_type(&self,
-                                expr: &'tcx hir::Expr,
+                                expr: &'gcx hir::Expr,
                                 expected: Ty<'tcx>) {
     self.check_expr_with_hint(expr, expected);
     self.demand_coerce(expr, expected);
 }
 
-fn check_expr_with_hint(&self, expr: &'tcx hir::Expr,
+fn check_expr_with_hint(&self, expr: &'gcx hir::Expr,
                         expected: Ty<'tcx>) {
     self.check_expr_with_expectation(expr, ExpectHasType(expected))
 }
 
 fn check_expr_with_expectation(&self,
-                               expr: &'tcx hir::Expr,
+                               expr: &'gcx hir::Expr,
                                expected: Expectation<'tcx>) {
     self.check_expr_with_expectation_and_lvalue_pref(expr, expected, NoPreference)
 }
 
-fn check_expr(&self, expr: &'tcx hir::Expr)  {
+fn check_expr(&self, expr: &'gcx hir::Expr)  {
     self.check_expr_with_expectation(expr, NoExpectation)
 }
 
-fn check_expr_with_lvalue_pref(&self, expr: &'tcx hir::Expr,
+fn check_expr_with_lvalue_pref(&self, expr: &'gcx hir::Expr,
                                lvalue_pref: LvaluePreference)  {
     self.check_expr_with_expectation_and_lvalue_pref(expr, NoExpectation, lvalue_pref)
 }
@@ -2867,9 +2865,9 @@ fn expected_types_for_fn_args(&self,
 
     // Checks a method call.
     fn check_method_call(&self,
-                         expr: &'tcx hir::Expr,
+                         expr: &'gcx hir::Expr,
                          method_name: Spanned<ast::Name>,
-                         args: &'tcx [P<hir::Expr>],
+                         args: &'gcx [P<hir::Expr>],
                          tps: &[P<hir::Ty>],
                          expected: Expectation<'tcx>,
                          lvalue_pref: LvaluePreference) {
@@ -2914,9 +2912,9 @@ fn expected_types_for_fn_args(&self,
     // A generic function for checking the then and else in an if
     // or if-else.
     fn check_then_else(&self,
-                       cond_expr: &'tcx hir::Expr,
-                       then_blk: &'tcx hir::Block,
-                       opt_else_expr: Option<&'tcx hir::Expr>,
+                       cond_expr: &'gcx hir::Expr,
+                       then_blk: &'gcx hir::Block,
+                       opt_else_expr: Option<&'gcx hir::Expr>,
                        id: ast::NodeId,
                        sp: Span,
                        expected: Expectation<'tcx>) {
@@ -2989,9 +2987,9 @@ fn expected_types_for_fn_args(&self,
 
     // Check field access expressions
     fn check_field(&self,
-                   expr: &'tcx hir::Expr,
+                   expr: &'gcx hir::Expr,
                    lvalue_pref: LvaluePreference,
-                   base: &'tcx hir::Expr,
+                   base: &'gcx hir::Expr,
                    field: &Spanned<ast::Name>) {
         self.check_expr_with_lvalue_pref(base, lvalue_pref);
         let expr_t = self.structurally_resolved_type(expr.span,
@@ -3080,9 +3078,9 @@ fn expected_types_for_fn_args(&self,
 
     // Check tuple index expressions
     fn check_tup_field(&self,
-                       expr: &'tcx hir::Expr,
+                       expr: &'gcx hir::Expr,
                        lvalue_pref: LvaluePreference,
-                       base: &'tcx hir::Expr,
+                       base: &'gcx hir::Expr,
                        idx: codemap::Spanned<usize>) {
         self.check_expr_with_lvalue_pref(base, lvalue_pref);
         let expr_t = self.structurally_resolved_type(expr.span,
@@ -3180,7 +3178,7 @@ fn expected_types_for_fn_args(&self,
                                 adt_ty: Ty<'tcx>,
                                 span: Span,
                                 variant: ty::VariantDef<'tcx>,
-                                ast_fields: &'tcx [hir::Field],
+                                ast_fields: &'gcx [hir::Field],
                                 check_completeness: bool) {
         let tcx = self.tcx;
         let substs = match adt_ty.sty {
@@ -3237,8 +3235,8 @@ fn expected_types_for_fn_args(&self,
 
     fn check_struct_fields_on_error(&self,
                                     id: ast::NodeId,
-                                    fields: &'tcx [hir::Field],
-                                    base_expr: &'tcx Option<P<hir::Expr>>) {
+                                    fields: &'gcx [hir::Field],
+                                    base_expr: &'gcx Option<P<hir::Expr>>) {
         // Make sure to still write the types
         // otherwise we might ICE
         self.write_error(id);
@@ -3254,8 +3252,8 @@ fn expected_types_for_fn_args(&self,
     fn check_expr_struct(&self,
                          expr: &hir::Expr,
                          path: &hir::Path,
-                         fields: &'tcx [hir::Field],
-                         base_expr: &'tcx Option<P<hir::Expr>>)
+                         fields: &'gcx [hir::Field],
+                         base_expr: &'gcx Option<P<hir::Expr>>)
     {
         let tcx = self.tcx;
 
@@ -3315,7 +3313,7 @@ fn expected_types_for_fn_args(&self,
 /// that there are actually multiple representations for `TyError`, so avoid
 /// that when err needs to be handled differently.
 fn check_expr_with_expectation_and_lvalue_pref(&self,
-                                               expr: &'tcx hir::Expr,
+                                               expr: &'gcx hir::Expr,
                                                expected: Expectation<'tcx>,
                                                lvalue_pref: LvaluePreference) {
     debug!(">> typechecking: expr={:?} expected={:?}",
@@ -3666,7 +3664,7 @@ fn check_expr_with_expectation_and_lvalue_pref(&self,
       }
       hir::ExprRepeat(ref element, ref count_expr) => {
         self.check_expr_has_type(&count_expr, tcx.types.usize);
-        let count = eval_repeat_count(self.tcx, &count_expr);
+        let count = eval_repeat_count(self.tcx.global_tcx(), &count_expr);
 
         let uty = match expected {
             ExpectHasType(uty) => {
@@ -3827,7 +3825,7 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
         let mut def = path_res.base_def;
         let ty_segments = path.segments.split_last().unwrap().1;
         let base_ty_end = path.segments.len() - path_res.depth;
-        let ty = astconv::finish_resolving_def_to_ty(self, self, span,
+        let ty = AstConv::finish_resolving_def_to_ty(self, self, span,
                                                      PathParamMode::Optional,
                                                      &mut def,
                                                      opt_self_ty,
@@ -3864,8 +3862,8 @@ pub fn resolve_ty_and_def_ufcs<'b>(&self,
 }
 
 pub fn check_decl_initializer(&self,
-                              local: &'tcx hir::Local,
-                              init: &'tcx hir::Expr)
+                              local: &'gcx hir::Local,
+                              init: &'gcx hir::Expr)
 {
     let ref_bindings = self.tcx.pat_contains_ref_binding(&local.pat);
 
@@ -3887,7 +3885,7 @@ pub fn check_decl_initializer(&self,
     };
 }
 
-pub fn check_decl_local(&self, local: &'tcx hir::Local)  {
+pub fn check_decl_local(&self, local: &'gcx hir::Local)  {
     let tcx = self.tcx;
 
     let t = self.local_ty(local.span, local.id);
@@ -3912,7 +3910,7 @@ pub fn check_decl_local(&self, local: &'tcx hir::Local)  {
     }
 }
 
-pub fn check_stmt(&self, stmt: &'tcx hir::Stmt)  {
+pub fn check_stmt(&self, stmt: &'gcx hir::Stmt)  {
     let node_id;
     let mut saw_bot = false;
     let mut saw_err = false;
@@ -3956,7 +3954,7 @@ pub fn check_stmt(&self, stmt: &'tcx hir::Stmt)  {
     }
 }
 
-pub fn check_block_no_value(&self, blk: &'tcx hir::Block)  {
+pub fn check_block_no_value(&self, blk: &'gcx hir::Block)  {
     self.check_block_with_expected(blk, ExpectHasType(self.tcx.mk_nil()));
     let blkty = self.node_ty(blk.id);
     if blkty.references_error() {
@@ -3968,7 +3966,7 @@ pub fn check_block_no_value(&self, blk: &'tcx hir::Block)  {
 }
 
 fn check_block_with_expected(&self,
-                             blk: &'tcx hir::Block,
+                             blk: &'gcx hir::Block,
                              expected: Expectation<'tcx>) {
     let prev = {
         let mut fcx_ps = self.ps.borrow_mut();
@@ -4047,7 +4045,7 @@ fn check_block_with_expected(&self,
 
 fn check_const_with_ty(&self,
                        _: Span,
-                       e: &'tcx hir::Expr,
+                       e: &'gcx hir::Expr,
                        declty: Ty<'tcx>) {
     // Gather locals in statics (because of block expressions).
     // This is technically unnecessary because locals in static items are forbidden,
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index 9b3823774f7..3986b866033 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -17,13 +17,13 @@ use syntax::ast;
 use syntax::parse::token;
 use rustc::hir;
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 /// Check a `a <op>= b`
 pub fn check_binop_assign(&self,
-                          expr: &'tcx hir::Expr,
+                          expr: &'gcx hir::Expr,
                           op: hir::BinOp,
-                          lhs_expr: &'tcx hir::Expr,
-                          rhs_expr: &'tcx hir::Expr)
+                          lhs_expr: &'gcx hir::Expr,
+                          rhs_expr: &'gcx hir::Expr)
 {
     self.check_expr_with_lvalue_pref(lhs_expr, PreferMutLvalue);
 
@@ -47,10 +47,10 @@ pub fn check_binop_assign(&self,
 
 /// Check a potentially overloaded binary operator.
 pub fn check_binop(&self,
-                   expr: &'tcx hir::Expr,
+                   expr: &'gcx hir::Expr,
                    op: hir::BinOp,
-                   lhs_expr: &'tcx hir::Expr,
-                   rhs_expr: &'tcx hir::Expr)
+                   lhs_expr: &'gcx hir::Expr,
+                   rhs_expr: &'gcx hir::Expr)
 {
     let tcx = self.tcx;
 
@@ -106,9 +106,9 @@ pub fn check_binop(&self,
 }
 
 fn enforce_builtin_binop_types(&self,
-                               lhs_expr: &'tcx hir::Expr,
+                               lhs_expr: &'gcx hir::Expr,
                                lhs_ty: Ty<'tcx>,
-                               rhs_expr: &'tcx hir::Expr,
+                               rhs_expr: &'gcx hir::Expr,
                                rhs_ty: Ty<'tcx>,
                                op: hir::BinOp)
                                -> Ty<'tcx>
@@ -144,10 +144,10 @@ fn enforce_builtin_binop_types(&self,
 }
 
 fn check_overloaded_binop(&self,
-                          expr: &'tcx hir::Expr,
-                          lhs_expr: &'tcx hir::Expr,
+                          expr: &'gcx hir::Expr,
+                          lhs_expr: &'gcx hir::Expr,
                           lhs_ty: Ty<'tcx>,
-                          rhs_expr: &'tcx hir::Expr,
+                          rhs_expr: &'gcx hir::Expr,
                           op: hir::BinOp,
                           is_assign: IsAssign)
                           -> (Ty<'tcx>, Ty<'tcx>)
@@ -222,8 +222,8 @@ pub fn check_user_unop(&self,
                        op_str: &str,
                        mname: &str,
                        trait_did: Option<DefId>,
-                       ex: &'tcx hir::Expr,
-                       operand_expr: &'tcx hir::Expr,
+                       ex: &'gcx hir::Expr,
+                       operand_expr: &'gcx hir::Expr,
                        operand_ty: Ty<'tcx>,
                        op: hir::UnOp)
                        -> Ty<'tcx>
@@ -294,7 +294,7 @@ fn name_and_trait_def_id(&self,
 }
 
 fn lookup_op_method(&self,
-                    expr: &'tcx hir::Expr,
+                    expr: &'gcx hir::Expr,
                     lhs_ty: Ty<'tcx>,
                     other_tys: Vec<Ty<'tcx>>,
                     opname: ast::Name,
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index b65fcbac8d4..931f77951eb 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -113,7 +113,7 @@ macro_rules! ignore_err {
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 pub fn regionck_expr(&self, e: &hir::Expr) {
     let mut rcx = RegionCtxt::new(self, RepeatingScope(e.id), e.id, Subject(e.id));
     if self.err_count_since_creation() == 0 {
@@ -198,11 +198,11 @@ impl<'a, 'gcx, 'tcx> Deref for RegionCtxt<'a, 'gcx, 'tcx> {
 pub struct RepeatingScope(ast::NodeId);
 pub enum SubjectNode { Subject(ast::NodeId), None }
 
-impl<'a, 'tcx> RegionCtxt<'a, 'tcx, 'tcx> {
-    pub fn new(fcx: &'a FnCtxt<'a, 'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
+    pub fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
                initial_repeating_scope: RepeatingScope,
                initial_body_id: ast::NodeId,
-               subject: SubjectNode) -> RegionCtxt<'a, 'tcx, 'tcx> {
+               subject: SubjectNode) -> RegionCtxt<'a, 'gcx, 'tcx> {
         let RepeatingScope(initial_repeating_scope) = initial_repeating_scope;
         RegionCtxt {
             fcx: fcx,
@@ -487,7 +487,7 @@ fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
 }
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'gcx, 'tcx> {
     // (..) FIXME(#3238) should use visit_pat, not visit_arm/visit_local,
     // However, right now we run into an issue whereby some free
     // regions are not properly related if they appear within the
@@ -794,7 +794,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
 }
 }
 
-impl<'a, 'tcx> RegionCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> RegionCtxt<'a, 'gcx, 'tcx> {
 fn constrain_cast(&mut self,
                   cast_expr: &hir::Expr,
                   source_expr: &hir::Expr)
@@ -1151,7 +1151,7 @@ fn link_fn_args(&self, body_scope: CodeExtent, args: &[hir::Arg]) {
 /// Link lifetimes of any ref bindings in `root_pat` to the pointers found in the discriminant, if
 /// needed.
 fn link_pattern<'t>(&self,
-                    mc: mc::MemCategorizationContext<'a, 'tcx, 'tcx>,
+                    mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
                     discr_cmt: mc::cmt<'tcx>,
                     root_pat: &hir::Pat) {
     debug!("link_pattern(discr_cmt={:?}, root_pat={:?})",
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 175171e2f2a..10c16391bf7 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -56,7 +56,7 @@ use rustc::hir::intravisit::{self, Visitor};
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 pub fn closure_analyze_fn(&self, body: &hir::Block) {
     let mut seed = SeedBorrowKind::new(self);
     seed.visit_block(body);
@@ -90,7 +90,7 @@ struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     closures_with_inferred_kinds: HashSet<ast::NodeId>,
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'gcx, 'tcx> {
     fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
             hir::ExprClosure(cc, _, ref body, _) => {
@@ -104,8 +104,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx, 'tcx> {
     }
 }
 
-impl<'a,'tcx> SeedBorrowKind<'a,'tcx, 'tcx> {
-    fn new(fcx: &'a FnCtxt<'a,'tcx, 'tcx>) -> SeedBorrowKind<'a,'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> SeedBorrowKind<'a, 'gcx, 'tcx> {
+    fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>) -> SeedBorrowKind<'a, 'gcx, 'tcx> {
         SeedBorrowKind { fcx: fcx, closures_with_inferred_kinds: HashSet::new() }
     }
 
@@ -157,10 +157,10 @@ struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     closures_with_inferred_kinds: &'a HashSet<ast::NodeId>,
 }
 
-impl<'a,'tcx> AdjustBorrowKind<'a,'tcx, 'tcx> {
-    fn new(fcx: &'a FnCtxt<'a,'tcx, 'tcx>,
+impl<'a, 'gcx, 'tcx> AdjustBorrowKind<'a, 'gcx, 'tcx> {
+    fn new(fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
            closures_with_inferred_kinds: &'a HashSet<ast::NodeId>)
-           -> AdjustBorrowKind<'a,'tcx, 'tcx> {
+           -> AdjustBorrowKind<'a, 'gcx, 'tcx> {
         AdjustBorrowKind { fcx: fcx, closures_with_inferred_kinds: closures_with_inferred_kinds }
     }
 
@@ -492,7 +492,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'gcx, 'tcx> {
     fn visit_fn(&mut self,
                 fn_kind: intravisit::FnKind<'v>,
                 decl: &'v hir::FnDecl,
@@ -505,7 +505,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx, 'tcx> {
     }
 }
 
-impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a, 'gcx, 'tcx> {
     fn consume(&mut self,
                _consume_id: ast::NodeId,
                _consume_span: Span,
diff --git a/src/librustc_typeck/check/wfcheck.rs b/src/librustc_typeck/check/wfcheck.rs
index 3069627a421..7739bb6bb8f 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -410,10 +410,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 
         debug!("check_method_receiver: receiver ty = {:?}", rcvr_ty);
 
-        let _ = ::require_same_types(
-            fcx.ccx, Some(fcx), span,
-            sig.inputs[0], rcvr_ty,
-            "mismatched method receiver");
+        fcx.require_same_types(span, sig.inputs[0], rcvr_ty,
+                               "mismatched method receiver");
     }
 
     fn check_variances_for_type_defn(&self,
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 5307753613d..1c7496d611e 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -34,7 +34,7 @@ use rustc::hir;
 ///////////////////////////////////////////////////////////////////////////
 // Entry point functions
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
+impl<'a, 'gcx, 'tcx> FnCtxt<'a, 'gcx, 'tcx> {
 pub fn resolve_type_vars_in_expr(&self, e: &hir::Expr) {
     assert_eq!(self.writeback_errors.get(), false);
     let mut wbcx = WritebackCx::new(self);
@@ -78,12 +78,12 @@ struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
 }
 
-impl<'cx, 'tcx> WritebackCx<'cx, 'tcx, 'tcx> {
-    fn new(fcx: &'cx FnCtxt<'cx, 'tcx, 'tcx>) -> WritebackCx<'cx, 'tcx, 'tcx> {
+impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
+    fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>) -> WritebackCx<'cx, 'gcx, 'tcx> {
         WritebackCx { fcx: fcx }
     }
 
-    fn tcx(&self) -> TyCtxt<'cx, 'tcx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'cx, 'gcx, 'tcx> {
         self.fcx.tcx
     }
 
@@ -134,7 +134,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx, 'tcx> {
 // below. In general, a function is made into a `visitor` if it must
 // traffic in node-ids or update tables in the type context etc.
 
-impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx, 'tcx> {
+impl<'cx, 'gcx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'gcx, 'tcx> {
     fn visit_stmt(&mut self, s: &hir::Stmt) {
         if self.fcx.writeback_errors.get() {
             return;
@@ -214,7 +214,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx, 'tcx> {
     }
 }
 
-impl<'cx, 'tcx> WritebackCx<'cx, 'tcx, 'tcx> {
+impl<'cx, 'gcx, 'tcx> WritebackCx<'cx, 'gcx, 'tcx> {
     fn visit_upvar_borrow_map(&self) {
         if self.fcx.writeback_errors.get() {
             return;
@@ -359,8 +359,16 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx, 'tcx> {
         }
     }
 
-    fn resolve<T:TypeFoldable<'tcx>>(&self, t: &T, reason: ResolveReason) -> T {
-        t.fold_with(&mut Resolver::new(self.fcx, reason))
+    fn resolve<T>(&self, x: &T, reason: ResolveReason) -> T::Lifted
+        where T: TypeFoldable<'tcx> + ty::Lift<'gcx>
+    {
+        let x = x.fold_with(&mut Resolver::new(self.fcx, reason));
+        if let Some(lifted) = self.tcx().lift_to_global(&x) {
+            lifted
+        } else {
+            span_bug!(reason.span(self.tcx()),
+                      "writeback: `{:?}` missing from the global type context", x);
+        }
     }
 }
 
@@ -378,8 +386,8 @@ enum ResolveReason {
     ResolvingFieldTypes(ast::NodeId)
 }
 
-impl ResolveReason {
-    fn span<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Span {
+impl<'a, 'gcx, 'tcx> ResolveReason {
+    fn span(&self, tcx: TyCtxt<'a, 'gcx, 'tcx>) -> Span {
         match *self {
             ResolvingExpr(s) => s,
             ResolvingLocal(s) => s,
@@ -415,18 +423,18 @@ struct Resolver<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
     reason: ResolveReason,
 }
 
-impl<'cx, 'tcx> Resolver<'cx, 'tcx, 'tcx> {
-    fn new(fcx: &'cx FnCtxt<'cx, 'tcx, 'tcx>,
+impl<'cx, 'gcx, 'tcx> Resolver<'cx, 'gcx, 'tcx> {
+    fn new(fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
            reason: ResolveReason)
-           -> Resolver<'cx, 'tcx, 'tcx>
+           -> Resolver<'cx, 'gcx, 'tcx>
     {
         Resolver::from_infcx(fcx, &fcx.writeback_errors, reason)
     }
 
-    fn from_infcx(infcx: &'cx InferCtxt<'cx, 'tcx, 'tcx>,
+    fn from_infcx(infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
                   writeback_errors: &'cx Cell<bool>,
                   reason: ResolveReason)
-                  -> Resolver<'cx, 'tcx, 'tcx>
+                  -> Resolver<'cx, 'gcx, 'tcx>
     {
         Resolver { infcx: infcx,
                    tcx: infcx.tcx,
@@ -480,8 +488,8 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx, 'tcx> {
     }
 }
 
-impl<'cx, 'tcx> TypeFolder<'tcx, 'tcx> for Resolver<'cx, 'tcx, 'tcx> {
-    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
+impl<'cx, 'gcx, 'tcx> TypeFolder<'gcx, 'tcx> for Resolver<'cx, 'gcx, 'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx> {
         self.tcx
     }
 
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index e49df1fc745..797a1509ebe 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -58,7 +58,7 @@ There are some shortcomings in this design:
 
 */
 
-use astconv::{self, AstConv, ty_of_arg, ast_ty_to_ty, ast_region_to_region};
+use astconv::{AstConv, ast_region_to_region, Bounds, PartitionedBounds, partition_bounds};
 use lint;
 use hir::def::Def;
 use hir::def_id::DefId;
@@ -291,7 +291,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
 
 impl<'a,'tcx> ItemCtxt<'a,'tcx> {
     fn to_ty<RS:RegionScope>(&self, rs: &RS, ast_ty: &hir::Ty) -> Ty<'tcx> {
-        ast_ty_to_ty(self, rs, ast_ty)
+        AstConv::ast_ty_to_ty(self, rs, ast_ty)
     }
 }
 
@@ -559,7 +559,7 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         ty_generic_predicates_for_fn(ccx, &sig.generics, rcvr_ty_predicates);
 
     let (fty, explicit_self_category) =
-        astconv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
+        AstConv::ty_of_method(&ccx.icx(&(rcvr_ty_predicates, &sig.generics)),
                               sig, untransformed_rcvr_ty);
 
     let def_id = ccx.tcx.map.local_def_id(id);
@@ -712,7 +712,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
         },
         hir::ItemDefaultImpl(_, ref ast_trait_ref) => {
             let trait_ref =
-                astconv::instantiate_mono_trait_ref(&ccx.icx(&()),
+                AstConv::instantiate_mono_trait_ref(&ccx.icx(&()),
                                                     &ExplicitRscope,
                                                     ast_trait_ref,
                                                     None);
@@ -742,7 +742,7 @@ fn convert_item(ccx: &CrateCtxt, it: &hir::Item) {
                                    TypeScheme { generics: ty_generics.clone(),
                                                 ty: selfty });
             let trait_ref = opt_trait_ref.as_ref().map(|ast_trait_ref| {
-                astconv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
+                AstConv::instantiate_mono_trait_ref(&ccx.icx(&ty_predicates),
                                                     &ExplicitRscope,
                                                     ast_trait_ref,
                                                     Some(selfty))
@@ -1452,7 +1452,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         }
         hir::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
             let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
-            let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl);
+            let tofd = AstConv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &decl);
             let def_id = ccx.tcx.map.local_def_id(it.id);
             let substs = mk_item_substs(ccx, &ty_generics);
             let ty = tcx.mk_fn_def(def_id, substs, tofd);
@@ -1582,7 +1582,7 @@ fn compute_type_scheme_of_foreign_item<'a, 'tcx>(
         hir::ForeignItemStatic(ref t, _) => {
             ty::TypeScheme {
                 generics: ty::Generics::empty(),
-                ty: ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
+                ty: AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, t)
             }
         }
     }
@@ -1793,9 +1793,9 @@ fn ty_generic_predicates<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     for predicate in &where_clause.predicates {
         match predicate {
             &hir::WherePredicate::BoundPredicate(ref bound_pred) => {
-                let ty = ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
-                                      &ExplicitRscope,
-                                      &bound_pred.bounded_ty);
+                let ty = AstConv::ast_ty_to_ty(&ccx.icx(&(base_predicates, ast_generics)),
+                                               &ExplicitRscope,
+                                               &bound_pred.bounded_ty);
 
                 for bound in bound_pred.bounds.iter() {
                     match bound {
@@ -1887,7 +1887,7 @@ fn convert_default_type_parameter<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                             index: u32)
                                             -> Ty<'tcx>
 {
-    let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path);
+    let ty = AstConv::ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &path);
 
     for leaf_ty in ty.walk() {
         if let ty::TyParam(p) = leaf_ty.sty {
@@ -1991,7 +1991,7 @@ fn compute_object_lifetime_default<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                       hir::TraitTyParamBound(..) =>
                           None,
                       hir::RegionTyParamBound(ref lifetime) =>
-                          Some(astconv::ast_region_to_region(ccx.tcx, lifetime)),
+                          Some(ast_region_to_region(ccx.tcx, lifetime)),
                   }
               })
               .collect()
@@ -2034,7 +2034,7 @@ fn compute_bounds<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                         ast_bounds: &[hir::TyParamBound],
                         sized_by_default: SizedByDefault,
                         span: Span)
-                        -> astconv::Bounds<'tcx>
+                        -> Bounds<'tcx>
 {
     let mut bounds =
         conv_param_bounds(astconv,
@@ -2090,7 +2090,7 @@ fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                              projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
                              -> ty::PolyTraitRef<'tcx>
 {
-    astconv::instantiate_poly_trait_ref(astconv,
+    AstConv::instantiate_poly_trait_ref(astconv,
                                         &ExplicitRscope,
                                         trait_ref,
                                         Some(param_ty),
@@ -2101,14 +2101,14 @@ fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                               span: Span,
                               param_ty: ty::Ty<'tcx>,
                               ast_bounds: &[hir::TyParamBound])
-                              -> astconv::Bounds<'tcx>
+                              -> Bounds<'tcx>
 {
     let tcx = astconv.tcx();
-    let astconv::PartitionedBounds {
+    let PartitionedBounds {
         builtin_bounds,
         trait_bounds,
         region_bounds
-    } = astconv::partition_bounds(tcx, span, &ast_bounds);
+    } = partition_bounds(tcx, span, &ast_bounds);
 
     let mut projection_bounds = Vec::new();
 
@@ -2125,7 +2125,7 @@ fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                      .map(|r| ast_region_to_region(tcx, r))
                      .collect();
 
-    astconv::Bounds {
+    Bounds {
         region_bounds: region_bounds,
         builtin_bounds: builtin_bounds,
         trait_bounds: trait_bounds,
@@ -2157,12 +2157,12 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
     let rb = BindingRscope::new();
     let input_tys = decl.inputs
                         .iter()
-                        .map(|a| ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
+                        .map(|a| AstConv::ty_of_arg(&ccx.icx(ast_generics), &rb, a, None))
                         .collect::<Vec<_>>();
 
     let output = match decl.output {
         hir::Return(ref ty) =>
-            ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &ty)),
+            ty::FnConverging(AstConv::ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &ty)),
         hir::DefaultReturn(..) =>
             ty::FnConverging(ccx.tcx.mk_nil()),
         hir::NoReturn(..) =>
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index cdc3cfb7d31..3c46d962198 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -104,7 +104,7 @@ pub use rustc::util;
 use dep_graph::DepNode;
 use hir::map as hir_map;
 use hir::def::Def;
-use rustc::infer::{self, InferCtxt, TypeOrigin};
+use rustc::infer::{InferCtxt, TypeOrigin};
 use rustc::ty::subst::Substs;
 use rustc::ty::{self, Ty, TyCtxt, TypeFoldable};
 use rustc::traits::ProjectionMode;
@@ -192,36 +192,33 @@ fn require_c_abi_if_variadic(tcx: TyCtxt,
     }
 }
 
+pub fn emit_type_err<'a, 'gcx, 'tcx>(tcx: TyCtxt<'a, 'gcx, 'tcx>,
+                                     span: Span,
+                                     found_ty: Ty<'tcx>,
+                                     expected_ty: Ty<'tcx>,
+                                     terr: &ty::error::TypeError<'tcx>,
+                                     msg: &str) {
+    let mut err = struct_span_err!(tcx.sess, span, E0211, "{}", msg);
+    err = err.span_label(span, &terr);
+    err = err.note_expected_found(&"type", &expected_ty, &found_ty);
+    tcx.note_and_explain_type_err(&mut err, terr, span);
+    err.emit();
+}
+
 fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx, 'tcx>>,
                                 span: Span,
                                 t1: Ty<'tcx>,
                                 t2: Ty<'tcx>,
                                 msg: &str)
-                                -> bool
-{
-    let err = if let Some(infcx) = maybe_infcx {
-        infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2).err()
-    } else {
-        InferCtxt::enter(ccx.tcx, None, None, ProjectionMode::AnyFinal, |infcx| {
-            infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2).err()
-        })
-    };
-
-    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);
+                                -> bool {
+    InferCtxt::enter(ccx.tcx, None, None, ProjectionMode::AnyFinal, |infcx| {
+        if let Err(err) = infcx.eq_types(false, TypeOrigin::Misc(span), t1, t2) {
+            emit_type_err(infcx.tcx, span, t1, t2, &err, msg);
+            false
+        } else {
+            true
         }
-        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,
@@ -258,7 +255,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 })
             }));
 
-            require_same_types(ccx, None, main_span, main_t, se_ty,
+            require_same_types(ccx, main_span, main_t, se_ty,
                                "main function has wrong type");
         }
         _ => {
@@ -307,7 +304,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 }),
             }));
 
-            require_same_types(ccx, None, start_span, start_t, se_ty,
+            require_same_types(ccx, start_span, start_t, se_ty,
                                "start function has wrong type");
         }
         _ => {