about summary refs log tree commit diff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/librustc/cfg/construct.rs6
-rw-r--r--src/librustc/cfg/mod.rs4
-rw-r--r--src/librustc/dep_graph/visit.rs4
-rw-r--r--src/librustc/hir/pat_util.rs2
-rw-r--r--src/librustc/infer/bivariate.rs12
-rw-r--r--src/librustc/infer/combine.rs30
-rw-r--r--src/librustc/infer/equate.rs12
-rw-r--r--src/librustc/infer/error_reporting.rs37
-rw-r--r--src/librustc/infer/freshen.rs12
-rw-r--r--src/librustc/infer/glb.rs16
-rw-r--r--src/librustc/infer/higher_ranked/mod.rs42
-rw-r--r--src/librustc/infer/lattice.rs2
-rw-r--r--src/librustc/infer/lub.rs16
-rw-r--r--src/librustc/infer/mod.rs21
-rw-r--r--src/librustc/infer/region_inference/graphviz.rs6
-rw-r--r--src/librustc/infer/region_inference/mod.rs10
-rw-r--r--src/librustc/infer/resolve.rs35
-rw-r--r--src/librustc/infer/sub.rs12
-rw-r--r--src/librustc/infer/unify_key.rs6
-rw-r--r--src/librustc/lint/context.rs7
-rw-r--r--src/librustc/middle/astconv_util.rs2
-rw-r--r--src/librustc/middle/cstore.rs72
-rw-r--r--src/librustc/middle/dataflow.rs4
-rw-r--r--src/librustc/middle/dead.rs27
-rw-r--r--src/librustc/middle/effect.rs4
-rw-r--r--src/librustc/middle/expr_use_visitor.rs77
-rw-r--r--src/librustc/middle/free_region.rs10
-rw-r--r--src/librustc/middle/intrinsicck.rs12
-rw-r--r--src/librustc/middle/liveness.rs6
-rw-r--r--src/librustc/middle/mem_categorization.rs59
-rw-r--r--src/librustc/middle/reachable.rs17
-rw-r--r--src/librustc/middle/stability.rs58
-rw-r--r--src/librustc/mir/tcx.rs12
-rw-r--r--src/librustc/mir/transform.rs15
-rw-r--r--src/librustc/traits/coherence.rs20
-rw-r--r--src/librustc/traits/error_reporting.rs12
-rw-r--r--src/librustc/traits/fulfill.rs38
-rw-r--r--src/librustc/traits/mod.rs4
-rw-r--r--src/librustc/traits/object_safety.rs2
-rw-r--r--src/librustc/traits/project.rs48
-rw-r--r--src/librustc/traits/select.rs18
-rw-r--r--src/librustc/traits/specialize/mod.rs12
-rw-r--r--src/librustc/traits/specialize/specialization_graph.rs27
-rw-r--r--src/librustc/traits/util.rs28
-rw-r--r--src/librustc/ty/_match.rs6
-rw-r--r--src/librustc/ty/adjustment.rs6
-rw-r--r--src/librustc/ty/contents.rs9
-rw-r--r--src/librustc/ty/context.rs40
-rw-r--r--src/librustc/ty/error.rs6
-rw-r--r--src/librustc/ty/fast_reject.rs8
-rw-r--r--src/librustc/ty/fold.rs30
-rw-r--r--src/librustc/ty/item_path.rs2
-rw-r--r--src/librustc/ty/layout.rs42
-rw-r--r--src/librustc/ty/mod.rs38
-rw-r--r--src/librustc/ty/outlives.rs2
-rw-r--r--src/librustc/ty/relate.rs2
-rw-r--r--src/librustc/ty/structural_impls.rs17
-rw-r--r--src/librustc/ty/sty.rs14
-rw-r--r--src/librustc/ty/subst.rs12
-rw-r--r--src/librustc/ty/trait_def.rs19
-rw-r--r--src/librustc/ty/util.rs29
-rw-r--r--src/librustc/ty/wf.rs14
-rw-r--r--src/librustc/util/ppaux.rs8
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs2
-rw-r--r--src/librustc_borrowck/borrowck/fragments.rs10
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mir/dataflow.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mir/gather_moves.rs6
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs8
-rw-r--r--src/librustc_borrowck/borrowck/move_data.rs14
-rw-r--r--src/librustc_const_eval/check_match.rs8
-rw-r--r--src/librustc_const_eval/eval.rs40
-rw-r--r--src/librustc_driver/driver.rs8
-rw-r--r--src/librustc_driver/pretty.rs4
-rw-r--r--src/librustc_driver/test.rs24
-rw-r--r--src/librustc_incremental/assert_dep_graph.rs10
-rw-r--r--src/librustc_incremental/calculate_svh.rs6
-rw-r--r--src/librustc_incremental/persist/directory.rs4
-rw-r--r--src/librustc_incremental/persist/dirty_clean.rs4
-rw-r--r--src/librustc_incremental/persist/load.rs16
-rw-r--r--src/librustc_incremental/persist/save.rs6
-rw-r--r--src/librustc_lint/builtin.rs8
-rw-r--r--src/librustc_lint/types.rs8
-rw-r--r--src/librustc_metadata/astencode.rs16
-rw-r--r--src/librustc_metadata/csearch.rs34
-rw-r--r--src/librustc_metadata/decoder.rs52
-rw-r--r--src/librustc_metadata/encoder.rs8
-rw-r--r--src/librustc_metadata/tls_context.rs6
-rw-r--r--src/librustc_metadata/tydecode.rs6
-rw-r--r--src/librustc_metadata/tyencode.rs4
-rw-r--r--src/librustc_mir/build/mod.rs8
-rw-r--r--src/librustc_mir/build/scope.rs4
-rw-r--r--src/librustc_mir/graphviz.rs9
-rw-r--r--src/librustc_mir/hair/cx/block.rs14
-rw-r--r--src/librustc_mir/hair/cx/expr.rs70
-rw-r--r--src/librustc_mir/hair/cx/mod.rs16
-rw-r--r--src/librustc_mir/hair/cx/pattern.rs6
-rw-r--r--src/librustc_mir/hair/mod.rs12
-rw-r--r--src/librustc_mir/mir_map.rs8
-rw-r--r--src/librustc_mir/pretty.rs13
-rw-r--r--src/librustc_mir/transform/break_critical_edges.rs3
-rw-r--r--src/librustc_mir/transform/erase_regions.rs7
-rw-r--r--src/librustc_mir/transform/no_landing_pads.rs3
-rw-r--r--src/librustc_mir/transform/promote_consts.rs2
-rw-r--r--src/librustc_mir/transform/qualify_consts.rs14
-rw-r--r--src/librustc_mir/transform/remove_dead_blocks.rs3
-rw-r--r--src/librustc_mir/transform/simplify_cfg.rs3
-rw-r--r--src/librustc_mir/transform/type_check.rs27
-rw-r--r--src/librustc_passes/consts.rs6
-rw-r--r--src/librustc_passes/rvalues.rs6
-rw-r--r--src/librustc_privacy/lib.rs18
-rw-r--r--src/librustc_save_analysis/dump_visitor.rs4
-rw-r--r--src/librustc_save_analysis/lib.rs8
-rw-r--r--src/librustc_trans/_match.rs4
-rw-r--r--src/librustc_trans/adt.rs8
-rw-r--r--src/librustc_trans/back/link.rs4
-rw-r--r--src/librustc_trans/back/symbol_names.rs4
-rw-r--r--src/librustc_trans/base.rs6
-rw-r--r--src/librustc_trans/callee.rs2
-rw-r--r--src/librustc_trans/closure.rs2
-rw-r--r--src/librustc_trans/collector.rs37
-rw-r--r--src/librustc_trans/common.rs14
-rw-r--r--src/librustc_trans/context.rs8
-rw-r--r--src/librustc_trans/expr.rs6
-rw-r--r--src/librustc_trans/glue.rs5
-rw-r--r--src/librustc_trans/meth.rs4
-rw-r--r--src/librustc_trans/monomorphize.rs6
-rw-r--r--src/librustc_trans/partitioning.rs8
-rw-r--r--src/librustc_typeck/astconv.rs119
-rw-r--r--src/librustc_typeck/check/_match.rs14
-rw-r--r--src/librustc_typeck/check/assoc.rs2
-rw-r--r--src/librustc_typeck/check/callee.rs4
-rw-r--r--src/librustc_typeck/check/cast.rs28
-rw-r--r--src/librustc_typeck/check/closure.rs2
-rw-r--r--src/librustc_typeck/check/coercion.rs14
-rw-r--r--src/librustc_typeck/check/demand.rs2
-rw-r--r--src/librustc_typeck/check/dropck.rs10
-rw-r--r--src/librustc_typeck/check/method/confirm.rs22
-rw-r--r--src/librustc_typeck/check/method/mod.rs2
-rw-r--r--src/librustc_typeck/check/method/probe.rs18
-rw-r--r--src/librustc_typeck/check/method/suggest.rs2
-rw-r--r--src/librustc_typeck/check/mod.rs80
-rw-r--r--src/librustc_typeck/check/op.rs2
-rw-r--r--src/librustc_typeck/check/regionck.rs22
-rw-r--r--src/librustc_typeck/check/upvar.rs30
-rw-r--r--src/librustc_typeck/check/wfcheck.rs16
-rw-r--r--src/librustc_typeck/check/writeback.rs42
-rw-r--r--src/librustc_typeck/check_unused.rs4
-rw-r--r--src/librustc_typeck/coherence/mod.rs14
-rw-r--r--src/librustc_typeck/coherence/orphan.rs4
-rw-r--r--src/librustc_typeck/coherence/overlap.rs9
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs4
-rw-r--r--src/librustc_typeck/collect.rs57
-rw-r--r--src/librustc_typeck/lib.rs8
-rw-r--r--src/librustc_typeck/variance/constraints.rs2
-rw-r--r--src/librustc_typeck/variance/mod.rs2
-rw-r--r--src/librustc_typeck/variance/terms.rs4
-rw-r--r--src/librustdoc/clean/inline.rs59
-rw-r--r--src/librustdoc/core.rs6
-rw-r--r--src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs3
160 files changed, 1296 insertions, 1189 deletions
diff --git a/src/librustc/cfg/construct.rs b/src/librustc/cfg/construct.rs
index a1f1fdb6b0e..64c51c94328 100644
--- a/src/librustc/cfg/construct.rs
+++ b/src/librustc/cfg/construct.rs
@@ -19,7 +19,7 @@ use syntax::ptr::P;
 use hir::{self, PatKind};
 
 struct CFGBuilder<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     graph: CFGGraph,
     fn_exit: CFGIndex,
     loop_scopes: Vec<LoopScope>,
@@ -32,8 +32,8 @@ struct LoopScope {
     break_index: CFGIndex,    // where to go on a `break
 }
 
-pub fn construct(tcx: TyCtxt,
-                 blk: &hir::Block) -> CFG {
+pub fn construct<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                           blk: &hir::Block) -> CFG {
     let mut graph = graph::Graph::new();
     let entry = graph.add_node(CFGNodeData::Entry);
 
diff --git a/src/librustc/cfg/mod.rs b/src/librustc/cfg/mod.rs
index e9c4dd1d87d..617e2ed2f1a 100644
--- a/src/librustc/cfg/mod.rs
+++ b/src/librustc/cfg/mod.rs
@@ -58,8 +58,8 @@ pub type CFGNode = graph::Node<CFGNodeData>;
 pub type CFGEdge = graph::Edge<CFGEdgeData>;
 
 impl CFG {
-    pub fn new(tcx: TyCtxt,
-               blk: &hir::Block) -> CFG {
+    pub fn new<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         blk: &hir::Block) -> CFG {
         construct::construct(tcx, blk)
     }
 
diff --git a/src/librustc/dep_graph/visit.rs b/src/librustc/dep_graph/visit.rs
index 4cc3f138ddd..321d109ca0e 100644
--- a/src/librustc/dep_graph/visit.rs
+++ b/src/librustc/dep_graph/visit.rs
@@ -22,13 +22,13 @@ use super::dep_node::DepNode;
 /// read edge from the corresponding AST node. This is used in
 /// compiler passes to automatically record the item that they are
 /// working on.
-pub fn visit_all_items_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx>,
+pub fn visit_all_items_in_krate<'a, 'tcx, V, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 mut dep_node_fn: F,
                                                 visitor: &mut V)
     where F: FnMut(DefId) -> DepNode<DefId>, V: Visitor<'tcx>
 {
     struct TrackingVisitor<'visit, 'tcx: 'visit, F: 'visit, V: 'visit> {
-        tcx: TyCtxt<'visit, 'tcx>,
+        tcx: TyCtxt<'visit, 'tcx, 'tcx>,
         dep_node_fn: &'visit mut F,
         visitor: &'visit mut V
     }
diff --git a/src/librustc/hir/pat_util.rs b/src/librustc/hir/pat_util.rs
index 17ad2189f68..6bbd6a207ee 100644
--- a/src/librustc/hir/pat_util.rs
+++ b/src/librustc/hir/pat_util.rs
@@ -209,7 +209,7 @@ pub fn simple_name<'a>(pat: &'a hir::Pat) -> Option<ast::Name> {
     }
 }
 
-pub fn def_to_path(tcx: TyCtxt, id: DefId) -> hir::Path {
+pub fn def_to_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> hir::Path {
     let name = tcx.item_name(id);
     hir::Path::from_ident(DUMMY_SP, hir::Ident::from_name(name))
 }
diff --git a/src/librustc/infer/bivariate.rs b/src/librustc/infer/bivariate.rs
index 71058647c36..f853396e758 100644
--- a/src/librustc/infer/bivariate.rs
+++ b/src/librustc/infer/bivariate.rs
@@ -32,20 +32,20 @@ use ty::{self, Ty, TyCtxt};
 use ty::TyVar;
 use ty::relate::{Relate, RelateResult, TypeRelation};
 
-pub struct Bivariate<'a, 'tcx: 'a> {
-    fields: CombineFields<'a, 'tcx>
+pub struct Bivariate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fields: CombineFields<'a, 'gcx, 'tcx>
 }
 
-impl<'a, 'tcx> Bivariate<'a, 'tcx> {
-    pub fn new(fields: CombineFields<'a, 'tcx>) -> Bivariate<'a, 'tcx> {
+impl<'a, 'tcx> Bivariate<'a, 'tcx, 'tcx> {
+    pub fn new(fields: CombineFields<'a, 'tcx, 'tcx>) -> Bivariate<'a, 'tcx, 'tcx> {
         Bivariate { fields: fields }
     }
 }
 
-impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx, 'tcx> {
     fn tag(&self) -> &'static str { "Bivariate" }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.fields.tcx() }
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
diff --git a/src/librustc/infer/combine.rs b/src/librustc/infer/combine.rs
index 96b0dba9d39..6a2dba14fd1 100644
--- a/src/librustc/infer/combine.rs
+++ b/src/librustc/infer/combine.rs
@@ -52,15 +52,15 @@ use syntax::ast;
 use syntax::codemap::Span;
 
 #[derive(Clone)]
-pub struct CombineFields<'a, 'tcx: 'a> {
-    pub infcx: &'a InferCtxt<'a, 'tcx>,
+pub struct CombineFields<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     pub a_is_expected: bool,
     pub trace: TypeTrace<'tcx>,
     pub cause: Option<ty::relate::Cause>,
     pub obligations: PredicateObligations<'tcx>,
 }
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'a, 'tcx> InferCtxt<'a, 'tcx, 'tcx> {
 pub fn super_combine_tys<R>(&self,
                             relation: &mut R,
                             a: Ty<'tcx>,
@@ -150,35 +150,35 @@ fn unify_float_variable(&self,
 }
 }
 
-impl<'a, 'tcx> CombineFields<'a, 'tcx> {
-    pub fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> CombineFields<'a, 'tcx, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
-    pub fn switch_expected(&self) -> CombineFields<'a, 'tcx> {
+    pub fn switch_expected(&self) -> CombineFields<'a, 'tcx, 'tcx> {
         CombineFields {
             a_is_expected: !self.a_is_expected,
             ..(*self).clone()
         }
     }
 
-    pub fn equate(&self) -> Equate<'a, 'tcx> {
+    pub fn equate(&self) -> Equate<'a, 'tcx, 'tcx> {
         Equate::new(self.clone())
     }
 
-    pub fn bivariate(&self) -> Bivariate<'a, 'tcx> {
+    pub fn bivariate(&self) -> Bivariate<'a, 'tcx, 'tcx> {
         Bivariate::new(self.clone())
     }
 
-    pub fn sub(&self) -> Sub<'a, 'tcx> {
+    pub fn sub(&self) -> Sub<'a, 'tcx, 'tcx> {
         Sub::new(self.clone())
     }
 
-    pub fn lub(&self) -> Lub<'a, 'tcx> {
+    pub fn lub(&self) -> Lub<'a, 'tcx, 'tcx> {
         Lub::new(self.clone())
     }
 
-    pub fn glb(&self) -> Glb<'a, 'tcx> {
+    pub fn glb(&self) -> Glb<'a, 'tcx, 'tcx> {
         Glb::new(self.clone())
     }
 
@@ -291,16 +291,16 @@ impl<'a, 'tcx> CombineFields<'a, 'tcx> {
     }
 }
 
-struct Generalizer<'cx, 'tcx:'cx> {
-    infcx: &'cx InferCtxt<'cx, 'tcx>,
+struct Generalizer<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
+    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
     span: Span,
     for_vid: ty::TyVid,
     make_region_vars: bool,
     cycle_detected: bool,
 }
 
-impl<'cx, 'tcx> ty::fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx> {
-    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx> {
+impl<'cx, 'tcx> ty::fold::TypeFolder<'tcx> for Generalizer<'cx, 'tcx, 'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
diff --git a/src/librustc/infer/equate.rs b/src/librustc/infer/equate.rs
index eff66469c4e..433baf42c40 100644
--- a/src/librustc/infer/equate.rs
+++ b/src/librustc/infer/equate.rs
@@ -19,12 +19,12 @@ use ty::relate::{Relate, RelateResult, TypeRelation};
 use traits::PredicateObligations;
 
 /// Ensures `a` is made equal to `b`. Returns `a` on success.
-pub struct Equate<'a, 'tcx: 'a> {
-    fields: CombineFields<'a, 'tcx>
+pub struct Equate<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fields: CombineFields<'a, 'gcx, 'tcx>
 }
 
-impl<'a, 'tcx> Equate<'a, 'tcx> {
-    pub fn new(fields: CombineFields<'a, 'tcx>) -> Equate<'a, 'tcx> {
+impl<'a, 'tcx> Equate<'a, 'tcx, 'tcx> {
+    pub fn new(fields: CombineFields<'a, 'tcx, 'tcx>) -> Equate<'a, 'tcx, 'tcx> {
         Equate { fields: fields }
     }
 
@@ -33,10 +33,10 @@ impl<'a, 'tcx> Equate<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx> {
+impl<'a, 'tcx> TypeRelation<'a,'tcx> for Equate<'a, 'tcx, 'tcx> {
     fn tag(&self) -> &'static str { "Equate" }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.fields.tcx() }
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
diff --git a/src/librustc/infer/error_reporting.rs b/src/librustc/infer/error_reporting.rs
index 66e5f52544d..219ebf625ec 100644
--- a/src/librustc/infer/error_reporting.rs
+++ b/src/librustc/infer/error_reporting.rs
@@ -95,7 +95,7 @@ use syntax::codemap::{self, Pos, Span};
 use syntax::parse::token;
 use syntax::ptr::P;
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn note_and_explain_region(self,
                                    err: &mut DiagnosticBuilder,
                                    prefix: &str,
@@ -112,8 +112,9 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
             }
         }
 
-        fn explain_span(tcx: TyCtxt, heading: &str, span: Span)
-                        -> (String, Option<Span>) {
+        fn explain_span<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                  heading: &str, span: Span)
+                                  -> (String, Option<Span>) {
             let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
             (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
              Some(span))
@@ -301,7 +302,7 @@ trait ErrorReportingHelpers<'tcx> {
                                 span: Span);
 }
 
-impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
+impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx, 'tcx> {
     fn report_region_errors(&self,
                             errors: &Vec<RegionResolutionError<'tcx>>) {
         debug!("report_region_errors(): {} errors to start", errors.len());
@@ -474,10 +475,10 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             }
         }
 
-        fn free_regions_from_same_fn(tcx: TyCtxt,
-                                     sub: Region,
-                                     sup: Region)
-                                     -> Option<FreeRegionsFromSameFn> {
+        fn free_regions_from_same_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                               sub: Region,
+                                               sup: Region)
+                                               -> Option<FreeRegionsFromSameFn> {
             debug!("free_regions_from_same_fn(sub={:?}, sup={:?})", sub, sup);
             let (scope_id, fr1, fr2) = match (sub, sup) {
                 (ReFree(fr1), ReFree(fr2)) => {
@@ -1109,7 +1110,7 @@ struct RebuildPathInfo<'a> {
 }
 
 struct Rebuilder<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     fn_decl: &'a hir::FnDecl,
     expl_self_opt: Option<&'a hir::ExplicitSelf_>,
     generics: &'a hir::Generics,
@@ -1125,7 +1126,7 @@ enum FreshOrKept {
 }
 
 impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx>,
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            fn_decl: &'a hir::FnDecl,
            expl_self_opt: Option<&'a hir::ExplicitSelf_>,
            generics: &'a hir::Generics,
@@ -1641,7 +1642,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
+impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx, 'tcx> {
     fn give_expl_lifetime_param(&self,
                                 err: &mut DiagnosticBuilder,
                                 decl: &hir::FnDecl,
@@ -1904,17 +1905,17 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
 }
 
 pub trait Resolvable<'tcx> {
-    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Self;
+    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx, 'tcx>) -> Self;
 }
 
 impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
-    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         infcx.resolve_type_vars_if_possible(self)
     }
 }
 
 impl<'tcx> Resolvable<'tcx> for ty::TraitRef<'tcx> {
-    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>)
+    fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx, 'tcx>)
                    -> ty::TraitRef<'tcx> {
         infcx.resolve_type_vars_if_possible(self)
     }
@@ -1922,16 +1923,16 @@ impl<'tcx> Resolvable<'tcx> for ty::TraitRef<'tcx> {
 
 impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
     fn resolve<'a>(&self,
-                   infcx: &InferCtxt<'a, 'tcx>)
+                   infcx: &InferCtxt<'a, 'tcx, 'tcx>)
                    -> ty::PolyTraitRef<'tcx>
     {
         infcx.resolve_type_vars_if_possible(self)
     }
 }
 
-fn lifetimes_in_scope(tcx: TyCtxt,
-                      scope_id: ast::NodeId)
-                      -> Vec<hir::LifetimeDef> {
+fn lifetimes_in_scope<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                scope_id: ast::NodeId)
+                                -> Vec<hir::LifetimeDef> {
     let mut taken = Vec::new();
     let parent = tcx.map.get_parent(scope_id);
     let method_id_opt = match tcx.map.find(parent) {
diff --git a/src/librustc/infer/freshen.rs b/src/librustc/infer/freshen.rs
index 7c87c0a8791..72f12188f92 100644
--- a/src/librustc/infer/freshen.rs
+++ b/src/librustc/infer/freshen.rs
@@ -37,14 +37,14 @@ use std::collections::hash_map::{self, Entry};
 use super::InferCtxt;
 use super::unify_key::ToType;
 
-pub struct TypeFreshener<'a, 'tcx:'a> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
+pub struct TypeFreshener<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     freshen_count: u32,
     freshen_map: hash_map::HashMap<ty::InferTy, Ty<'tcx>>,
 }
 
-impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> TypeFreshener<'a, 'tcx> {
+impl<'a, 'tcx> TypeFreshener<'a, 'tcx, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>) -> TypeFreshener<'a, 'tcx, 'tcx> {
         TypeFreshener {
             infcx: infcx,
             freshen_count: 0,
@@ -77,8 +77,8 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> {
+impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
diff --git a/src/librustc/infer/glb.rs b/src/librustc/infer/glb.rs
index da7d5894da9..6daf60648ba 100644
--- a/src/librustc/infer/glb.rs
+++ b/src/librustc/infer/glb.rs
@@ -19,12 +19,12 @@ use ty::relate::{Relate, RelateResult, TypeRelation};
 use traits::PredicateObligations;
 
 /// "Greatest lower bound" (common subtype)
-pub struct Glb<'a, 'tcx: 'a> {
-    fields: CombineFields<'a, 'tcx>
+pub struct Glb<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fields: CombineFields<'a, 'gcx, 'tcx>
 }
 
-impl<'a, 'tcx> Glb<'a, 'tcx> {
-    pub fn new(fields: CombineFields<'a, 'tcx>) -> Glb<'a, 'tcx> {
+impl<'a, 'tcx> Glb<'a, 'tcx, 'tcx> {
+    pub fn new(fields: CombineFields<'a, 'tcx, 'tcx>) -> Glb<'a, 'tcx, 'tcx> {
         Glb { fields: fields }
     }
 
@@ -33,10 +33,10 @@ impl<'a, 'tcx> Glb<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx, 'tcx> {
     fn tag(&self) -> &'static str { "Glb" }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.fields.tcx() }
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
@@ -76,8 +76,8 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Glb<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx> {
-    fn infcx(&self) -> &'a InferCtxt<'a,'tcx> {
+impl<'a, 'tcx> LatticeDir<'a,'tcx> for Glb<'a, 'tcx, 'tcx> {
+    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx, 'tcx> {
         self.fields.infcx
     }
 
diff --git a/src/librustc/infer/higher_ranked/mod.rs b/src/librustc/infer/higher_ranked/mod.rs
index 546bfe65fe9..803dbfdfdea 100644
--- a/src/librustc/infer/higher_ranked/mod.rs
+++ b/src/librustc/infer/higher_ranked/mod.rs
@@ -31,7 +31,7 @@ pub trait HigherRankedRelations<'a,'tcx> {
         where T: Relate<'a,'tcx>;
 }
 
-impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
+impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a, 'tcx, 'tcx> {
     fn higher_ranked_sub<T>(&self, a: &Binder<T>, b: &Binder<T>)
                             -> RelateResult<'tcx, Binder<T>>
         where T: Relate<'a,'tcx>
@@ -119,14 +119,14 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
             Ok(ty::Binder(result1))
         });
 
-        fn generalize_region(infcx: &InferCtxt,
-                             span: Span,
-                             snapshot: &CombinedSnapshot,
-                             debruijn: ty::DebruijnIndex,
-                             new_vars: &[ty::RegionVid],
-                             a_map: &FnvHashMap<ty::BoundRegion, ty::Region>,
-                             r0: ty::Region)
-                             -> ty::Region {
+        fn generalize_region<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
+                                       span: Span,
+                                       snapshot: &CombinedSnapshot,
+                                       debruijn: ty::DebruijnIndex,
+                                       new_vars: &[ty::RegionVid],
+                                       a_map: &FnvHashMap<ty::BoundRegion, ty::Region>,
+                                       r0: ty::Region)
+                                       -> ty::Region {
             // Regions that pre-dated the LUB computation stay as they are.
             if !is_var_in_set(new_vars, r0) {
                 assert!(!r0.is_bound());
@@ -214,15 +214,15 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
             Ok(ty::Binder(result1))
         });
 
-        fn generalize_region(infcx: &InferCtxt,
-                             span: Span,
-                             snapshot: &CombinedSnapshot,
-                             debruijn: ty::DebruijnIndex,
-                             new_vars: &[ty::RegionVid],
-                             a_map: &FnvHashMap<ty::BoundRegion, ty::Region>,
-                             a_vars: &[ty::RegionVid],
-                             b_vars: &[ty::RegionVid],
-                             r0: ty::Region) -> ty::Region {
+        fn generalize_region<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
+                                       span: Span,
+                                       snapshot: &CombinedSnapshot,
+                                       debruijn: ty::DebruijnIndex,
+                                       new_vars: &[ty::RegionVid],
+                                       a_map: &FnvHashMap<ty::BoundRegion, ty::Region>,
+                                       a_vars: &[ty::RegionVid],
+                                       b_vars: &[ty::RegionVid],
+                                       r0: ty::Region) -> ty::Region {
             if !is_var_in_set(new_vars, r0) {
                 assert!(!r0.is_bound());
                 return r0;
@@ -306,7 +306,7 @@ impl<'a,'tcx> HigherRankedRelations<'a,'tcx> for CombineFields<'a,'tcx> {
     }
 }
 
-fn var_ids<'a, 'tcx>(fields: &CombineFields<'a, 'tcx>,
+fn var_ids<'a, 'tcx>(fields: &CombineFields<'a, 'tcx, 'tcx>,
                       map: &FnvHashMap<ty::BoundRegion, ty::Region>)
                      -> Vec<ty::RegionVid> {
     map.iter()
@@ -329,7 +329,7 @@ fn is_var_in_set(new_vars: &[ty::RegionVid], r: ty::Region) -> bool {
     }
 }
 
-fn fold_regions_in<'a, 'tcx, T, F>(tcx: TyCtxt<'a, 'tcx>,
+fn fold_regions_in<'a, 'tcx, T, F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    unbound_value: &T,
                                    mut fldr: F)
                                    -> T
@@ -349,7 +349,7 @@ fn fold_regions_in<'a, 'tcx, T, F>(tcx: TyCtxt<'a, 'tcx>,
     })
 }
 
-impl<'a,'tcx> InferCtxt<'a,'tcx> {
+impl<'a,'tcx> InferCtxt<'a,'tcx, 'tcx> {
     fn tainted_regions(&self, snapshot: &CombinedSnapshot, r: ty::Region) -> Vec<ty::Region> {
         self.region_vars.tainted(&snapshot.region_vars_snapshot, r)
     }
diff --git a/src/librustc/infer/lattice.rs b/src/librustc/infer/lattice.rs
index 94d261f9df3..69f86686fe4 100644
--- a/src/librustc/infer/lattice.rs
+++ b/src/librustc/infer/lattice.rs
@@ -36,7 +36,7 @@ use ty::{self, Ty};
 use ty::relate::{RelateResult, TypeRelation};
 
 pub trait LatticeDir<'f,'tcx> : TypeRelation<'f,'tcx> {
-    fn infcx(&self) -> &'f InferCtxt<'f, 'tcx>;
+    fn infcx(&self) -> &'f InferCtxt<'f, 'tcx, 'tcx>;
 
     // Relates the type `v` to `a` and `b` such that `v` represents
     // the LUB/GLB of `a` and `b` as appropriate.
diff --git a/src/librustc/infer/lub.rs b/src/librustc/infer/lub.rs
index 6bb4a22b4c7..890170325ee 100644
--- a/src/librustc/infer/lub.rs
+++ b/src/librustc/infer/lub.rs
@@ -19,12 +19,12 @@ use ty::relate::{Relate, RelateResult, TypeRelation};
 use traits::PredicateObligations;
 
 /// "Least upper bound" (common supertype)
-pub struct Lub<'a, 'tcx: 'a> {
-    fields: CombineFields<'a, 'tcx>
+pub struct Lub<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fields: CombineFields<'a, 'gcx, 'tcx>
 }
 
-impl<'a, 'tcx> Lub<'a, 'tcx> {
-    pub fn new(fields: CombineFields<'a, 'tcx>) -> Lub<'a, 'tcx> {
+impl<'a, 'tcx> Lub<'a, 'tcx, 'tcx> {
+    pub fn new(fields: CombineFields<'a, 'tcx, 'tcx>) -> Lub<'a, 'tcx, 'tcx> {
         Lub { fields: fields }
     }
 
@@ -33,10 +33,10 @@ impl<'a, 'tcx> Lub<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx, 'tcx> {
     fn tag(&self) -> &'static str { "Lub" }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.fields.tcx() }
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.fields.tcx() }
 
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
@@ -76,8 +76,8 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Lub<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx> {
-    fn infcx(&self) -> &'a InferCtxt<'a,'tcx> {
+impl<'a, 'tcx> LatticeDir<'a,'tcx> for Lub<'a, 'tcx, 'tcx> {
+    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx, 'tcx> {
         self.fields.infcx
     }
 
diff --git a/src/librustc/infer/mod.rs b/src/librustc/infer/mod.rs
index 1036b918b9a..cef2ae12d6b 100644
--- a/src/librustc/infer/mod.rs
+++ b/src/librustc/infer/mod.rs
@@ -73,8 +73,8 @@ pub type Bound<T> = Option<T>;
 pub type UnitResult<'tcx> = RelateResult<'tcx, ()>; // "unify result"
 pub type FixupResult<T> = Result<T, FixupError>; // "fixup result"
 
-pub struct InferCtxt<'a, 'tcx: 'a> {
-    pub tcx: TyCtxt<'a, 'tcx>,
+pub struct InferCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    pub tcx: TyCtxt<'a, 'gcx, 'tcx>,
 
     pub tables: &'a RefCell<ty::Tables<'tcx>>,
 
@@ -384,8 +384,8 @@ impl fmt::Display for FixupError {
     }
 }
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx>,
+impl<'a, 'tcx> InferCtxt<'a, 'tcx, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                tables: &'a RefCell<ty::Tables<'tcx>>,
                param_env: Option<ty::ParameterEnvironment<'a, 'tcx>>,
                projection_mode: ProjectionMode)
@@ -406,7 +406,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn normalizing(tcx: TyCtxt<'a, 'tcx>,
+    pub fn normalizing(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        tables: &'a RefCell<ty::Tables<'tcx>>,
                        projection_mode: ProjectionMode)
                        -> Self {
@@ -441,7 +441,7 @@ pub struct CombinedSnapshot {
 }
 
 // NOTE: Callable from trans only!
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn normalize_associated_type<T>(self, value: &T) -> T
         where T : TypeFoldable<'tcx>
     {
@@ -473,7 +473,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'a, 'tcx> InferCtxt<'a, 'tcx, 'tcx> {
 pub fn drain_fulfillment_cx_or_panic<T>(&self,
                                         span: Span,
                                         fulfill_cx: &mut traits::FulfillmentContext<'tcx>,
@@ -532,7 +532,7 @@ pub fn drain_fulfillment_cx<T>(&self,
         }
     }
 
-    pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx> {
+    pub fn freshener<'b>(&'b self) -> TypeFreshener<'b, 'tcx, 'tcx> {
         freshen::TypeFreshener::new(self)
     }
 
@@ -603,8 +603,7 @@ pub fn drain_fulfillment_cx<T>(&self,
     }
 
     fn combine_fields(&'a self, a_is_expected: bool, trace: TypeTrace<'tcx>)
-        -> CombineFields<'a, 'tcx>
-    {
+                      -> CombineFields<'a, 'tcx, 'tcx> {
         CombineFields {
             infcx: self,
             a_is_expected: a_is_expected,
@@ -1539,7 +1538,7 @@ impl<'a, 'tcx> TypeTrace<'tcx> {
         }
     }
 
-    pub fn dummy(tcx: TyCtxt<'a, 'tcx>) -> TypeTrace<'tcx> {
+    pub fn dummy(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> TypeTrace<'tcx> {
         TypeTrace {
             origin: TypeOrigin::Misc(codemap::DUMMY_SP),
             values: Types(ExpectedFound {
diff --git a/src/librustc/infer/region_inference/graphviz.rs b/src/librustc/infer/region_inference/graphviz.rs
index 05303ae1376..5c39e39bee0 100644
--- a/src/librustc/infer/region_inference/graphviz.rs
+++ b/src/librustc/infer/region_inference/graphviz.rs
@@ -119,7 +119,7 @@ pub fn maybe_print_constraints_for<'a, 'tcx>(region_vars: &RegionVarBindings<'a,
 }
 
 struct ConstraintGraph<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     graph_name: String,
     map: &'a FnvHashMap<Constraint, SubregionOrigin<'tcx>>,
     node_ids: FnvHashMap<Node, usize>,
@@ -139,7 +139,7 @@ enum Edge {
 }
 
 impl<'a, 'tcx> ConstraintGraph<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx>,
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            name: String,
            map: &'a ConstraintMap<'tcx>)
            -> ConstraintGraph<'a, 'tcx> {
@@ -258,7 +258,7 @@ 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>,
+fn dump_region_constraints_to<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                             map: &ConstraintMap<'tcx>,
                                             path: &str)
                                             -> io::Result<()> {
diff --git a/src/librustc/infer/region_inference/mod.rs b/src/librustc/infer/region_inference/mod.rs
index 9dcc19d76b5..3e231f8bb3e 100644
--- a/src/librustc/infer/region_inference/mod.rs
+++ b/src/librustc/infer/region_inference/mod.rs
@@ -191,7 +191,7 @@ impl SameRegions {
 pub type CombineMap = FnvHashMap<TwoRegions, RegionVid>;
 
 pub struct RegionVarBindings<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     var_origins: RefCell<Vec<RegionVariableOrigin>>,
 
     // Constraints of the form `A <= B` introduced by the region
@@ -254,7 +254,7 @@ pub struct RegionSnapshot {
 }
 
 impl<'a, 'tcx> RegionVarBindings<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx>) -> RegionVarBindings<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> RegionVarBindings<'a, 'tcx> {
         RegionVarBindings {
             tcx: tcx,
             var_origins: RefCell::new(Vec::new()),
@@ -1363,7 +1363,7 @@ impl<'tcx> fmt::Display for GenericKind<'tcx> {
 }
 
 impl<'a, 'tcx> GenericKind<'tcx> {
-    pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, '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 VerifyBound {
+impl<'a, 'tcx> VerifyBound {
     fn for_each_region(&self, f: &mut FnMut(ty::Region)) {
         match self {
             &VerifyBound::AnyRegion(ref rs) |
@@ -1424,7 +1424,7 @@ impl VerifyBound {
         }
     }
 
-    fn is_met(&self, tcx: TyCtxt,
+    fn is_met(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
               free_regions: &FreeRegionMap,
               var_values: &Vec<VarValue>,
               min: ty::Region)
diff --git a/src/librustc/infer/resolve.rs b/src/librustc/infer/resolve.rs
index c2f38332f54..af5341e56ee 100644
--- a/src/librustc/infer/resolve.rs
+++ b/src/librustc/infer/resolve.rs
@@ -19,18 +19,18 @@ use ty::{self, Ty, TyCtxt, TypeFoldable};
 /// been unified with (similar to `shallow_resolve`, but deep). This is
 /// useful for printing messages etc but also required at various
 /// points for correctness.
-pub struct OpportunisticTypeResolver<'a, 'tcx:'a> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
+pub struct OpportunisticTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
 }
 
-impl<'a, 'tcx> OpportunisticTypeResolver<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> OpportunisticTypeResolver<'a, 'tcx> {
+impl<'a, 'tcx> OpportunisticTypeResolver<'a, 'tcx, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>) -> OpportunisticTypeResolver<'a, 'tcx, 'tcx> {
         OpportunisticTypeResolver { infcx: infcx }
     }
 }
 
-impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> {
+impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
@@ -47,18 +47,18 @@ impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx
 /// The opportunistic type and region resolver is similar to the
 /// opportunistic type resolver, but also opportunistly resolves
 /// regions. It is useful for canonicalization.
-pub struct OpportunisticTypeAndRegionResolver<'a, 'tcx:'a> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
+pub struct OpportunisticTypeAndRegionResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
 }
 
-impl<'a, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+impl<'a, 'tcx> OpportunisticTypeAndRegionResolver<'a, 'tcx, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>) -> Self {
         OpportunisticTypeAndRegionResolver { infcx: infcx }
     }
 }
 
-impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> {
+impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver<'a, 'tcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
@@ -85,7 +85,8 @@ impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for OpportunisticTypeAndRegionResolver
 /// Full type resolution replaces all type and region variables with
 /// their concrete results. If any variable cannot be replaced (never unified, etc)
 /// then an `Err` result is returned.
-pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> FixupResult<T>
+pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
+                                  value: &T) -> FixupResult<T>
     where T : TypeFoldable<'tcx>
 {
     let mut full_resolver = FullTypeResolver { infcx: infcx, err: None };
@@ -98,13 +99,13 @@ pub fn fully_resolve<'a, 'tcx, T>(infcx: &InferCtxt<'a,'tcx>, value: &T) -> Fixu
 
 // N.B. This type is not public because the protocol around checking the
 // `err` field is not enforcable otherwise.
-struct FullTypeResolver<'a, 'tcx:'a> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
+struct FullTypeResolver<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     err: Option<FixupError>,
 }
 
-impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> {
+impl<'a, 'tcx> ty::fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
diff --git a/src/librustc/infer/sub.rs b/src/librustc/infer/sub.rs
index d6a16727363..969ae1e0bd1 100644
--- a/src/librustc/infer/sub.rs
+++ b/src/librustc/infer/sub.rs
@@ -20,12 +20,12 @@ use traits::PredicateObligations;
 use std::mem;
 
 /// Ensures `a` is made a subtype of `b`. Returns `a` on success.
-pub struct Sub<'a, 'tcx: 'a> {
-    fields: CombineFields<'a, 'tcx>,
+pub struct Sub<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fields: CombineFields<'a, 'gcx, 'tcx>,
 }
 
-impl<'a, 'tcx> Sub<'a, 'tcx> {
-    pub fn new(f: CombineFields<'a, 'tcx>) -> Sub<'a, 'tcx> {
+impl<'a, 'tcx> Sub<'a, 'tcx, 'tcx> {
+    pub fn new(f: CombineFields<'a, 'tcx, 'tcx>) -> Sub<'a, 'tcx, 'tcx> {
         Sub { fields: f }
     }
 
@@ -34,9 +34,9 @@ impl<'a, 'tcx> Sub<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx> {
+impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Sub<'a, 'tcx, 'tcx> {
     fn tag(&self) -> &'static str { "Sub" }
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.fields.infcx.tcx }
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.fields.infcx.tcx }
     fn a_is_expected(&self) -> bool { self.fields.a_is_expected }
 
     fn with_cause<F,R>(&mut self, cause: Cause, f: F) -> R
diff --git a/src/librustc/infer/unify_key.rs b/src/librustc/infer/unify_key.rs
index bf54e7c1b39..922bbbc1b4c 100644
--- a/src/librustc/infer/unify_key.rs
+++ b/src/librustc/infer/unify_key.rs
@@ -13,7 +13,7 @@ use ty::{self, IntVarValue, Ty, TyCtxt};
 use rustc_data_structures::unify::{Combine, UnifyKey};
 
 pub trait ToType<'tcx> {
-    fn to_type<'a>(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx>;
+    fn to_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx>;
 }
 
 impl UnifyKey for ty::IntVid {
@@ -51,7 +51,7 @@ impl UnifyKey for ty::RegionVid {
 }
 
 impl<'tcx> ToType<'tcx> for IntVarValue {
-    fn to_type<'a>(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    fn to_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         match *self {
             ty::IntType(i) => tcx.mk_mach_int(i),
             ty::UintType(i) => tcx.mk_mach_uint(i),
@@ -69,7 +69,7 @@ impl UnifyKey for ty::FloatVid {
 }
 
 impl<'tcx> ToType<'tcx> for ast::FloatTy {
-    fn to_type<'a>(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    fn to_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         tcx.mk_mach_float(*self)
     }
 }
diff --git a/src/librustc/lint/context.rs b/src/librustc/lint/context.rs
index a6d6895154c..a4b9b5f4556 100644
--- a/src/librustc/lint/context.rs
+++ b/src/librustc/lint/context.rs
@@ -297,7 +297,7 @@ impl LintStore {
 /// Context for lint checking after type checking.
 pub struct LateContext<'a, 'tcx: 'a> {
     /// Type context we're checking in.
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     /// The crate being checked.
     pub krate: &'a hir::Crate,
@@ -652,7 +652,7 @@ impl<'a> EarlyContext<'a> {
 }
 
 impl<'a, 'tcx> LateContext<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx>,
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            krate: &'a hir::Crate,
            access_levels: &'a AccessLevels) -> LateContext<'a, 'tcx> {
         // We want to own the lint store, so move it out of the session.
@@ -1220,7 +1220,8 @@ fn check_lint_name_cmdline(sess: &Session, lint_cx: &LintStore,
 /// Perform lint checking on a crate.
 ///
 /// Consumes the `lint_store` field of the `Session`.
-pub fn check_crate(tcx: TyCtxt, access_levels: &AccessLevels) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             access_levels: &AccessLevels) {
     let _task = tcx.dep_graph.in_task(DepNode::LateLintCheck);
 
     let krate = tcx.map.krate();
diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs
index de0d41ea64b..99521f9ef0f 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> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, '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/cstore.rs b/src/librustc/middle/cstore.rs
index e3d94c7a5d3..c0af457ed23 100644
--- a/src/librustc/middle/cstore.rs
+++ b/src/librustc/middle/cstore.rs
@@ -161,47 +161,47 @@ pub trait CrateStore<'tcx> : Any {
     fn deprecation(&self, def: DefId) -> Option<attr::Deprecation>;
     fn visibility(&self, def: DefId) -> ty::Visibility;
     fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind;
-    fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def_id: DefId)
+    fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
                       -> ty::ClosureTy<'tcx>;
     fn item_variances(&self, def: DefId) -> ty::ItemVariances;
     fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr>;
-    fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                      -> ty::TypeScheme<'tcx>;
     fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>>;
     fn item_name(&self, def: DefId) -> ast::Name;
-    fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                            -> ty::GenericPredicates<'tcx>;
-    fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                  -> ty::GenericPredicates<'tcx>;
     fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute>;
     fn item_symbol(&self, def: DefId) -> String;
-    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>;
-    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>;
+    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>;
+    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>;
     fn method_arg_names(&self, did: DefId) -> Vec<String>;
     fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId>;
 
     // trait info
     fn implementations_of_trait(&self, def_id: DefId) -> Vec<DefId>;
-    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                   -> Vec<Rc<ty::Method<'tcx>>>;
     fn trait_item_def_ids(&self, def: DefId)
                           -> Vec<ty::ImplOrTraitItemId>;
 
     // impl info
     fn impl_items(&self, impl_def_id: DefId) -> Vec<ty::ImplOrTraitItemId>;
-    fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                           -> Option<ty::TraitRef<'tcx>>;
     fn impl_polarity(&self, def: DefId) -> Option<hir::ImplPolarity>;
     fn custom_coerce_unsized_kind(&self, def: DefId)
                                   -> Option<ty::adjustment::CustomCoerceUnsized>;
-    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                              -> Vec<Rc<ty::AssociatedConst<'tcx>>>;
     fn impl_parent(&self, impl_def_id: DefId) -> Option<DefId>;
 
     // trait/impl-item info
-    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def_id: DefId)
+    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
                          -> Option<DefId>;
-    fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<ty::ImplOrTraitItem<'tcx>>;
 
     // flags
@@ -209,7 +209,7 @@ pub trait CrateStore<'tcx> : Any {
     fn is_defaulted_trait(&self, did: DefId) -> bool;
     fn is_impl(&self, did: DefId) -> bool;
     fn is_default_impl(&self, impl_did: DefId) -> bool;
-    fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, did: DefId) -> bool;
+    fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool;
     fn is_static_method(&self, did: DefId) -> bool;
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool;
     fn is_typedef(&self, did: DefId) -> bool;
@@ -250,9 +250,9 @@ pub trait CrateStore<'tcx> : Any {
     fn crate_top_level_items(&self, cnum: ast::CrateNum) -> Vec<ChildItem>;
 
     // misc. metadata
-    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> FoundAst<'tcx>;
-    fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<Mir<'tcx>>;
     fn is_item_mir_available(&self, def: DefId) -> bool;
 
@@ -266,14 +266,14 @@ pub trait CrateStore<'tcx> : Any {
     fn metadata_filename(&self) -> &str;
     fn metadata_section_name(&self, target: &Target) -> &str;
     fn encode_type<'a>(&self,
-                       tcx: TyCtxt<'a, 'tcx>,
+                       tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        ty: Ty<'tcx>,
-                       def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx>, DefId) -> String)
+                       def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String)
                        -> Vec<u8>;
     fn used_crates(&self, prefer: LinkagePreference) -> Vec<(ast::CrateNum, Option<PathBuf>)>;
     fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource;
     fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<ast::CrateNum>;
-    fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx>,
+    fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            reexports: &def::ExportMap,
                            item_symbols: &RefCell<NodeMap<String>>,
                            link_meta: &LinkMeta,
@@ -338,32 +338,32 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     fn deprecation(&self, def: DefId) -> Option<attr::Deprecation> { bug!("deprecation") }
     fn visibility(&self, def: DefId) -> ty::Visibility { bug!("visibility") }
     fn closure_kind(&self, def_id: DefId) -> ty::ClosureKind  { bug!("closure_kind") }
-    fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def_id: DefId)
+    fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
                       -> ty::ClosureTy<'tcx>  { bug!("closure_ty") }
     fn item_variances(&self, def: DefId) -> ty::ItemVariances { bug!("item_variances") }
     fn repr_attrs(&self, def: DefId) -> Vec<attr::ReprAttr> { bug!("repr_attrs") }
-    fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                      -> ty::TypeScheme<'tcx> { bug!("item_type") }
     fn visible_parent_map<'a>(&'a self) -> ::std::cell::RefMut<'a, DefIdMap<DefId>> {
         bug!("visible_parent_map")
     }
     fn item_name(&self, def: DefId) -> ast::Name { bug!("item_name") }
-    fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                            -> ty::GenericPredicates<'tcx> { bug!("item_predicates") }
-    fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                  -> ty::GenericPredicates<'tcx> { bug!("item_super_predicates") }
     fn item_attrs(&self, def_id: DefId) -> Vec<ast::Attribute> { bug!("item_attrs") }
     fn item_symbol(&self, def: DefId) -> String { bug!("item_symbol") }
-    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>
+    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)-> ty::TraitDef<'tcx>
         { bug!("trait_def") }
-    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>
+    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>
         { bug!("adt_def") }
     fn method_arg_names(&self, did: DefId) -> Vec<String> { bug!("method_arg_names") }
     fn inherent_implementations_for_type(&self, def_id: DefId) -> Vec<DefId> { vec![] }
 
     // trait info
     fn implementations_of_trait(&self, def_id: DefId) -> Vec<DefId> { vec![] }
-    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                   -> Vec<Rc<ty::Method<'tcx>>> { bug!("provided_trait_methods") }
     fn trait_item_def_ids(&self, def: DefId)
                           -> Vec<ty::ImplOrTraitItemId> { bug!("trait_item_def_ids") }
@@ -371,20 +371,20 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     // impl info
     fn impl_items(&self, impl_def_id: DefId) -> Vec<ty::ImplOrTraitItemId>
         { bug!("impl_items") }
-    fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                           -> Option<ty::TraitRef<'tcx>> { bug!("impl_trait_ref") }
     fn impl_polarity(&self, def: DefId) -> Option<hir::ImplPolarity> { bug!("impl_polarity") }
     fn custom_coerce_unsized_kind(&self, def: DefId)
                                   -> Option<ty::adjustment::CustomCoerceUnsized>
         { bug!("custom_coerce_unsized_kind") }
-    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                              -> Vec<Rc<ty::AssociatedConst<'tcx>>> { bug!("associated_consts") }
     fn impl_parent(&self, def: DefId) -> Option<DefId> { bug!("impl_parent") }
 
     // trait/impl-item info
-    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def_id: DefId)
+    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
                          -> Option<DefId> { bug!("trait_of_item") }
-    fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<ty::ImplOrTraitItem<'tcx>> { bug!("impl_or_trait_item") }
 
     // flags
@@ -392,7 +392,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     fn is_defaulted_trait(&self, did: DefId) -> bool { bug!("is_defaulted_trait") }
     fn is_impl(&self, did: DefId) -> bool { bug!("is_impl") }
     fn is_default_impl(&self, impl_did: DefId) -> bool { bug!("is_default_impl") }
-    fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, did: DefId) -> bool
+    fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool
         { bug!("is_extern_item") }
     fn is_static_method(&self, did: DefId) -> bool { bug!("is_static_method") }
     fn is_statically_included_foreign_item(&self, id: ast::NodeId) -> bool { false }
@@ -446,9 +446,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
         { bug!("crate_top_level_items") }
 
     // misc. metadata
-    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> FoundAst<'tcx> { bug!("maybe_get_item_ast") }
-    fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<Mir<'tcx>> { bug!("maybe_get_item_mir") }
     fn is_item_mir_available(&self, def: DefId) -> bool {
         bug!("is_item_mir_available")
@@ -464,9 +464,9 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
     fn metadata_filename(&self) -> &str { bug!("metadata_filename") }
     fn metadata_section_name(&self, target: &Target) -> &str { bug!("metadata_section_name") }
     fn encode_type<'a>(&self,
-                       tcx: TyCtxt<'a, 'tcx>,
+                       tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        ty: Ty<'tcx>,
-                       def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx>, DefId) -> String)
+                       def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String)
                        -> Vec<u8> {
         bug!("encode_type")
     }
@@ -474,7 +474,7 @@ impl<'tcx> CrateStore<'tcx> for DummyCrateStore {
         { vec![] }
     fn used_crate_source(&self, cnum: ast::CrateNum) -> CrateSource { bug!("used_crate_source") }
     fn extern_mod_stmt_cnum(&self, emod_id: ast::NodeId) -> Option<ast::CrateNum> { None }
-    fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx>,
+    fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            reexports: &def::ExportMap,
                            item_symbols: &RefCell<NodeMap<String>>,
                            link_meta: &LinkMeta,
@@ -507,7 +507,7 @@ pub mod tls {
     use hir::def_id::DefId;
 
     pub trait EncodingContext<'tcx> {
-        fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx>;
+        fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
         fn encode_ty(&self, encoder: &mut OpaqueEncoder, t: Ty<'tcx>);
         fn encode_substs(&self, encoder: &mut OpaqueEncoder, substs: &Substs<'tcx>);
     }
@@ -574,7 +574,7 @@ pub mod tls {
     }
 
     pub trait DecodingContext<'tcx> {
-        fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx>;
+        fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
         fn decode_ty(&self, decoder: &mut OpaqueDecoder) -> ty::Ty<'tcx>;
         fn decode_substs(&self, decoder: &mut OpaqueDecoder) -> Substs<'tcx>;
         fn translate_def_id(&self, def_id: DefId) -> DefId;
diff --git a/src/librustc/middle/dataflow.rs b/src/librustc/middle/dataflow.rs
index dc58a663195..41b27a48b29 100644
--- a/src/librustc/middle/dataflow.rs
+++ b/src/librustc/middle/dataflow.rs
@@ -37,7 +37,7 @@ pub enum EntryOrExit {
 
 #[derive(Clone)]
 pub struct DataFlowContext<'a, 'tcx: 'a, O> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     /// a name for the analysis using this dataflow instance
     analysis_name: &'static str,
@@ -222,7 +222,7 @@ pub enum KillFrom {
 }
 
 impl<'a, 'tcx, O:DataFlowOperator> DataFlowContext<'a, 'tcx, O> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx>,
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                analysis_name: &'static str,
                decl: Option<&hir::FnDecl>,
                cfg: &cfg::CFG,
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index a1fe1b521f5..cc6b83fccf9 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -31,7 +31,8 @@ use syntax::attr;
 // explored. For example, if it's a live NodeItem that is a
 // function, then we should explore its block to check for codes that
 // may need to be marked as live.
-fn should_explore(tcx: TyCtxt, node_id: ast::NodeId) -> bool {
+fn should_explore<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            node_id: ast::NodeId) -> bool {
     match tcx.map.find(node_id) {
         Some(ast_map::NodeItem(..)) |
         Some(ast_map::NodeImplItem(..)) |
@@ -45,7 +46,7 @@ fn should_explore(tcx: TyCtxt, node_id: ast::NodeId) -> bool {
 
 struct MarkSymbolVisitor<'a, 'tcx: 'a> {
     worklist: Vec<ast::NodeId>,
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     live_symbols: Box<HashSet<ast::NodeId>>,
     struct_has_extern_repr: bool,
     ignore_non_const_paths: bool,
@@ -54,7 +55,7 @@ struct MarkSymbolVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx>,
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            worklist: Vec<ast::NodeId>) -> MarkSymbolVisitor<'a, 'tcx> {
         MarkSymbolVisitor {
             worklist: worklist,
@@ -362,9 +363,10 @@ impl<'v> Visitor<'v> for LifeSeeder {
     }
 }
 
-fn create_and_seed_worklist(tcx: TyCtxt,
-                            access_levels: &privacy::AccessLevels,
-                            krate: &hir::Crate) -> Vec<ast::NodeId> {
+fn create_and_seed_worklist<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                      access_levels: &privacy::AccessLevels,
+                                      krate: &hir::Crate)
+                                      -> Vec<ast::NodeId> {
     let mut worklist = Vec::new();
     for (id, _) in &access_levels.map {
         worklist.push(*id);
@@ -385,10 +387,10 @@ fn create_and_seed_worklist(tcx: TyCtxt,
     return life_seeder.worklist;
 }
 
-fn find_live(tcx: TyCtxt,
-             access_levels: &privacy::AccessLevels,
-             krate: &hir::Crate)
-             -> Box<HashSet<ast::NodeId>> {
+fn find_live<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                       access_levels: &privacy::AccessLevels,
+                       krate: &hir::Crate)
+                       -> Box<HashSet<ast::NodeId>> {
     let worklist = create_and_seed_worklist(tcx, access_levels, krate);
     let mut symbol_visitor = MarkSymbolVisitor::new(tcx, worklist);
     symbol_visitor.mark_live_symbols();
@@ -405,7 +407,7 @@ fn get_struct_ctor_id(item: &hir::Item) -> Option<ast::NodeId> {
 }
 
 struct DeadVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     live_symbols: Box<HashSet<ast::NodeId>>,
 }
 
@@ -583,7 +585,8 @@ impl<'a, 'tcx, 'v> Visitor<'v> for DeadVisitor<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: TyCtxt, access_levels: &privacy::AccessLevels) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             access_levels: &privacy::AccessLevels) {
     let _task = tcx.dep_graph.in_task(DepNode::DeadCheck);
     let krate = tcx.map.krate();
     let live_symbols = find_live(tcx, access_levels, krate);
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index 55a130697fe..b62368c2a98 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -51,7 +51,7 @@ fn type_is_unsafe_function(ty: Ty) -> bool {
 }
 
 struct EffectCheckVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     /// Whether we're in an unsafe context.
     unsafe_context: UnsafeContext,
@@ -183,7 +183,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: TyCtxt) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _task = tcx.dep_graph.in_task(DepNode::EffectCheck);
 
     let mut visitor = EffectCheckVisitor {
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index b662dc81d94..3c813dffb0a 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -22,7 +22,7 @@ use self::OverloadedCallType::*;
 use hir::pat_util;
 use hir::def::Def;
 use hir::def_id::{DefId};
-use infer;
+use infer::InferCtxt;
 use middle::mem_categorization as mc;
 use ty::{self, TyCtxt, adjustment};
 
@@ -209,8 +209,8 @@ enum OverloadedCallType {
 }
 
 impl OverloadedCallType {
-    fn from_trait_id(tcx: TyCtxt, trait_id: DefId)
-                     -> OverloadedCallType {
+    fn from_trait_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, 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 +227,8 @@ impl OverloadedCallType {
         bug!("overloaded call didn't map to known function trait")
     }
 
-    fn from_method_id(tcx: TyCtxt, method_id: DefId)
-                      -> OverloadedCallType {
+    fn from_method_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, method_id: DefId)
+                                -> OverloadedCallType {
         let method = tcx.impl_or_trait_item(method_id);
         OverloadedCallType::from_trait_id(tcx, method.container().id())
     }
@@ -241,9 +241,8 @@ impl OverloadedCallType {
 // mem_categorization, it requires a TYPER, which is a type that
 // supplies types from the tree. After type checking is complete, you
 // can just use the tcx as the typer.
-pub struct ExprUseVisitor<'d, 't, 'a: 't, 'tcx:'a+'d> {
-    typer: &'t infer::InferCtxt<'a, 'tcx>,
-    mc: mc::MemCategorizationContext<'t, 'a, 'tcx>,
+pub struct ExprUseVisitor<'d, 'a, 'gcx: 'a+'tcx, 'tcx:'a+'d> {
+    mc: mc::MemCategorizationContext<'a, 'gcx, 'tcx>,
     delegate: &'d mut Delegate<'tcx>,
 }
 
@@ -272,14 +271,14 @@ enum PassArgs {
     ByRef,
 }
 
-impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
+impl<'d, 'a, 'tcx> ExprUseVisitor<'d, 'a, 'tcx, 'tcx> {
     pub fn new(delegate: &'d mut (Delegate<'tcx>+'d),
-               typer: &'t infer::InferCtxt<'a, 'tcx>)
-               -> ExprUseVisitor<'d,'t,'a,'tcx> where 'tcx:'a+'d
+               infcx: &'a InferCtxt<'a, 'tcx, 'tcx>) -> Self
     {
-        let mc: mc::MemCategorizationContext<'t, 'a, 'tcx> =
-            mc::MemCategorizationContext::new(typer);
-        ExprUseVisitor { typer: typer, mc: mc, delegate: delegate }
+        ExprUseVisitor {
+            mc: mc::MemCategorizationContext::new(infcx),
+            delegate: delegate
+        }
     }
 
     pub fn walk_fn(&mut self,
@@ -293,7 +292,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                          decl: &hir::FnDecl,
                          body: &hir::Block) {
         for arg in &decl.inputs {
-            let arg_ty = return_if_err!(self.typer.node_ty(arg.pat.id));
+            let arg_ty = return_if_err!(self.mc.infcx.node_ty(arg.pat.id));
 
             let fn_body_scope = self.tcx().region_maps.node_extent(body.id);
             let arg_cmt = self.mc.cat_rvalue(
@@ -306,8 +305,8 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         }
     }
 
-    fn tcx(&self) -> TyCtxt<'t, 'tcx> {
-        self.typer.tcx
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
+        self.mc.infcx.tcx
     }
 
     fn delegate_consume(&mut self,
@@ -317,7 +316,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         debug!("delegate_consume(consume_id={}, cmt={:?})",
                consume_id, cmt);
 
-        let mode = copy_or_move(self.typer, &cmt, DirectRefMove);
+        let mode = copy_or_move(self.mc.infcx, &cmt, DirectRefMove);
         self.delegate.consume(consume_id, consume_span, cmt, mode);
     }
 
@@ -442,7 +441,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
             hir::ExprAddrOf(m, ref base) => {   // &base
                 // make sure that the thing we are pointing out stays valid
                 // for the lifetime `scope_r` of the resulting ptr:
-                let expr_ty = return_if_err!(self.typer.node_ty(expr.id));
+                let expr_ty = return_if_err!(self.mc.infcx.node_ty(expr.id));
                 if let ty::TyRef(&r, _) = expr_ty.sty {
                     let bk = ty::BorrowKind::from_mutbl(m);
                     self.borrow_expr(&base, r, bk, AddrOf);
@@ -548,7 +547,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     }
 
     fn walk_callee(&mut self, call: &hir::Expr, callee: &hir::Expr) {
-        let callee_ty = return_if_err!(self.typer.expr_ty_adjusted(callee));
+        let callee_ty = return_if_err!(self.mc.infcx.expr_ty_adjusted(callee));
         debug!("walk_callee: callee={:?} callee_ty={:?}",
                callee, callee_ty);
         let call_scope = self.tcx().region_maps.node_extent(call.id);
@@ -559,7 +558,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
             ty::TyError => { }
             _ => {
                 let overloaded_call_type =
-                    match self.typer.node_method_id(ty::MethodCall::expr(call.id)) {
+                    match self.mc.infcx.node_method_id(ty::MethodCall::expr(call.id)) {
                         Some(method_id) => {
                             OverloadedCallType::from_method_id(self.tcx(), method_id)
                         }
@@ -615,7 +614,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         match local.init {
             None => {
                 let delegate = &mut self.delegate;
-                pat_util::pat_bindings(&self.typer.tcx.def_map, &local.pat,
+                pat_util::pat_bindings(&self.mc.infcx.tcx.def_map, &local.pat,
                                        |_, id, span, _| {
                     delegate.decl_without_init(id, span);
                 })
@@ -707,9 +706,9 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
     // consumed or borrowed as part of the automatic adjustment
     // process.
     fn walk_adjustment(&mut self, expr: &hir::Expr) {
-        let typer = self.typer;
+        let infcx = self.mc.infcx;
         //NOTE(@jroesch): mixed RefCell borrow causes crash
-        let adj = typer.adjustments().get(&expr.id).map(|x| x.clone());
+        let adj = infcx.adjustments().get(&expr.id).map(|x| x.clone());
         if let Some(adjustment) = adj {
             match adjustment {
                 adjustment::AdjustReifyFnPointer |
@@ -739,7 +738,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
 
         for i in 0..autoderefs {
             let deref_id = ty::MethodCall::autoderef(expr.id, i as u32);
-            match self.typer.node_method_ty(deref_id) {
+            match self.mc.infcx.node_method_ty(deref_id) {
                 None => {}
                 Some(method_ty) => {
                     let cmt = return_if_err!(self.mc.cat_expr_autoderefd(expr, i));
@@ -865,7 +864,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                                 pass_args: PassArgs)
                                 -> bool
     {
-        if !self.typer.is_method_call(expr.id) {
+        if !self.mc.infcx.is_method_call(expr.id) {
             return false;
         }
 
@@ -941,7 +940,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                     PatKind::Ident(hir::BindByRef(_), _, _) =>
                         mode.lub(BorrowingMatch),
                     PatKind::Ident(hir::BindByValue(_), _, _) => {
-                        match copy_or_move(self.typer, &cmt_pat, PatBindingMove) {
+                        match copy_or_move(self.mc.infcx, &cmt_pat, PatBindingMove) {
                             Copy => mode.lub(CopyingMatch),
                             Move(_) => mode.lub(MovingMatch),
                         }
@@ -967,7 +966,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                pat);
 
         let mc = &self.mc;
-        let typer = self.typer;
+        let infcx = self.mc.infcx;
         let def_map = &self.tcx().def_map;
         let delegate = &mut self.delegate;
         return_if_err!(mc.cat_pattern(cmt_discr.clone(), pat, |mc, cmt_pat, pat| {
@@ -978,7 +977,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                        match_mode);
 
                 // pat_ty: the type of the binding being produced.
-                let pat_ty = return_if_err!(typer.node_ty(pat.id));
+                let pat_ty = return_if_err!(infcx.node_ty(pat.id));
 
                 // Each match binding is effectively an assignment to the
                 // binding being produced.
@@ -1000,7 +999,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                         }
                     }
                     PatKind::Ident(hir::BindByValue(_), _, _) => {
-                        let mode = copy_or_move(typer, &cmt_pat, PatBindingMove);
+                        let mode = copy_or_move(infcx, &cmt_pat, PatBindingMove);
                         debug!("walk_pat binding consuming pat");
                         delegate.consume_pat(pat, cmt_pat, mode);
                     }
@@ -1057,7 +1056,7 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         // the leaves of the pattern tree structure.
         return_if_err!(mc.cat_pattern(cmt_discr, pat, |mc, cmt_pat, pat| {
             let def_map = def_map.borrow();
-            let tcx = typer.tcx;
+            let tcx = infcx.tcx;
 
             match pat.node {
                 PatKind::TupleStruct(..) | PatKind::Path(..) | PatKind::QPath(..) |
@@ -1150,13 +1149,13 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
                 let id_var = freevar.def.var_id();
                 let upvar_id = ty::UpvarId { var_id: id_var,
                                              closure_expr_id: closure_expr.id };
-                let upvar_capture = self.typer.upvar_capture(upvar_id).unwrap();
+                let upvar_capture = self.mc.infcx.upvar_capture(upvar_id).unwrap();
                 let cmt_var = return_if_err!(self.cat_captured_var(closure_expr.id,
                                                                    fn_decl_span,
                                                                    freevar.def));
                 match upvar_capture {
                     ty::UpvarCapture::ByValue => {
-                        let mode = copy_or_move(self.typer, &cmt_var, CaptureMove);
+                        let mode = copy_or_move(self.mc.infcx, &cmt_var, CaptureMove);
                         self.delegate.consume(closure_expr.id, freevar.span, cmt_var, mode);
                     }
                     ty::UpvarCapture::ByRef(upvar_borrow) => {
@@ -1180,17 +1179,17 @@ impl<'d,'t,'a,'tcx> ExprUseVisitor<'d,'t,'a,'tcx> {
         // Create the cmt for the variable being borrowed, from the
         // caller's perspective
         let var_id = upvar_def.var_id();
-        let var_ty = self.typer.node_ty(var_id)?;
+        let var_ty = self.mc.infcx.node_ty(var_id)?;
         self.mc.cat_def(closure_id, closure_span, var_ty, upvar_def)
     }
 }
 
-fn copy_or_move<'a, 'tcx>(typer: &infer::InferCtxt<'a, 'tcx>,
-                      cmt: &mc::cmt<'tcx>,
-                      move_reason: MoveReason)
-                      -> ConsumeMode
+fn copy_or_move<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
+                          cmt: &mc::cmt<'tcx>,
+                          move_reason: MoveReason)
+                          -> ConsumeMode
 {
-    if typer.type_moves_by_default(cmt.ty, cmt.span) {
+    if infcx.type_moves_by_default(cmt.ty, cmt.span) {
         Move(move_reason)
     } else {
         Copy
diff --git a/src/librustc/middle/free_region.rs b/src/librustc/middle/free_region.rs
index e4ce8976713..90d4627c93d 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(&self,
-                           tcx: TyCtxt,
-                           sub_region: ty::Region,
-                           super_region: ty::Region)
-                           -> bool {
+    pub fn is_subregion_of<'a, 'tcx>(&self,
+                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     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/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index ee201335b11..e87de2875dd 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -22,7 +22,7 @@ use syntax::codemap::Span;
 use hir::intravisit::{self, Visitor, FnKind};
 use hir;
 
-pub fn check_crate(tcx: TyCtxt) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut visitor = ItemVisitor {
         tcx: tcx
     };
@@ -30,7 +30,7 @@ pub fn check_crate(tcx: TyCtxt) {
 }
 
 struct ItemVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>
+    tcx: TyCtxt<'a, 'tcx, 'tcx>
 }
 
 impl<'a, 'tcx> ItemVisitor<'a, 'tcx> {
@@ -46,11 +46,11 @@ impl<'a, 'tcx> ItemVisitor<'a, 'tcx> {
     }
 }
 
-struct ExprVisitor<'a, 'tcx: 'a> {
-    infcx: &'a InferCtxt<'a, 'tcx>
+struct ExprVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>
 }
 
-impl<'a, 'tcx> ExprVisitor<'a, 'tcx> {
+impl<'a, 'tcx> ExprVisitor<'a, 'tcx, 'tcx> {
     fn def_id_is_transmute(&self, def_id: DefId) -> bool {
         let intrinsic = match self.infcx.tcx.lookup_item_type(def_id).ty.sty {
             ty::TyFnDef(_, _, ref bfty) => bfty.abi == RustIntrinsic,
@@ -159,7 +159,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ItemVisitor<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'tcx> {
+impl<'a, 'tcx, 'v> Visitor<'v> for ExprVisitor<'a, 'tcx, 'tcx> {
     fn visit_expr(&mut self, expr: &hir::Expr) {
         if let hir::ExprPath(..) = expr.node {
             match self.infcx.tcx.resolve_expr(expr) {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 2d269133932..eeace7f658d 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -195,7 +195,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IrMaps<'a, 'tcx> {
     fn visit_arm(&mut self, a: &hir::Arm) { visit_arm(self, a); }
 }
 
-pub fn check_crate(tcx: TyCtxt) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _task = tcx.dep_graph.in_task(DepNode::Liveness);
     tcx.map.krate().visit_all_items(&mut IrMaps::new(tcx));
     tcx.sess.abort_if_errors();
@@ -263,7 +263,7 @@ enum VarKind {
 }
 
 struct IrMaps<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     num_live_nodes: usize,
     num_vars: usize,
@@ -275,7 +275,7 @@ struct IrMaps<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> IrMaps<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx>) -> IrMaps<'a, 'tcx> {
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> IrMaps<'a, 'tcx> {
         IrMaps {
             tcx: tcx,
             num_live_nodes: 0,
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index 9faae0c098d..53e6102587b 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -73,7 +73,7 @@ use self::Aliasability::*;
 
 use hir::def_id::DefId;
 use hir::map as ast_map;
-use infer;
+use infer::InferCtxt;
 use middle::const_qualif::ConstQualif;
 use hir::def::Def;
 use ty::adjustment;
@@ -256,8 +256,8 @@ impl ast_node for hir::Pat {
 }
 
 #[derive(Copy, Clone)]
-pub struct MemCategorizationContext<'t, 'a: 't, 'tcx : 'a> {
-    pub typer: &'t infer::InferCtxt<'a, 'tcx>,
+pub struct MemCategorizationContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    pub infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
 }
 
 pub type McResult<T> = Result<T, ()>;
@@ -302,7 +302,9 @@ impl MutabilityCategory {
         ret
     }
 
-    fn from_local(tcx: TyCtxt, id: ast::NodeId) -> MutabilityCategory {
+    fn from_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            id: ast::NodeId)
+                            -> MutabilityCategory {
         let ret = match tcx.map.get(id) {
             ast_map::NodeLocal(p) => match p.node {
                 PatKind::Ident(bind_mode, _, _) => {
@@ -358,17 +360,18 @@ impl MutabilityCategory {
     }
 }
 
-impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
-    pub fn new(typer: &'t infer::InferCtxt<'a, 'tcx>) -> MemCategorizationContext<'t, 'a, 'tcx> {
-        MemCategorizationContext { typer: typer }
+impl<'a, 'tcx> MemCategorizationContext<'a, 'tcx, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>)
+               -> MemCategorizationContext<'a, 'tcx, 'tcx> {
+        MemCategorizationContext { infcx: infcx }
     }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> {
-        self.typer.tcx
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
+        self.infcx.tcx
     }
 
     fn expr_ty(&self, expr: &hir::Expr) -> McResult<Ty<'tcx>> {
-        match self.typer.node_ty(expr.id) {
+        match self.infcx.node_ty(expr.id) {
             Ok(t) => Ok(t),
             Err(()) => {
                 debug!("expr_ty({:?}) yielded Err", expr);
@@ -381,16 +384,16 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         let unadjusted_ty = self.expr_ty(expr)?;
         Ok(unadjusted_ty.adjust(
             self.tcx(), expr.span, expr.id,
-            self.typer.adjustments().get(&expr.id),
-            |method_call| self.typer.node_method_ty(method_call)))
+            self.infcx.adjustments().get(&expr.id),
+            |method_call| self.infcx.node_method_ty(method_call)))
     }
 
     fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
-        self.typer.node_ty(id)
+        self.infcx.node_ty(id)
     }
 
     fn pat_ty(&self, pat: &hir::Pat) -> McResult<Ty<'tcx>> {
-        let base_ty = self.typer.node_ty(pat.id)?;
+        let base_ty = self.infcx.node_ty(pat.id)?;
         // FIXME (Issue #18207): This code detects whether we are
         // looking at a `ref x`, and if so, figures out what the type
         // *being borrowed* is.  But ideally we would put in a more
@@ -413,7 +416,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
     }
 
     pub fn cat_expr(&self, expr: &hir::Expr) -> McResult<cmt<'tcx>> {
-        match self.typer.adjustments().get(&expr.id) {
+        match self.infcx.adjustments().get(&expr.id) {
             None => {
                 // No adjustments.
                 self.cat_expr_unadjusted(expr)
@@ -485,7 +488,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
           hir::ExprIndex(ref base, _) => {
             let method_call = ty::MethodCall::expr(expr.id());
             let context = InteriorOffsetKind::Index;
-            match self.typer.node_method_ty(method_call) {
+            match self.infcx.node_method_ty(method_call) {
                 Some(method_ty) => {
                     // If this is an index implemented by a method call, then it
                     // will include an implicit deref of the result.
@@ -578,7 +581,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
               let ty = self.node_ty(fn_node_id)?;
               match ty.sty {
                   ty::TyClosure(closure_id, _) => {
-                      match self.typer.closure_kind(closure_id) {
+                      match self.infcx.closure_kind(closure_id) {
                           Some(kind) => {
                               self.cat_upvar(id, span, var_id, fn_node_id, kind)
                           }
@@ -687,7 +690,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         // for that.
         let upvar_id = ty::UpvarId { var_id: var_id,
                                      closure_expr_id: fn_node_id };
-        let upvar_capture = self.typer.upvar_capture(upvar_id).unwrap();
+        let upvar_capture = self.infcx.upvar_capture(upvar_id).unwrap();
         let cmt_result = match upvar_capture {
             ty::UpvarCapture::ByValue => {
                 cmt_result
@@ -785,7 +788,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
     /// Returns the lifetime of a temporary created by expr with id `id`.
     /// This could be `'static` if `id` is part of a constant expression.
     pub fn temporary_scope(&self, id: ast::NodeId) -> ty::Region {
-        match self.typer.temporary_scope(id) {
+        match self.infcx.temporary_scope(id) {
             Some(scope) => ty::ReScope(scope),
             None => ty::ReStatic
         }
@@ -882,7 +885,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
             expr_id: node.id(),
             autoderef: deref_cnt as u32
         };
-        let method_ty = self.typer.node_method_ty(method_call);
+        let method_ty = self.infcx.node_method_ty(method_call);
 
         debug!("cat_deref: method_call={:?} method_ty={:?}",
                method_call, method_ty.map(|ty| ty));
@@ -977,7 +980,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
         //! - `base_cmt`: the cmt of `elt`
 
         let method_call = ty::MethodCall::expr(elt.id());
-        let method_ty = self.typer.node_method_ty(method_call);
+        let method_ty = self.infcx.node_method_ty(method_call);
 
         let element_ty = match method_ty {
             Some(method_ty) => {
@@ -1082,10 +1085,10 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, '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(tcx: TyCtxt,
-                          pat: &hir::Pat,
-                          slice_ty: Ty)
-                          -> (hir::Mutability, ty::Region) {
+        fn vec_slice_info<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                    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),
@@ -1137,7 +1140,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, 'tcx> {
     }
 
     pub fn cat_pattern<F>(&self, cmt: cmt<'tcx>, pat: &hir::Pat, mut op: F) -> McResult<()>
-        where F: FnMut(&MemCategorizationContext<'t, 'a, 'tcx>, cmt<'tcx>, &hir::Pat),
+        where F: FnMut(&MemCategorizationContext<'a, 'tcx, 'tcx>, cmt<'tcx>, &hir::Pat),
     {
         self.cat_pattern_(cmt, pat, &mut op)
     }
@@ -1145,7 +1148,7 @@ impl<'t, 'a,'tcx> MemCategorizationContext<'t, 'a, '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<'t, 'a, 'tcx>, cmt<'tcx>, &hir::Pat),
+        where F : FnMut(&MemCategorizationContext<'a, 'tcx, '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.
@@ -1463,7 +1466,7 @@ impl<'tcx> cmt_<'tcx> {
     }
 
 
-    pub fn descriptive_string(&self, tcx: TyCtxt) -> String {
+    pub fn descriptive_string<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
         match self.cat {
             Categorization::StaticItem => {
                 "static item".to_string()
diff --git a/src/librustc/middle/reachable.rs b/src/librustc/middle/reachable.rs
index b2036d7a4c0..bca5af69edf 100644
--- a/src/librustc/middle/reachable.rs
+++ b/src/librustc/middle/reachable.rs
@@ -55,9 +55,10 @@ fn item_might_be_inlined(item: &hir::Item) -> bool {
     }
 }
 
-fn method_might_be_inlined(tcx: TyCtxt, sig: &hir::MethodSig,
-                           impl_item: &hir::ImplItem,
-                           impl_src: DefId) -> bool {
+fn method_might_be_inlined<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     sig: &hir::MethodSig,
+                                     impl_item: &hir::ImplItem,
+                                     impl_src: DefId) -> bool {
     if attr::requests_inline(&impl_item.attrs) ||
         generics_require_inlining(&sig.generics) {
         return true
@@ -77,7 +78,7 @@ fn method_might_be_inlined(tcx: TyCtxt, sig: &hir::MethodSig,
 // Information needed while computing reachability.
 struct ReachableContext<'a, 'tcx: 'a> {
     // The type context.
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     // The set of items which must be exported in the linkage sense.
     reachable_symbols: NodeSet,
     // A worklist of item IDs. Each item ID in this worklist will be inlined
@@ -142,7 +143,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ReachableContext<'a, 'tcx> {
 
 impl<'a, 'tcx> ReachableContext<'a, 'tcx> {
     // Creates a new reachability computation context.
-    fn new(tcx: TyCtxt<'a, 'tcx>) -> ReachableContext<'a, 'tcx> {
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ReachableContext<'a, 'tcx> {
         let any_library = tcx.sess.crate_types.borrow().iter().any(|ty| {
             *ty != config::CrateTypeExecutable
         });
@@ -344,9 +345,9 @@ impl<'a, 'v> Visitor<'v> for CollectPrivateImplItemsVisitor<'a> {
     }
 }
 
-pub fn find_reachable(tcx: TyCtxt,
-                      access_levels: &privacy::AccessLevels)
-                      -> NodeSet {
+pub fn find_reachable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                access_levels: &privacy::AccessLevels)
+                                -> NodeSet {
     let _task = tcx.dep_graph.in_task(DepNode::Reachability);
 
     let mut reachable_context = ReachableContext::new(tcx);
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index 6edbb6c584f..9fabdf58b6f 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -72,7 +72,7 @@ pub struct Index<'tcx> {
 
 // A private tree-walker for producing an Index.
 struct Annotator<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     index: &'a mut Index<'tcx>,
     parent_stab: Option<&'tcx Stability>,
     parent_depr: Option<Deprecation>,
@@ -280,7 +280,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for Annotator<'a, 'tcx> {
 
 impl<'a, 'tcx> Index<'tcx> {
     /// Construct the stability index for a crate being compiled.
-    pub fn build(&mut self, tcx: TyCtxt<'a, 'tcx>, access_levels: &AccessLevels) {
+    pub fn build(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, access_levels: &AccessLevels) {
         let _task = tcx.dep_graph.in_task(DepNode::StabilityIndex);
         let krate = tcx.map.krate();
         let mut annotator = Annotator {
@@ -320,8 +320,8 @@ impl<'a, 'tcx> Index<'tcx> {
 /// Cross-references the feature names of unstable APIs with enabled
 /// features and possibly prints errors. Returns a list of all
 /// features used.
-pub fn check_unstable_api_usage(tcx: TyCtxt)
-                                -> FnvHashMap<InternedString, StabilityLevel> {
+pub fn check_unstable_api_usage<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                                          -> FnvHashMap<InternedString, StabilityLevel> {
     let _task = tcx.dep_graph.in_task(DepNode::StabilityCheck);
     let ref active_lib_features = tcx.sess.features.borrow().declared_lib_features;
 
@@ -340,7 +340,7 @@ pub fn check_unstable_api_usage(tcx: TyCtxt)
 }
 
 struct Checker<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     active_features: FnvHashSet<InternedString>,
     used_features: FnvHashMap<InternedString, StabilityLevel>,
     // Within a block where feature gate checking can be skipped.
@@ -468,8 +468,12 @@ impl<'a, 'v, 'tcx> Visitor<'v> for Checker<'a, 'tcx> {
 }
 
 /// Helper for discovering nodes to check for stability
-pub fn check_item(tcx: TyCtxt, item: &hir::Item, warn_about_defns: bool,
-                  cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
+pub fn check_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            item: &hir::Item,
+                            warn_about_defns: bool,
+                            cb: &mut FnMut(DefId, Span,
+                                           &Option<&Stability>,
+                                           &Option<Deprecation>)) {
     match item.node {
         hir::ItemExternCrate(_) => {
             // compiler-generated `extern crate` items have a dummy span.
@@ -505,8 +509,10 @@ pub fn check_item(tcx: TyCtxt, item: &hir::Item, warn_about_defns: bool,
 }
 
 /// Helper for discovering nodes to check for stability
-pub fn check_expr(tcx: TyCtxt, e: &hir::Expr,
-                  cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
+pub fn check_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, e: &hir::Expr,
+                            cb: &mut FnMut(DefId, Span,
+                                           &Option<&Stability>,
+                                           &Option<Deprecation>)) {
     let span;
     let id = match e.node {
         hir::ExprMethodCall(i, _, _) => {
@@ -566,8 +572,11 @@ pub fn check_expr(tcx: TyCtxt, e: &hir::Expr,
     maybe_do_stability_check(tcx, id, span, cb);
 }
 
-pub fn check_path(tcx: TyCtxt, path: &hir::Path, id: ast::NodeId,
-                  cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
+pub fn check_path<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            path: &hir::Path, id: ast::NodeId,
+                            cb: &mut FnMut(DefId, Span,
+                                           &Option<&Stability>,
+                                           &Option<Deprecation>)) {
     match tcx.def_map.borrow().get(&id).map(|d| d.full_def()) {
         Some(Def::PrimTy(..)) => {}
         Some(Def::SelfTy(..)) => {}
@@ -578,8 +587,11 @@ pub fn check_path(tcx: TyCtxt, path: &hir::Path, id: ast::NodeId,
     }
 }
 
-pub fn check_path_list_item(tcx: TyCtxt, item: &hir::PathListItem,
-                  cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
+pub fn check_path_list_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                      item: &hir::PathListItem,
+                                      cb: &mut FnMut(DefId, Span,
+                                                     &Option<&Stability>,
+                                                     &Option<Deprecation>)) {
     match tcx.def_map.borrow().get(&item.node.id()).map(|d| d.full_def()) {
         Some(Def::PrimTy(..)) => {}
         Some(def) => {
@@ -589,8 +601,10 @@ pub fn check_path_list_item(tcx: TyCtxt, item: &hir::PathListItem,
     }
 }
 
-pub fn check_pat(tcx: TyCtxt, pat: &hir::Pat,
-                 cb: &mut FnMut(DefId, Span, &Option<&Stability>, &Option<Deprecation>)) {
+pub fn check_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pat: &hir::Pat,
+                           cb: &mut FnMut(DefId, Span,
+                                          &Option<&Stability>,
+                                          &Option<Deprecation>)) {
     debug!("check_pat(pat = {:?})", pat);
     if is_internal(tcx, pat.span) { return; }
 
@@ -618,9 +632,11 @@ pub fn check_pat(tcx: TyCtxt, pat: &hir::Pat,
     }
 }
 
-fn maybe_do_stability_check(tcx: TyCtxt, id: DefId, span: Span,
-                            cb: &mut FnMut(DefId, Span,
-                                           &Option<&Stability>, &Option<Deprecation>)) {
+fn maybe_do_stability_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                      id: DefId, span: Span,
+                                      cb: &mut FnMut(DefId, Span,
+                                                     &Option<&Stability>,
+                                                     &Option<Deprecation>)) {
     if is_internal(tcx, span) {
         debug!("maybe_do_stability_check: \
                 skipping span={:?} since it is internal", span);
@@ -636,11 +652,11 @@ fn maybe_do_stability_check(tcx: TyCtxt, id: DefId, span: Span,
     cb(id, span, &stability, &deprecation);
 }
 
-fn is_internal(tcx: TyCtxt, span: Span) -> bool {
+fn is_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, span: Span) -> bool {
     tcx.sess.codemap().span_allows_unstable(span)
 }
 
-fn is_staged_api(tcx: TyCtxt, id: DefId) -> bool {
+fn is_staged_api<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefId) -> bool {
     match tcx.trait_item_of_item(id) {
         Some(ty::MethodTraitItemId(trait_method_id))
             if trait_method_id != id => {
@@ -653,7 +669,7 @@ fn is_staged_api(tcx: TyCtxt, id: DefId) -> bool {
     }
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
 /// Lookup the stability for a node, loading external crate
 /// metadata as necessary.
 pub fn lookup_stability(self, id: DefId) -> Option<&'tcx Stability> {
diff --git a/src/librustc/mir/tcx.rs b/src/librustc/mir/tcx.rs
index 3d59f8965ed..b122907b64d 100644
--- a/src/librustc/mir/tcx.rs
+++ b/src/librustc/mir/tcx.rs
@@ -35,7 +35,7 @@ impl<'a, 'tcx> LvalueTy<'tcx> {
         LvalueTy::Ty { ty: ty }
     }
 
-    pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    pub fn to_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         match *self {
             LvalueTy::Ty { ty } =>
                 ty,
@@ -44,7 +44,7 @@ impl<'a, 'tcx> LvalueTy<'tcx> {
         }
     }
 
-    pub fn projection_ty(self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn projection_ty(self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          elem: &LvalueElem<'tcx>)
                          -> LvalueTy<'tcx>
     {
@@ -101,7 +101,7 @@ impl<'tcx> TypeFoldable<'tcx> for LvalueTy<'tcx> {
 }
 
 impl<'a, 'tcx> Mir<'tcx> {
-    pub fn operand_ty(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn operand_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                       operand: &Operand<'tcx>)
                       -> Ty<'tcx>
     {
@@ -111,7 +111,7 @@ impl<'a, 'tcx> Mir<'tcx> {
         }
     }
 
-    pub fn binop_ty(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn binop_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     op: BinOp,
                     lhs_ty: Ty<'tcx>,
                     rhs_ty: Ty<'tcx>)
@@ -135,7 +135,7 @@ impl<'a, 'tcx> Mir<'tcx> {
         }
     }
 
-    pub fn lvalue_ty(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn lvalue_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                      lvalue: &Lvalue<'tcx>)
                      -> LvalueTy<'tcx>
     {
@@ -155,7 +155,7 @@ impl<'a, 'tcx> Mir<'tcx> {
         }
     }
 
-    pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn rvalue_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                      rvalue: &Rvalue<'tcx>)
                      -> Option<Ty<'tcx>>
     {
diff --git a/src/librustc/mir/transform.rs b/src/librustc/mir/transform.rs
index 1d8ca5f84d1..79c44b2b851 100644
--- a/src/librustc/mir/transform.rs
+++ b/src/librustc/mir/transform.rs
@@ -33,8 +33,8 @@ pub enum MirSource {
     Promoted(NodeId, usize)
 }
 
-impl MirSource {
-    pub fn from_node(tcx: TyCtxt, id: NodeId) -> MirSource {
+impl<'a, 'tcx> MirSource {
+    pub fn from_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> MirSource {
         use hir::*;
 
         // Handle constants in enum discriminants, types, and repeat expressions.
@@ -79,21 +79,22 @@ pub trait Pass {
 
 /// A pass which inspects the whole MirMap.
 pub trait MirMapPass<'tcx>: Pass {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>, map: &mut MirMap<'tcx>);
+    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>);
 }
 
 /// A pass which inspects Mir of functions in isolation.
 pub trait MirPass<'tcx>: Pass {
-    fn run_pass_on_promoted<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>,
+    fn run_pass_on_promoted<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                 item_id: NodeId, index: usize,
                                 mir: &mut Mir<'tcx>) {
         self.run_pass(tcx, MirSource::Promoted(item_id, index), mir);
     }
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>);
+    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    src: MirSource, mir: &mut Mir<'tcx>);
 }
 
 impl<'tcx, T: MirPass<'tcx>> MirMapPass<'tcx> for T {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>, map: &mut MirMap<'tcx>) {
+    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
         for (&id, mir) in &mut map.map {
             let def_id = tcx.map.local_def_id(id);
             let _task = tcx.dep_graph.in_task(self.dep_node(def_id));
@@ -123,7 +124,7 @@ impl<'a, 'tcx> Passes {
         passes
     }
 
-    pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx>, map: &mut MirMap<'tcx>) {
+    pub fn run_passes(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
         for pass in &mut self.plugin_passes {
             pass.run_pass(tcx, map);
         }
diff --git a/src/librustc/traits/coherence.rs b/src/librustc/traits/coherence.rs
index 03478eaf61a..8802f98d54a 100644
--- a/src/librustc/traits/coherence.rs
+++ b/src/librustc/traits/coherence.rs
@@ -24,7 +24,7 @@ struct InferIsLocal(bool);
 
 /// If there are types that satisfy both impls, returns a suitably-freshened
 /// `ImplHeader` with those types substituted
-pub fn overlapping_impls<'cx, 'tcx>(infcx: &InferCtxt<'cx, 'tcx>,
+pub fn overlapping_impls<'cx, 'tcx>(infcx: &InferCtxt<'cx, 'tcx, 'tcx>,
                                     impl1_def_id: DefId,
                                     impl2_def_id: DefId)
                                     -> Option<ty::ImplHeader<'tcx>>
@@ -41,7 +41,7 @@ pub fn overlapping_impls<'cx, 'tcx>(infcx: &InferCtxt<'cx, 'tcx>,
 
 /// Can both impl `a` and impl `b` be satisfied by a common type (including
 /// `where` clauses)? If so, returns an `ImplHeader` that unifies the two impls.
-fn overlap<'cx, 'tcx>(selcx: &mut SelectionContext<'cx, 'tcx>,
+fn overlap<'cx, 'tcx>(selcx: &mut SelectionContext<'cx, 'tcx, 'tcx>,
                       a_def_id: DefId,
                       b_def_id: DefId)
                       -> Option<ty::ImplHeader<'tcx>>
@@ -86,7 +86,7 @@ fn overlap<'cx, 'tcx>(selcx: &mut SelectionContext<'cx, 'tcx>,
     Some(selcx.infcx().resolve_type_vars_if_possible(&a_impl_header))
 }
 
-pub fn trait_ref_is_knowable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn trait_ref_is_knowable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        trait_ref: &ty::TraitRef<'tcx>) -> bool
 {
     debug!("trait_ref_is_knowable(trait_ref={:?})", trait_ref);
@@ -129,7 +129,7 @@ pub enum OrphanCheckErr<'tcx> {
 ///
 /// 1. All type parameters in `Self` must be "covered" by some local type constructor.
 /// 2. Some local type must appear in `Self`.
-pub fn orphan_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn orphan_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               impl_def_id: DefId)
                               -> Result<(), OrphanCheckErr<'tcx>>
 {
@@ -150,7 +150,7 @@ pub fn orphan_check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
     orphan_check_trait_ref(tcx, &trait_ref, InferIsLocal(false))
 }
 
-fn orphan_check_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn orphan_check_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     trait_ref: &ty::TraitRef<'tcx>,
                                     infer_is_local: InferIsLocal)
                                     -> Result<(), OrphanCheckErr<'tcx>>
@@ -198,7 +198,7 @@ fn orphan_check_trait_ref<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
     return Err(OrphanCheckErr::NoLocalInputType);
 }
 
-fn uncovered_tys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn uncovered_tys<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            ty: Ty<'tcx>,
                            infer_is_local: InferIsLocal)
                            -> Vec<Ty<'tcx>>
@@ -222,13 +222,15 @@ fn is_type_parameter<'tcx>(ty: Ty<'tcx>) -> bool {
     }
 }
 
-fn ty_is_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, ty: Ty<'tcx>, infer_is_local: InferIsLocal) -> bool
+fn ty_is_local<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         ty: Ty<'tcx>,
+                         infer_is_local: InferIsLocal) -> bool
 {
     ty_is_local_constructor(tcx, ty, infer_is_local) ||
         fundamental_ty(tcx, ty) && ty.walk_shallow().any(|t| ty_is_local(tcx, t, infer_is_local))
 }
 
-fn fundamental_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> bool
+fn fundamental_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool
 {
     match ty.sty {
         ty::TyBox(..) | ty::TyRef(..) =>
@@ -242,7 +244,7 @@ fn fundamental_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> bool
     }
 }
 
-fn ty_is_local_constructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn ty_is_local_constructor<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      ty: Ty<'tcx>,
                                      infer_is_local: InferIsLocal)
                                      -> bool
diff --git a/src/librustc/traits/error_reporting.rs b/src/librustc/traits/error_reporting.rs
index f1fe990863a..786f58f20cc 100644
--- a/src/librustc/traits/error_reporting.rs
+++ b/src/librustc/traits/error_reporting.rs
@@ -47,7 +47,7 @@ pub struct TraitErrorKey<'tcx> {
 }
 
 impl<'tcx> TraitErrorKey<'tcx> {
-    fn from_error<'a>(infcx: &InferCtxt<'a, 'tcx>,
+    fn from_error<'a>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                       e: &FulfillmentError<'tcx>,
                       warning_node_id: Option<ast::NodeId>) -> Self {
         let predicate =
@@ -60,7 +60,7 @@ impl<'tcx> TraitErrorKey<'tcx> {
     }
 }
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'a, 'tcx> InferCtxt<'a, 'tcx, 'tcx> {
 pub fn report_fulfillment_errors(&self, errors: &Vec<FulfillmentError<'tcx>>) {
     for error in errors {
         self.report_fulfillment_error(error, None);
@@ -558,7 +558,7 @@ pub fn report_selection_error(&self,
 }
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
 pub fn recursive_type_with_infinite_size_error(self,
                                                type_def_id: DefId)
                                                -> DiagnosticBuilder<'tcx>
@@ -646,7 +646,7 @@ pub fn report_object_safety_error(self,
 }
 }
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'a, 'tcx> InferCtxt<'a, 'tcx, 'tcx> {
 fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
     // Unable to successfully determine, probably means
     // insufficient type information, but could mean
@@ -738,13 +738,13 @@ fn maybe_report_ambiguity(&self, obligation: &PredicateObligation<'tcx>) {
 /// to the type parameters.
 fn predicate_can_apply(&self, pred: ty::PolyTraitRef<'tcx>) -> bool {
     struct ParamToVarFolder<'a, 'tcx: 'a> {
-        infcx: &'a InferCtxt<'a, 'tcx>,
+        infcx: &'a InferCtxt<'a, 'tcx, 'tcx>,
         var_map: FnvHashMap<Ty<'tcx>, Ty<'tcx>>
     }
 
     impl<'a, 'tcx> TypeFolder<'tcx> for ParamToVarFolder<'a, 'tcx>
     {
-        fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> { self.infcx.tcx }
+        fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.infcx.tcx }
 
         fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
             if let ty::TyParam(..) = ty.sty {
diff --git a/src/librustc/traits/fulfill.rs b/src/librustc/traits/fulfill.rs
index c7061fc8c2f..9d87be36ecc 100644
--- a/src/librustc/traits/fulfill.rs
+++ b/src/librustc/traits/fulfill.rs
@@ -130,7 +130,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     /// something concrete. If this fails, we'll unify `$0` with
     /// `projection_ty` again.
     pub fn normalize_projection_type(&mut self,
-                                     infcx: &InferCtxt<'a,'tcx>,
+                                     infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                      projection_ty: ty::ProjectionTy<'tcx>,
                                      cause: ObligationCause<'tcx>)
                                      -> Ty<'tcx>
@@ -155,7 +155,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     }
 
     pub fn register_builtin_bound(&mut self,
-                                  infcx: &InferCtxt<'a, 'tcx>,
+                                  infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                   ty: Ty<'tcx>,
                                   builtin_bound: ty::BuiltinBound,
                                   cause: ObligationCause<'tcx>)
@@ -177,7 +177,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     }
 
     pub fn register_predicate_obligation(&mut self,
-                                         infcx: &InferCtxt<'a, 'tcx>,
+                                         infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                          obligation: PredicateObligation<'tcx>)
     {
         // this helps to reduce duplicate errors, as well as making
@@ -200,7 +200,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     }
 
     pub fn register_rfc1592_obligation(&mut self,
-                                       _infcx: &InferCtxt<'a,'tcx>,
+                                       _infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                        obligation: PredicateObligation<'tcx>)
     {
         self.rfc1592_obligations.push(obligation);
@@ -217,7 +217,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     }
 
     pub fn select_rfc1592_obligations(&mut self,
-                                      infcx: &InferCtxt<'a,'tcx>)
+                                      infcx: &InferCtxt<'a, 'tcx, 'tcx>)
                                       -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
         while !self.rfc1592_obligations.is_empty() {
@@ -232,7 +232,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     }
 
     pub fn select_all_or_error(&mut self,
-                               infcx: &InferCtxt<'a,'tcx>)
+                               infcx: &InferCtxt<'a, 'tcx, 'tcx>)
                                -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
         self.select_where_possible(infcx)?;
@@ -250,7 +250,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
     }
 
     pub fn select_where_possible(&mut self,
-                                 infcx: &InferCtxt<'a, 'tcx>)
+                                 infcx: &InferCtxt<'a, 'tcx, 'tcx>)
                                  -> Result<(),Vec<FulfillmentError<'tcx>>>
     {
         let mut selcx = SelectionContext::new(infcx);
@@ -261,7 +261,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
         self.predicates.pending_obligations()
     }
 
-    fn is_duplicate_or_add(&mut self, tcx: TyCtxt<'a, 'tcx>,
+    fn is_duplicate_or_add(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            predicate: &ty::Predicate<'tcx>)
                            -> bool {
         // For "global" predicates -- that is, predicates that don't
@@ -289,7 +289,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
 
     /// Attempts to select obligations using `selcx`. If `only_new_obligations` is true, then it
     /// only attempts to select obligations that haven't been seen before.
-    fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx>)
+    fn select(&mut self, selcx: &mut SelectionContext<'a, 'tcx, 'tcx>)
               -> Result<(),Vec<FulfillmentError<'tcx>>> {
         debug!("select(obligation-forest-size={})", self.predicates.len());
 
@@ -341,7 +341,7 @@ impl<'a, 'tcx> FulfillmentContext<'tcx> {
 }
 
 /// Like `process_predicate1`, but wrap result into a pending predicate.
-fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
+fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx, 'tcx>,
                               tree_cache: &mut LocalFulfilledPredicates<'tcx>,
                               pending_obligation: &mut PendingPredicateObligation<'tcx>,
                               backtrace: Backtrace<PendingPredicateObligation<'tcx>>,
@@ -362,8 +362,8 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
     }
 }
 
-fn process_child_obligations<'a,'tcx>(
-    selcx: &mut SelectionContext<'a,'tcx>,
+fn process_child_obligations<'a, 'tcx>(
+    selcx: &mut SelectionContext<'a, 'tcx, 'tcx>,
     tree_cache: &mut LocalFulfilledPredicates<'tcx>,
     pending_obligation: &PredicateObligation<'tcx>,
     backtrace: Backtrace<PendingPredicateObligation<'tcx>>,
@@ -478,7 +478,7 @@ impl<'a, 'b, 'tcx> AncestorSet<'b, 'tcx> {
     /// type-resolved).  Returns `None` if not; otherwise, returns
     /// `Some` with the index within the backtrace.
     fn has(&mut self,
-           infcx: &InferCtxt<'a, 'tcx>,
+           infcx: &InferCtxt<'a, 'tcx, 'tcx>,
            predicate: &ty::Predicate<'tcx>)
            -> Option<usize> {
         // the first time, we have to populate the cache
@@ -514,7 +514,7 @@ impl<'a, 'b, 'tcx> AncestorSet<'b, 'tcx> {
 }
 
 /// Return the set of type variables contained in a trait ref
-fn trait_ref_type_vars<'a, 'tcx>(selcx: &mut SelectionContext<'a, 'tcx>,
+fn trait_ref_type_vars<'a, 'tcx>(selcx: &mut SelectionContext<'a, 'tcx, 'tcx>,
                                  t: ty::PolyTraitRef<'tcx>) -> Vec<Ty<'tcx>>
 {
     t.skip_binder() // ok b/c this check doesn't care about regions
@@ -531,7 +531,7 @@ fn trait_ref_type_vars<'a, 'tcx>(selcx: &mut SelectionContext<'a, 'tcx>,
 /// - `Ok(Some(v))` if the predicate is true, presuming that `v` are also true
 /// - `Ok(None)` if we don't have enough info to be sure
 /// - `Err` if the predicate does not hold
-fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
+fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx, 'tcx>,
                                pending_obligation: &mut PendingPredicateObligation<'tcx>,
                                region_obligations: &mut NodeMap<Vec<RegionObligation<'tcx>>>,
                                rfc1592_obligations: &mut Vec<PredicateObligation<'tcx>>)
@@ -722,9 +722,9 @@ fn process_predicate1<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
 /// - it also appears in the backtrace at some position `X`; and,
 /// - all the predicates at positions `X..` between `X` an the top are
 ///   also defaulted traits.
-fn coinductive_match<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
-                              cycle: &[PredicateObligation<'tcx>])
-                              -> bool
+fn coinductive_match<'a, 'tcx>(selcx: &mut SelectionContext<'a, 'tcx, 'tcx>,
+                               cycle: &[PredicateObligation<'tcx>])
+                               -> bool
 {
     let len = cycle.len();
 
@@ -740,7 +740,7 @@ fn coinductive_match<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
         })
 }
 
-fn coinductive_obligation<'a, 'tcx>(selcx: &SelectionContext<'a, 'tcx>,
+fn coinductive_obligation<'a, 'tcx>(selcx: &SelectionContext<'a, 'tcx, 'tcx>,
                                     obligation: &PredicateObligation<'tcx>)
                                     -> bool {
     match obligation.predicate {
diff --git a/src/librustc/traits/mod.rs b/src/librustc/traits/mod.rs
index 49851f720cc..25710e86f60 100644
--- a/src/librustc/traits/mod.rs
+++ b/src/librustc/traits/mod.rs
@@ -316,7 +316,7 @@ pub fn predicates_for_generics<'tcx>(cause: ObligationCause<'tcx>,
 /// `bound` or is not known to meet bound (note that this is
 /// conservative towards *no impl*, which is the opposite of the
 /// `evaluate` methods).
-pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
+pub fn type_known_to_meet_builtin_bound<'a,'tcx>(infcx: &InferCtxt<'a,'tcx, 'tcx>,
                                                  ty: Ty<'tcx>,
                                                  bound: ty::BuiltinBound,
                                                  span: Span)
@@ -460,7 +460,7 @@ pub fn normalize_param_env_or_error<'a,'tcx>(unnormalized_env: ty::ParameterEnvi
     infcx.parameter_environment.with_caller_bounds(predicates)
 }
 
-pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
+pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx, 'tcx>,
                                   cause: ObligationCause<'tcx>,
                                   value: &T)
                                   -> Result<T, Vec<FulfillmentError<'tcx>>>
diff --git a/src/librustc/traits/object_safety.rs b/src/librustc/traits/object_safety.rs
index 5419994cdd1..74818e683f1 100644
--- a/src/librustc/traits/object_safety.rs
+++ b/src/librustc/traits/object_safety.rs
@@ -53,7 +53,7 @@ pub enum MethodViolationCode {
     Generic,
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
 pub fn is_object_safe(self, trait_def_id: DefId) -> bool {
     // Because we query yes/no results frequently, we keep a cache:
     let def = self.lookup_trait_def(trait_def_id);
diff --git a/src/librustc/traits/project.rs b/src/librustc/traits/project.rs
index 49f40e1533d..88ec6d65918 100644
--- a/src/librustc/traits/project.rs
+++ b/src/librustc/traits/project.rs
@@ -172,7 +172,7 @@ struct ProjectionTyCandidateSet<'tcx> {
 ///
 /// If successful, this may result in additional obligations.
 pub fn poly_project_and_unify_type<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &PolyProjectionObligation<'tcx>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
 {
@@ -205,7 +205,7 @@ pub fn poly_project_and_unify_type<'cx,'tcx>(
 ///
 /// If successful, this may result in additional obligations.
 fn project_and_unify_type<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionObligation<'tcx>)
     -> Result<Option<Vec<PredicateObligation<'tcx>>>, MismatchedProjectionTypes<'tcx>>
 {
@@ -240,7 +240,7 @@ fn project_and_unify_type<'cx,'tcx>(
     }
 }
 
-fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext<'cx,'tcx>,
+fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
                                                     obligation: &ProjectionObligation<'tcx>) {
     debug!("consider_unification_despite_ambiguity(obligation={:?})",
            obligation);
@@ -295,7 +295,7 @@ fn consider_unification_despite_ambiguity<'cx,'tcx>(selcx: &mut SelectionContext
 /// them with a fully resolved type where possible. The return value
 /// combines the normalized result and any additional obligations that
 /// were incurred as result.
-pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
+pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx, 'tcx>,
                                cause: ObligationCause<'tcx>,
                                value: &T)
                                -> Normalized<'tcx, T>
@@ -305,7 +305,7 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
 }
 
 /// As `normalize`, but with a custom depth.
-pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
+pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx, 'tcx>,
                                           cause: ObligationCause<'tcx>,
                                           depth: usize,
                                           value: &T)
@@ -322,14 +322,14 @@ pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tc
 }
 
 struct AssociatedTypeNormalizer<'a,'b:'a,'tcx:'b> {
-    selcx: &'a mut SelectionContext<'b,'tcx>,
+    selcx: &'a mut SelectionContext<'b,'tcx, 'tcx>,
     cause: ObligationCause<'tcx>,
     obligations: Vec<PredicateObligation<'tcx>>,
     depth: usize,
 }
 
 impl<'a,'b,'tcx> AssociatedTypeNormalizer<'a,'b,'tcx> {
-    fn new(selcx: &'a mut SelectionContext<'b,'tcx>,
+    fn new(selcx: &'a mut SelectionContext<'b,'tcx, 'tcx>,
            cause: ObligationCause<'tcx>,
            depth: usize)
            -> AssociatedTypeNormalizer<'a,'b,'tcx>
@@ -354,7 +354,7 @@ impl<'a,'b,'tcx> AssociatedTypeNormalizer<'a,'b,'tcx> {
 }
 
 impl<'a,'b,'tcx> TypeFolder<'tcx> for AssociatedTypeNormalizer<'a,'b,'tcx> {
-    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'tcx> {
+    fn tcx<'c>(&'c self) -> TyCtxt<'c, 'tcx, 'tcx> {
         self.selcx.tcx()
     }
 
@@ -423,7 +423,7 @@ impl<'tcx,T> Normalized<'tcx,T> {
 /// substitute a fresh type variable `$X` and generate a new
 /// obligation `<T as Trait>::Item == $X` for later.
 pub fn normalize_projection_type<'a,'b,'tcx>(
-    selcx: &'a mut SelectionContext<'b,'tcx>,
+    selcx: &'a mut SelectionContext<'b,'tcx, 'tcx>,
     projection_ty: ty::ProjectionTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize)
@@ -454,7 +454,7 @@ pub fn normalize_projection_type<'a,'b,'tcx>(
 /// additional obligations). Returns `None` in the case of ambiguity,
 /// which indicates that there are unbound type variables.
 fn opt_normalize_projection_type<'a,'b,'tcx>(
-    selcx: &'a mut SelectionContext<'b,'tcx>,
+    selcx: &'a mut SelectionContext<'b,'tcx, 'tcx>,
     projection_ty: ty::ProjectionTy<'tcx>,
     cause: ObligationCause<'tcx>,
     depth: usize)
@@ -542,7 +542,7 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
 /// an error for this obligation, but we legitimately should not,
 /// because it contains `[type error]`. Yuck! (See issue #29857 for
 /// one case where this arose.)
-fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
+fn normalize_to_error<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx, 'tcx>,
                                projection_ty: ty::ProjectionTy<'tcx>,
                                cause: ObligationCause<'tcx>,
                                depth: usize)
@@ -566,7 +566,7 @@ enum ProjectedTy<'tcx> {
 
 /// Compute the result of a projection type (if we can).
 fn project_type<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>)
     -> Result<ProjectedTy<'tcx>, ProjectionTyError<'tcx>>
 {
@@ -749,7 +749,7 @@ fn project_type<'cx,'tcx>(
 /// environment to see whether there are any projection predicates
 /// there that can answer this question.
 fn assemble_candidates_from_param_env<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
@@ -775,7 +775,7 @@ fn assemble_candidates_from_param_env<'cx,'tcx>(
 ///
 /// Here, for example, we could conclude that the result is `i32`.
 fn assemble_candidates_from_trait_def<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
@@ -807,7 +807,7 @@ fn assemble_candidates_from_trait_def<'cx,'tcx>(
 }
 
 fn assemble_candidates_from_predicates<'cx,'tcx,I>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>,
@@ -854,7 +854,7 @@ fn assemble_candidates_from_predicates<'cx,'tcx,I>(
 }
 
 fn assemble_candidates_from_object_type<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation:  &ProjectionTyObligation<'tcx>,
     obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
@@ -886,7 +886,7 @@ fn assemble_candidates_from_object_type<'cx,'tcx>(
 }
 
 fn assemble_candidates_from_impls<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     obligation_trait_ref: &ty::TraitRef<'tcx>,
     candidate_set: &mut ProjectionTyCandidateSet<'tcx>)
@@ -970,7 +970,7 @@ fn assemble_candidates_from_impls<'cx,'tcx>(
 }
 
 fn confirm_candidate<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     candidate: ProjectionTyCandidate<'tcx>)
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
@@ -1000,7 +1000,7 @@ fn confirm_candidate<'cx,'tcx>(
 }
 
 fn confirm_fn_pointer_candidate<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     fn_type: Ty<'tcx>)
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
@@ -1011,7 +1011,7 @@ fn confirm_fn_pointer_candidate<'cx,'tcx>(
 }
 
 fn confirm_closure_candidate<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     vtable: VtableClosureData<'tcx, PredicateObligation<'tcx>>)
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
@@ -1034,7 +1034,7 @@ fn confirm_closure_candidate<'cx,'tcx>(
 }
 
 fn confirm_callable_candidate<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     fn_sig: &ty::PolyFnSig<'tcx>,
     flag: util::TupleArgumentsFlag)
@@ -1068,7 +1068,7 @@ fn confirm_callable_candidate<'cx,'tcx>(
 }
 
 fn confirm_param_env_candidate<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     poly_projection: ty::PolyProjectionPredicate<'tcx>)
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
@@ -1107,7 +1107,7 @@ fn confirm_param_env_candidate<'cx,'tcx>(
 }
 
 fn confirm_impl_candidate<'cx,'tcx>(
-    selcx: &mut SelectionContext<'cx,'tcx>,
+    selcx: &mut SelectionContext<'cx,'tcx, 'tcx>,
     obligation: &ProjectionTyObligation<'tcx>,
     impl_vtable: VtableImplData<'tcx, PredicateObligation<'tcx>>)
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
@@ -1146,7 +1146,7 @@ fn confirm_impl_candidate<'cx,'tcx>(
 ///
 /// Based on the "projection mode", this lookup may in fact only examine the
 /// topmost impl. See the comments for `ProjectionMode` for more details.
-fn assoc_ty_def<'cx, 'tcx>(selcx: &SelectionContext<'cx, 'tcx>,
+fn assoc_ty_def<'cx, 'tcx>(selcx: &SelectionContext<'cx, 'tcx, 'tcx>,
                            impl_def_id: DefId,
                            assoc_ty_name: ast::Name)
                            -> Option<specialization_graph::NodeItem<Rc<ty::AssociatedType<'tcx>>>>
diff --git a/src/librustc/traits/select.rs b/src/librustc/traits/select.rs
index 861810de22c..eda9587f98e 100644
--- a/src/librustc/traits/select.rs
+++ b/src/librustc/traits/select.rs
@@ -49,15 +49,15 @@ use syntax::abi::Abi;
 use hir;
 use util::nodemap::FnvHashMap;
 
-pub struct SelectionContext<'cx, 'tcx:'cx> {
-    infcx: &'cx InferCtxt<'cx, 'tcx>,
+pub struct SelectionContext<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
+    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
 
     /// Freshener used specifically for skolemizing entries on the
     /// obligation stack. This ensures that all entries on the stack
     /// at one time will have the same set of skolemized entries,
     /// which is important for checking for trait bounds that
     /// recursively require themselves.
-    freshener: TypeFreshener<'cx, 'tcx>,
+    freshener: TypeFreshener<'cx, 'tcx, 'tcx>,
 
     /// If true, indicates that the evaluation should be conservative
     /// and consider the possibility of types outside this crate.
@@ -262,8 +262,8 @@ pub struct EvaluationCache<'tcx> {
     hashmap: RefCell<FnvHashMap<ty::PolyTraitRef<'tcx>, EvaluationResult>>
 }
 
-impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
-    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
+impl<'cx, 'tcx> SelectionContext<'cx, 'tcx, 'tcx> {
+    pub fn new(infcx: &'cx InferCtxt<'cx, 'tcx, 'tcx>) -> SelectionContext<'cx, 'tcx, 'tcx> {
         SelectionContext {
             infcx: infcx,
             freshener: infcx.freshener(),
@@ -271,7 +271,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
-    pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx>) -> SelectionContext<'cx, 'tcx> {
+    pub fn intercrate(infcx: &'cx InferCtxt<'cx, 'tcx, 'tcx>) -> SelectionContext<'cx, 'tcx, 'tcx> {
         SelectionContext {
             infcx: infcx,
             freshener: infcx.freshener(),
@@ -279,11 +279,11 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         }
     }
 
-    pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+    pub fn infcx(&self) -> &'cx InferCtxt<'cx, 'tcx, 'tcx> {
         self.infcx
     }
 
-    pub fn tcx(&self) -> TyCtxt<'cx, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'cx, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
@@ -291,7 +291,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         self.infcx.param_env()
     }
 
-    pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx> {
+    pub fn closure_typer(&self) -> &'cx InferCtxt<'cx, 'tcx, 'tcx> {
         self.infcx
     }
 
diff --git a/src/librustc/traits/specialize/mod.rs b/src/librustc/traits/specialize/mod.rs
index 0e96f96823f..0de493443a9 100644
--- a/src/librustc/traits/specialize/mod.rs
+++ b/src/librustc/traits/specialize/mod.rs
@@ -31,8 +31,8 @@ use syntax::codemap::DUMMY_SP;
 pub mod specialization_graph;
 
 /// Information pertinent to an overlapping impl error.
-pub struct Overlap<'a, 'tcx: 'a> {
-    pub in_context: InferCtxt<'a, 'tcx>,
+pub struct Overlap<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    pub in_context: InferCtxt<'a, 'gcx, 'tcx>,
     pub with_impl: DefId,
     pub on_trait_ref: ty::TraitRef<'tcx>,
 }
@@ -72,7 +72,7 @@ pub struct Overlap<'a, 'tcx: 'a> {
 /// through associated type projection. We deal with such cases by using
 /// *fulfillment* to relate the two impls, requiring that all projections are
 /// resolved.
-pub fn translate_substs<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+pub fn translate_substs<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                   source_impl: DefId,
                                   source_substs: &'tcx Substs<'tcx>,
                                   target_node: specialization_graph::Node)
@@ -108,7 +108,9 @@ pub fn translate_substs<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 /// Specialization is determined by the sets of types to which the impls apply;
 /// impl1 specializes impl2 if it applies to a subset of the types impl2 applies
 /// to.
-pub fn specializes(tcx: TyCtxt, impl1_def_id: DefId, impl2_def_id: DefId) -> bool {
+pub fn specializes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             impl1_def_id: DefId,
+                             impl2_def_id: DefId) -> bool {
     // The feature gate should prevent introducing new specializations, but not
     // taking advantage of upstream ones.
     if !tcx.sess.features.borrow().specialization &&
@@ -165,7 +167,7 @@ pub fn specializes(tcx: TyCtxt, impl1_def_id: DefId, impl2_def_id: DefId) -> boo
 /// generics of `target_impl`, including both those needed to unify with
 /// `source_trait_ref` and those whose identity is determined via a where
 /// clause in the impl.
-fn fulfill_implication<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+fn fulfill_implication<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                  source_trait_ref: ty::TraitRef<'tcx>,
                                  target_impl: DefId)
                                  -> Result<Substs<'tcx>, ()> {
diff --git a/src/librustc/traits/specialize/specialization_graph.rs b/src/librustc/traits/specialize/specialization_graph.rs
index b88028a4aae..8f605a3a556 100644
--- a/src/librustc/traits/specialize/specialization_graph.rs
+++ b/src/librustc/traits/specialize/specialization_graph.rs
@@ -78,7 +78,7 @@ enum InsertResult<'a, 'tcx: 'a> {
 
     /// The impl has an unresolvable overlap with an existing child (neither
     /// specializes the other).
-    Overlapped(Overlap<'a, 'tcx>),
+    Overlapped(Overlap<'a, 'tcx, 'tcx>),
 }
 
 impl<'a, 'tcx> Children {
@@ -90,7 +90,9 @@ impl<'a, 'tcx> Children {
     }
 
     /// Insert an impl into this set of children without comparing to any existing impls
-    fn insert_blindly(&mut self, tcx: TyCtxt, impl_def_id: DefId) {
+    fn insert_blindly(&mut self,
+                      tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                      impl_def_id: DefId) {
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
         if let Some(sty) = fast_reject::simplify_type(tcx, trait_ref.self_ty(), false) {
             self.nonblanket_impls.entry(sty).or_insert(vec![]).push(impl_def_id)
@@ -102,7 +104,7 @@ impl<'a, 'tcx> Children {
     /// Attempt to insert an impl into this set of children, while comparing for
     /// specialiation relationships.
     fn insert(&mut self,
-              tcx: TyCtxt<'a, 'tcx>,
+              tcx: TyCtxt<'a, 'tcx, 'tcx>,
               impl_def_id: DefId,
               simplified_self: Option<SimplifiedType>)
               -> InsertResult<'a, 'tcx>
@@ -174,9 +176,9 @@ impl<'a, 'tcx> Graph {
     /// conflicts with it (has overlap, but neither specializes the other),
     /// information about the area of overlap is returned in the `Err`.
     pub fn insert(&mut self,
-                  tcx: TyCtxt<'a, 'tcx>,
+                  tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   impl_def_id: DefId)
-                  -> Result<(), Overlap<'a, 'tcx>> {
+                  -> Result<(), Overlap<'a, 'tcx, 'tcx>> {
         assert!(impl_def_id.is_local());
 
         let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
@@ -235,7 +237,10 @@ impl<'a, 'tcx> Graph {
     }
 
     /// Insert cached metadata mapping from a child impl back to its parent.
-    pub fn record_impl_from_cstore(&mut self, tcx: TyCtxt, parent: DefId, child: DefId) {
+    pub fn record_impl_from_cstore(&mut self,
+                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   parent: DefId,
+                                   child: DefId) {
         if self.parent.insert(child, parent).is_some() {
             bug!("When recording an impl from the crate store, information about its parent \
                   was already present.");
@@ -269,7 +274,7 @@ impl<'a, 'tcx> Node {
     }
 
     /// Iterate over the items defined directly by the given (impl or trait) node.
-    pub fn items(&self, tcx: TyCtxt<'a, 'tcx>) -> NodeItems<'a, 'tcx> {
+    pub fn items(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> NodeItems<'a, 'tcx> {
         match *self {
             Node::Impl(impl_def_id) => {
                 NodeItems::Impl {
@@ -299,7 +304,7 @@ impl<'a, 'tcx> Node {
 /// An iterator over the items defined within a trait or impl.
 pub enum NodeItems<'a, 'tcx: 'a> {
     Impl {
-        tcx: TyCtxt<'a, 'tcx>,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
         items: cell::Ref<'a, Vec<ty::ImplOrTraitItemId>>,
         idx: usize,
     },
@@ -411,7 +416,7 @@ impl<'a, 'tcx> Iterator for ConstDefs<'a, 'tcx> {
 impl<'a, 'tcx> Ancestors<'a, 'tcx> {
     /// Search the items from the given ancestors, returning each type definition
     /// with the given name.
-    pub fn type_defs(self, tcx: TyCtxt<'a, 'tcx>, name: Name) -> TypeDefs<'a, 'tcx> {
+    pub fn type_defs(self, tcx: TyCtxt<'a, 'tcx, 'tcx>, name: Name) -> TypeDefs<'a, 'tcx> {
         let iter = self.flat_map(move |node| {
             node.items(tcx)
                 .filter_map(move |item| {
@@ -432,7 +437,7 @@ impl<'a, 'tcx> Ancestors<'a, 'tcx> {
 
     /// Search the items from the given ancestors, returning each fn definition
     /// with the given name.
-    pub fn fn_defs(self, tcx: TyCtxt<'a, 'tcx>, name: Name) -> FnDefs<'a, 'tcx> {
+    pub fn fn_defs(self, tcx: TyCtxt<'a, 'tcx, 'tcx>, name: Name) -> FnDefs<'a, 'tcx> {
         let iter = self.flat_map(move |node| {
             node.items(tcx)
                 .filter_map(move |item| {
@@ -453,7 +458,7 @@ impl<'a, 'tcx> Ancestors<'a, 'tcx> {
 
     /// Search the items from the given ancestors, returning each const
     /// definition with the given name.
-    pub fn const_defs(self, tcx: TyCtxt<'a, 'tcx>, name: Name) -> ConstDefs<'a, 'tcx> {
+    pub fn const_defs(self, tcx: TyCtxt<'a, 'tcx, 'tcx>, name: Name) -> ConstDefs<'a, 'tcx> {
         let iter = self.flat_map(move |node| {
             node.items(tcx)
                 .filter_map(move |item| {
diff --git a/src/librustc/traits/util.rs b/src/librustc/traits/util.rs
index 15819992222..001f273b311 100644
--- a/src/librustc/traits/util.rs
+++ b/src/librustc/traits/util.rs
@@ -18,7 +18,7 @@ use util::nodemap::FnvHashSet;
 
 use super::{Obligation, ObligationCause, PredicateObligation, SelectionContext, Normalized};
 
-fn anonymize_predicate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, pred: &ty::Predicate<'tcx>)
+fn anonymize_predicate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, pred: &ty::Predicate<'tcx>)
                                  -> ty::Predicate<'tcx> {
     match *pred {
         ty::Predicate::Trait(ref data) =>
@@ -52,12 +52,12 @@ fn anonymize_predicate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, pred: &ty::Predicate<'tc
 
 
 struct PredicateSet<'a,'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     set: FnvHashSet<ty::Predicate<'tcx>>,
 }
 
 impl<'a,'tcx> PredicateSet<'a,'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx>) -> PredicateSet<'a,'tcx> {
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> PredicateSet<'a,'tcx> {
         PredicateSet { tcx: tcx, set: FnvHashSet() }
     }
 
@@ -88,13 +88,13 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> {
 /// Foo : 'static`, and we know that `T : Foo`, then we know that `T :
 /// 'static`.
 pub struct Elaborator<'cx, 'tcx:'cx> {
-    tcx: TyCtxt<'cx, 'tcx>,
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
     stack: Vec<ty::Predicate<'tcx>>,
     visited: PredicateSet<'cx,'tcx>,
 }
 
 pub fn elaborate_trait_ref<'cx, 'tcx>(
-    tcx: TyCtxt<'cx, 'tcx>,
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
     trait_ref: ty::PolyTraitRef<'tcx>)
     -> Elaborator<'cx, 'tcx>
 {
@@ -102,7 +102,7 @@ pub fn elaborate_trait_ref<'cx, 'tcx>(
 }
 
 pub fn elaborate_trait_refs<'cx, 'tcx>(
-    tcx: TyCtxt<'cx, 'tcx>,
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
     trait_refs: &[ty::PolyTraitRef<'tcx>])
     -> Elaborator<'cx, 'tcx>
 {
@@ -113,7 +113,7 @@ pub fn elaborate_trait_refs<'cx, 'tcx>(
 }
 
 pub fn elaborate_predicates<'cx, 'tcx>(
-    tcx: TyCtxt<'cx, 'tcx>,
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
     mut predicates: Vec<ty::Predicate<'tcx>>)
     -> Elaborator<'cx, 'tcx>
 {
@@ -222,14 +222,14 @@ impl<'cx, 'tcx> Iterator for Elaborator<'cx, 'tcx> {
 
 pub type Supertraits<'cx, 'tcx> = FilterToTraits<Elaborator<'cx, 'tcx>>;
 
-pub fn supertraits<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx>,
+pub fn supertraits<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx, 'tcx>,
                               trait_ref: ty::PolyTraitRef<'tcx>)
                               -> Supertraits<'cx, 'tcx>
 {
     elaborate_trait_ref(tcx, trait_ref).filter_to_traits()
 }
 
-pub fn transitive_bounds<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx>,
+pub fn transitive_bounds<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx, 'tcx>,
                                     bounds: &[ty::PolyTraitRef<'tcx>])
                                     -> Supertraits<'cx, 'tcx>
 {
@@ -240,12 +240,12 @@ pub fn transitive_bounds<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx>,
 // Iterator over def-ids of supertraits
 
 pub struct SupertraitDefIds<'cx, 'tcx:'cx> {
-    tcx: TyCtxt<'cx, 'tcx>,
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
     stack: Vec<DefId>,
     visited: FnvHashSet<DefId>,
 }
 
-pub fn supertrait_def_ids<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx>,
+pub fn supertrait_def_ids<'cx, 'tcx>(tcx: TyCtxt<'cx, 'tcx, 'tcx>,
                                      trait_def_id: DefId)
                                      -> SupertraitDefIds<'cx, 'tcx>
 {
@@ -319,7 +319,7 @@ impl<'tcx,I:Iterator<Item=ty::Predicate<'tcx>>> Iterator for FilterToTraits<I> {
 /// Instantiate all bound parameters of the impl with the given substs,
 /// returning the resulting trait ref and all obligations that arise.
 /// The obligations are closed under normalization.
-pub fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
+pub fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx, 'tcx>,
                                          impl_def_id: DefId,
                                          impl_substs: &Substs<'tcx>)
                                          -> (ty::TraitRef<'tcx>,
@@ -352,7 +352,7 @@ pub fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
 // declared on the impl declaration e.g., `impl<A,B> for Box<[(A,B)]>`
 // would return ($0, $1) where $0 and $1 are freshly instantiated type
 // variables.
-pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                           span: Span,
                                           impl_def_id: DefId)
                                           -> Substs<'tcx>
@@ -391,7 +391,7 @@ pub fn predicate_for_trait_ref<'tcx>(
     }
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
 pub fn trait_ref_for_builtin_bound(self,
     builtin_bound: ty::BuiltinBound,
     param_ty: Ty<'tcx>)
diff --git a/src/librustc/ty/_match.rs b/src/librustc/ty/_match.rs
index c024611d769..ef53b736091 100644
--- a/src/librustc/ty/_match.rs
+++ b/src/librustc/ty/_match.rs
@@ -29,18 +29,18 @@ use ty::relate::{self, Relate, TypeRelation, RelateResult};
 /// important thing about the result is Ok/Err. Also, matching never
 /// affects any type variables or unification state.
 pub struct Match<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>
+    tcx: TyCtxt<'a, 'tcx, 'tcx>
 }
 
 impl<'a, 'tcx> Match<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx>) -> Match<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Match<'a, 'tcx> {
         Match { tcx: tcx }
     }
 }
 
 impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Match<'a, 'tcx> {
     fn tag(&self) -> &'static str { "Match" }
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.tcx }
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.tcx }
     fn a_is_expected(&self) -> bool { true } // irrelevant
 
     fn relate_with_variance<T:Relate<'a,'tcx>>(&mut self,
diff --git a/src/librustc/ty/adjustment.rs b/src/librustc/ty/adjustment.rs
index 8cbe110baec..1cc60c808ef 100644
--- a/src/librustc/ty/adjustment.rs
+++ b/src/librustc/ty/adjustment.rs
@@ -139,7 +139,7 @@ pub enum CustomCoerceUnsized {
 impl<'a, 'tcx> ty::TyS<'tcx> {
     /// See `expr_ty_adjusted`
     pub fn adjust<F>(&'tcx self,
-                     tcx: TyCtxt<'a, 'tcx>,
+                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
                      span: Span,
                      expr_id: ast::NodeId,
                      adjustment: Option<&AutoAdjustment<'tcx>>,
@@ -216,7 +216,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
     }
 
     pub fn adjust_for_autoderef<F>(&'tcx self,
-                                   tcx: TyCtxt<'a, 'tcx>,
+                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    expr_id: ast::NodeId,
                                    expr_span: Span,
                                    autoderef: u32, // how many autoderefs so far?
@@ -244,7 +244,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
         }
     }
 
-    pub fn adjust_for_autoref(&'tcx self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn adjust_for_autoref(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               autoref: Option<AutoRef<'tcx>>)
                               -> Ty<'tcx> {
         match autoref {
diff --git a/src/librustc/ty/contents.rs b/src/librustc/ty/contents.rs
index 381b07dc7c8..33b33092b25 100644
--- a/src/librustc/ty/contents.rs
+++ b/src/librustc/ty/contents.rs
@@ -140,10 +140,10 @@ impl fmt::Debug for TypeContents {
 }
 
 impl<'a, 'tcx> ty::TyS<'tcx> {
-    pub fn type_contents(&'tcx self, tcx: TyCtxt<'a, 'tcx>) -> TypeContents {
+    pub fn type_contents(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> TypeContents {
         return tcx.tc_cache.memoize(self, || tc_ty(tcx, self, &mut FnvHashMap()));
 
-        fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+        fn tc_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            ty: Ty<'tcx>,
                            cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
         {
@@ -255,8 +255,9 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
             result
         }
 
-        fn apply_lang_items(tcx: TyCtxt, did: DefId, tc: TypeContents)
-                            -> TypeContents {
+        fn apply_lang_items<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                      did: DefId, tc: TypeContents)
+                                      -> TypeContents {
             if Some(did) == tcx.lang_items.unsafe_cell_type() {
                 tc | TC::InteriorUnsafe
             } else {
diff --git a/src/librustc/ty/context.rs b/src/librustc/ty/context.rs
index 36e97c8a3f3..bdeb6d146a2 100644
--- a/src/librustc/ty/context.rs
+++ b/src/librustc/ty/context.rs
@@ -210,7 +210,7 @@ impl<'a, 'tcx> Tables<'tcx> {
     }
 
     pub fn closure_kind(this: &RefCell<Self>,
-                        tcx: TyCtxt<'a, 'tcx>,
+                        tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         def_id: DefId)
                         -> ty::ClosureKind {
         // If this is a local def-id, it should be inserted into the
@@ -226,7 +226,7 @@ impl<'a, 'tcx> Tables<'tcx> {
     }
 
     pub fn closure_type(this: &RefCell<Self>,
-                        tcx: TyCtxt<'a, 'tcx>,
+                        tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         def_id: DefId,
                         substs: &ClosureSubsts<'tcx>)
                         -> ty::ClosureTy<'tcx>
@@ -271,14 +271,14 @@ impl<'tcx> CommonTypes<'tcx> {
 /// generates so that so that it can be reused and doesn't have to be redone
 /// later on.
 #[derive(Copy, Clone)]
-pub struct TyCtxt<'a, 'tcx: 'a> {
-    gcx: &'a GlobalCtxt<'tcx>,
+pub struct TyCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    gcx: &'a GlobalCtxt<'gcx>,
     interners: &'a CtxtInterners<'tcx>
 }
 
-impl<'a, 'tcx> Deref for TyCtxt<'a, 'tcx> {
-    type Target = &'a GlobalCtxt<'tcx>;
-    fn deref(&self) -> &&'a GlobalCtxt<'tcx> {
+impl<'a, 'gcx, 'tcx> Deref for TyCtxt<'a, 'gcx, 'tcx> {
+    type Target = &'a GlobalCtxt<'gcx>;
+    fn deref(&self) -> &Self::Target {
         &self.gcx
     }
 }
@@ -486,7 +486,7 @@ pub struct GlobalCtxt<'tcx> {
 
 impl<'tcx> GlobalCtxt<'tcx> {
     /// Get the global TyCtxt.
-    pub fn global_tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx> {
+    pub fn global_tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
         TyCtxt {
             gcx: self,
             interners: &self.global_interners
@@ -494,7 +494,7 @@ impl<'tcx> GlobalCtxt<'tcx> {
     }
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn crate_name(self, cnum: ast::CrateNum) -> token::InternedString {
         if cnum == LOCAL_CRATE {
             self.crate_name.clone()
@@ -617,7 +617,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
                                   stability: stability::Index<'tcx>,
                                  crate_name: &str,
                                   f: F) -> R
-                                  where F: for<'b> FnOnce(TyCtxt<'b, 'tcx>) -> R
+                                  where F: for<'b> FnOnce(TyCtxt<'b, 'tcx, 'tcx>) -> R
     {
         let data_layout = TargetDataLayout::parse(s);
         let interners = CtxtInterners::new(arenas);
@@ -693,12 +693,12 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
 /// e.g. `()` or `u8`, was interned in a different context.
 pub trait Lift<'tcx> {
     type Lifted;
-    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx>) -> Option<Self::Lifted>;
+    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Self::Lifted>;
 }
 
 impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
     type Lifted = Ty<'tcx>;
-    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx>) -> Option<Ty<'tcx>> {
+    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> Option<Ty<'tcx>> {
         if let Some(&InternedTy { ty }) = tcx.interners.type_.borrow().get(&self.sty) {
             if *self as *const _ == ty as *const _ {
                 return Some(ty);
@@ -710,7 +710,7 @@ impl<'a, 'tcx> Lift<'tcx> for Ty<'a> {
 
 impl<'a, 'tcx> Lift<'tcx> for &'a Substs<'a> {
     type Lifted = &'tcx Substs<'tcx>;
-    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx>) -> Option<&'tcx Substs<'tcx>> {
+    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> Option<&'tcx Substs<'tcx>> {
         if let Some(&InternedSubsts { substs }) = tcx.interners.substs.borrow().get(*self) {
             if *self as *const _ == substs as *const _ {
                 return Some(substs);
@@ -744,7 +744,7 @@ pub mod tls {
     }
 
     pub fn enter<'tcx, F, R>(gcx: GlobalCtxt<'tcx>, f: F) -> R
-        where F: for<'a> FnOnce(TyCtxt<'a, 'tcx>) -> R
+        where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>) -> R
     {
         codemap::SPAN_DEBUG.with(|span_dbg| {
             let original_span_debug = span_dbg.get();
@@ -762,7 +762,9 @@ pub mod tls {
         })
     }
 
-    pub fn with<F: FnOnce(TyCtxt) -> R, R>(f: F) -> R {
+    pub fn with<F, R>(f: F) -> R
+        where F: for<'a, 'tcx> FnOnce(TyCtxt<'a, 'tcx, 'tcx>) -> R
+    {
         TLS_TCX.with(|gcx| {
             let gcx = gcx.get().unwrap();
             let gcx = unsafe { &*(gcx as *const GlobalCtxt) };
@@ -773,7 +775,9 @@ pub mod tls {
         })
     }
 
-    pub fn with_opt<F: FnOnce(Option<TyCtxt>) -> R, R>(f: F) -> R {
+    pub fn with_opt<F, R>(f: F) -> R
+        where F: for<'a, 'tcx> FnOnce(Option<TyCtxt<'a, 'tcx, 'tcx>>) -> R
+    {
         if TLS_TCX.with(|gcx| gcx.get().is_some()) {
             with(|v| f(Some(v)))
         } else {
@@ -846,7 +850,7 @@ macro_rules! sty_debug_print {
     }}
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn print_debug_stats(self) {
         sty_debug_print!(
             self,
@@ -906,7 +910,7 @@ fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
             |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     // Type constructors
     pub fn mk_substs(self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> {
         if let Some(interned) = self.interners.substs.borrow().get(&substs) {
diff --git a/src/librustc/ty/error.rs b/src/librustc/ty/error.rs
index 48f3e0e0bf7..49ab25cc5ad 100644
--- a/src/librustc/ty/error.rs
+++ b/src/librustc/ty/error.rs
@@ -210,8 +210,8 @@ impl<'tcx> fmt::Display for TypeError<'tcx> {
     }
 }
 
-impl<'tcx> ty::TyS<'tcx> {
-    fn sort_string(&self, tcx: TyCtxt) -> String {
+impl<'a, 'tcx, 'lcx> ty::TyS<'tcx> {
+    fn sort_string(&self, tcx: TyCtxt<'a, 'lcx, 'lcx>) -> String {
         match self.sty {
             ty::TyBool | ty::TyChar | ty::TyInt(_) |
             ty::TyUint(_) | ty::TyFloat(_) | ty::TyStr => self.to_string(),
@@ -252,7 +252,7 @@ impl<'tcx> ty::TyS<'tcx> {
     }
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn note_and_explain_type_err(self,
                                      db: &mut DiagnosticBuilder,
                                      err: &TypeError<'tcx>,
diff --git a/src/librustc/ty/fast_reject.rs b/src/librustc/ty/fast_reject.rs
index ff257e0c3b5..ad07894f8bb 100644
--- a/src/librustc/ty/fast_reject.rs
+++ b/src/librustc/ty/fast_reject.rs
@@ -43,10 +43,10 @@ pub enum SimplifiedType {
 /// then we can't say much about whether two types would unify. Put another way,
 /// `can_simplify_params` should be true if type parameters appear free in `ty` and `false` if they
 /// are to be considered bound.
-pub fn simplify_type(tcx: TyCtxt,
-                     ty: Ty,
-                     can_simplify_params: bool)
-                     -> Option<SimplifiedType>
+pub fn simplify_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                               ty: Ty,
+                               can_simplify_params: bool)
+                               -> Option<SimplifiedType>
 {
     match ty.sty {
         ty::TyBool => Some(BoolSimplifiedType),
diff --git a/src/librustc/ty/fold.rs b/src/librustc/ty/fold.rs
index c01842d8af4..d145c080d4b 100644
--- a/src/librustc/ty/fold.rs
+++ b/src/librustc/ty/fold.rs
@@ -114,7 +114,7 @@ pub trait TypeFoldable<'tcx>: fmt::Debug + Clone {
 /// identity fold, it should invoke `foo.fold_with(self)` to fold each
 /// sub-item.
 pub trait TypeFolder<'tcx> : Sized {
-    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx>;
+    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx>;
 
     fn fold_binder<T>(&mut self, t: &Binder<T>) -> Binder<T>
         where T : TypeFoldable<'tcx>
@@ -202,14 +202,14 @@ pub trait TypeVisitor<'tcx> : Sized {
 // Some sample folders
 
 pub struct BottomUpFolder<'a, 'tcx: 'a, F> where F: FnMut(Ty<'tcx>) -> Ty<'tcx> {
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub fldop: F,
 }
 
 impl<'a, 'tcx, F> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx, F> where
     F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
 {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> { self.tcx }
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx }
 
     fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
         let t1 = ty.super_fold_with(self);
@@ -220,7 +220,7 @@ impl<'a, 'tcx, F> TypeFolder<'tcx> for BottomUpFolder<'a, 'tcx, F> where
 ///////////////////////////////////////////////////////////////////////////
 // Region folder
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     /// Collects the free and escaping regions in `value` into `region_set`. Returns
     /// whether any late-bound regions were skipped
     pub fn collect_regions<T>(self,
@@ -260,14 +260,14 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
 /// visited by `fld_r`.
 
 pub struct RegionFolder<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     skipped_regions: &'a mut bool,
     current_depth: u32,
     fld_r: &'a mut (FnMut(ty::Region, u32) -> ty::Region + 'a),
 }
 
 impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
-    pub fn new<F>(tcx: TyCtxt<'a, 'tcx>,
+    pub fn new<F>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                   skipped_regions: &'a mut bool,
                   fld_r: &'a mut F) -> RegionFolder<'a, 'tcx>
         where F : FnMut(ty::Region, u32) -> ty::Region
@@ -283,7 +283,7 @@ impl<'a, 'tcx> RegionFolder<'a, 'tcx> {
 
 impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
 {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> { self.tcx }
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx }
 
     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
         self.current_depth += 1;
@@ -315,13 +315,13 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionFolder<'a, 'tcx>
 // Replaces the escaping regions in a type.
 
 struct RegionReplacer<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     current_depth: u32,
     fld_r: &'a mut (FnMut(ty::BoundRegion) -> ty::Region + 'a),
     map: FnvHashMap<ty::BoundRegion, ty::Region>
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn replace_late_bound_regions<T,F>(self,
         value: &Binder<T>,
         mut f: F)
@@ -409,7 +409,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> RegionReplacer<'a, 'tcx> {
-    fn new<F>(tcx: TyCtxt<'a, 'tcx>, fld_r: &'a mut F) -> RegionReplacer<'a, 'tcx>
+    fn new<F>(tcx: TyCtxt<'a, 'tcx, 'tcx>, fld_r: &'a mut F) -> RegionReplacer<'a, 'tcx>
         where F : FnMut(ty::BoundRegion) -> ty::Region
     {
         RegionReplacer {
@@ -423,7 +423,7 @@ impl<'a, 'tcx> RegionReplacer<'a, 'tcx> {
 
 impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx>
 {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> { self.tcx }
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx }
 
     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
         self.current_depth += 1;
@@ -463,7 +463,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx>
 ///////////////////////////////////////////////////////////////////////////
 // Region eraser
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     /// Returns an equivalent value with all free regions removed (note
     /// that late-bound regions remain, because they are important for
     /// subtyping, but they are anonymized and normalized as well)..
@@ -475,10 +475,10 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
                value, value1);
         return value1;
 
-        struct RegionEraser<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx>);
+        struct RegionEraser<'a, 'tcx: 'a>(TyCtxt<'a, 'tcx, 'tcx>);
 
         impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
-            fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> { self.0 }
+            fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.0 }
 
             fn fold_ty(&mut self, ty: Ty<'tcx>) -> Ty<'tcx> {
                 match self.tcx().normalized_cache.borrow().get(&ty).cloned() {
@@ -543,7 +543,7 @@ pub fn shift_region(region: ty::Region, amount: u32) -> ty::Region {
     }
 }
 
-pub fn shift_regions<'a, 'tcx, T:TypeFoldable<'tcx>>(tcx: TyCtxt<'a, 'tcx>,
+pub fn shift_regions<'a, 'tcx, T:TypeFoldable<'tcx>>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                      amount: u32, value: &T) -> T {
     debug!("shift_regions(value={:?}, amount={})",
            value, amount);
diff --git a/src/librustc/ty/item_path.rs b/src/librustc/ty/item_path.rs
index aef54b75db5..05e39e9ca44 100644
--- a/src/librustc/ty/item_path.rs
+++ b/src/librustc/ty/item_path.rs
@@ -14,7 +14,7 @@ use hir::def_id::{DefId, CRATE_DEF_INDEX};
 use ty::{self, Ty, TyCtxt};
 use syntax::ast;
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     /// Returns a string identifying this def-id. This string is
     /// suitable for user output. It is relative to the current crate
     /// root.
diff --git a/src/librustc/ty/layout.rs b/src/librustc/ty/layout.rs
index aef67552df5..9c9da6960e7 100644
--- a/src/librustc/ty/layout.rs
+++ b/src/librustc/ty/layout.rs
@@ -466,7 +466,7 @@ pub struct Struct {
     pub offset_after_field: Vec<Size>
 }
 
-impl Struct {
+impl<'a, 'tcx> Struct {
     pub fn new(dl: &TargetDataLayout, packed: bool) -> Struct {
         Struct {
             align: if packed { dl.i8_align } else { dl.aggregate_align },
@@ -477,10 +477,10 @@ impl Struct {
     }
 
     /// Extend the Struct with more fields.
-    pub fn extend<'a, 'tcx, I>(&mut self, dl: &TargetDataLayout,
-                               fields: I,
-                               scapegoat: Ty<'tcx>)
-                               -> Result<(), LayoutError<'tcx>>
+    pub fn extend<I>(&mut self, dl: &TargetDataLayout,
+                     fields: I,
+                     scapegoat: Ty<'tcx>)
+                     -> Result<(), LayoutError<'tcx>>
     where I: Iterator<Item=Result<&'a Layout, LayoutError<'tcx>>> {
         self.offset_after_field.reserve(fields.size_hint().0);
 
@@ -527,8 +527,8 @@ impl Struct {
     }
 
     /// Determine whether a structure would be zero-sized, given its fields.
-    pub fn would_be_zero_sized<'a, 'tcx, I>(dl: &TargetDataLayout, fields: I)
-                                            -> Result<bool, LayoutError<'tcx>>
+    pub fn would_be_zero_sized<I>(dl: &TargetDataLayout, fields: I)
+                                  -> Result<bool, LayoutError<'tcx>>
     where I: Iterator<Item=Result<&'a Layout, LayoutError<'tcx>>> {
         for field in fields {
             let field = field?;
@@ -542,9 +542,9 @@ impl Struct {
     /// Find the path leading to a non-zero leaf field, starting from
     /// the given type and recursing through aggregates.
     // FIXME(eddyb) track value ranges and traverse already optimized enums.
-    pub fn non_zero_field_in_type<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
-                                            ty: Ty<'tcx>)
-                                            -> Result<Option<FieldPath>, LayoutError<'tcx>> {
+    pub fn non_zero_field_in_type(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
+                                  ty: Ty<'tcx>)
+                                  -> Result<Option<FieldPath>, LayoutError<'tcx>> {
         let tcx = infcx.tcx;
         match (ty.layout(infcx)?, &ty.sty) {
             (&Scalar { non_zero: true, .. }, _) => Ok(Some(vec![])),
@@ -600,9 +600,9 @@ impl Struct {
 
     /// Find the path leading to a non-zero leaf field, starting from
     /// the given set of fields and recursing through aggregates.
-    pub fn non_zero_field_path<'a, 'tcx, I>(infcx: &InferCtxt<'a, 'tcx>,
-                                            fields: I)
-                                            -> Result<Option<FieldPath>, LayoutError<'tcx>>
+    pub fn non_zero_field_path<I>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
+                                  fields: I)
+                                  -> Result<Option<FieldPath>, LayoutError<'tcx>>
     where I: Iterator<Item=Ty<'tcx>> {
         for (i, ty) in fields.enumerate() {
             if let Some(mut path) = Struct::non_zero_field_in_type(infcx, ty)? {
@@ -736,7 +736,7 @@ impl<'tcx> fmt::Display for LayoutError<'tcx> {
 }
 
 /// Helper function for normalizing associated types in an inference context.
-fn normalize_associated_type<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+fn normalize_associated_type<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                        ty: Ty<'tcx>)
                                        -> Ty<'tcx> {
     if !ty.has_projection_types() {
@@ -757,10 +757,10 @@ fn normalize_associated_type<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     infcx.drain_fulfillment_cx_or_panic(DUMMY_SP, &mut fulfill_cx, &result)
 }
 
-impl Layout {
-    pub fn compute_uncached<'a, 'tcx>(ty: Ty<'tcx>,
-                                      infcx: &InferCtxt<'a, 'tcx>)
-                                      -> Result<Layout, LayoutError<'tcx>> {
+impl<'a, 'tcx> Layout {
+    pub fn compute_uncached(ty: Ty<'tcx>,
+                            infcx: &InferCtxt<'a, 'tcx, 'tcx>)
+                            -> Result<Layout, LayoutError<'tcx>> {
         let tcx = infcx.tcx;
         let dl = &tcx.data_layout;
         assert!(!ty.has_infer_types());
@@ -1220,9 +1220,9 @@ pub enum SizeSkeleton<'tcx> {
     }
 }
 
-impl<'tcx> SizeSkeleton<'tcx> {
-    pub fn compute<'a>(ty: Ty<'tcx>, infcx: &InferCtxt<'a, 'tcx>)
-                       -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
+impl<'a, 'tcx> SizeSkeleton<'tcx> {
+    pub fn compute(ty: Ty<'tcx>, infcx: &InferCtxt<'a, 'tcx, 'tcx>)
+                   -> Result<SizeSkeleton<'tcx>, LayoutError<'tcx>> {
         let tcx = infcx.tcx;
         assert!(!ty.has_infer_types());
 
diff --git a/src/librustc/ty/mod.rs b/src/librustc/ty/mod.rs
index 91cac6999aa..5e860eeedf4 100644
--- a/src/librustc/ty/mod.rs
+++ b/src/librustc/ty/mod.rs
@@ -166,7 +166,7 @@ pub struct ImplHeader<'tcx> {
 }
 
 impl<'a, 'tcx> ImplHeader<'tcx> {
-    pub fn with_fresh_ty_vars(selcx: &mut traits::SelectionContext<'a, 'tcx>,
+    pub fn with_fresh_ty_vars(selcx: &mut traits::SelectionContext<'a, 'tcx, 'tcx>,
                               impl_def_id: DefId)
                               -> ImplHeader<'tcx>
     {
@@ -780,14 +780,14 @@ impl<'a, 'tcx> GenericPredicates<'tcx> {
         }
     }
 
-    pub fn instantiate(&self, tcx: TyCtxt<'a, 'tcx>, substs: &Substs<'tcx>)
+    pub fn instantiate(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, substs: &Substs<'tcx>)
                        -> InstantiatedPredicates<'tcx> {
         InstantiatedPredicates {
             predicates: self.predicates.subst(tcx, substs),
         }
     }
 
-    pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn instantiate_supertrait(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   poly_trait_ref: &ty::PolyTraitRef<'tcx>)
                                   -> InstantiatedPredicates<'tcx>
     {
@@ -838,7 +838,7 @@ impl<'a, 'tcx> Predicate<'tcx> {
     /// poly-trait-ref holds. This is slightly different from a normal
     /// substitution in terms of what happens with bound regions.  See
     /// lengthy comment below for details.
-    pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn subst_supertrait(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             trait_ref: &ty::PolyTraitRef<'tcx>)
                             -> ty::Predicate<'tcx>
     {
@@ -1210,7 +1210,7 @@ impl<'tcx> TraitRef<'tcx> {
 /// more distinctions clearer.
 #[derive(Clone)]
 pub struct ParameterEnvironment<'a, 'tcx:'a> {
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     /// See `construct_free_substs` for details.
     pub free_substs: Substs<'tcx>,
@@ -1260,7 +1260,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
     }
 
     /// Construct a parameter environment given an item, impl item, or trait item
-    pub fn for_item(tcx: TyCtxt<'a, 'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx> {
+    pub fn for_item(tcx: TyCtxt<'a, 'tcx, 'tcx>, id: NodeId) -> ParameterEnvironment<'a, 'tcx> {
         match tcx.map.find(id) {
             Some(ast_map::NodeImplItem(ref impl_item)) => {
                 match impl_item.node {
@@ -1569,7 +1569,7 @@ impl VariantKind {
 }
 
 impl<'a, 'tcx, 'container> AdtDefData<'tcx, 'container> {
-    fn new(tcx: TyCtxt<'a, 'tcx>,
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            did: DefId,
            kind: AdtKind,
            variants: Vec<VariantDefData<'tcx, 'container>>) -> Self {
@@ -1599,7 +1599,7 @@ impl<'a, 'tcx, 'container> AdtDefData<'tcx, 'container> {
         }
     }
 
-    fn calculate_dtorck(&'tcx self, tcx: TyCtxt<'a, 'tcx>) {
+    fn calculate_dtorck(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         if tcx.is_adt_dtorck(self) {
             self.flags.set(self.flags.get() | AdtFlags::IS_DTORCK);
         }
@@ -1620,7 +1620,7 @@ impl<'a, 'tcx, 'container> AdtDefData<'tcx, '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(&'tcx self, tcx: TyCtxt<'a, 'tcx>) -> bool {
+    pub fn is_dtorck(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
         if !self.flags.get().intersects(AdtFlags::IS_DTORCK_VALID) {
             self.calculate_dtorck(tcx)
         }
@@ -1661,12 +1661,12 @@ impl<'a, 'tcx, 'container> AdtDefData<'tcx, 'container> {
     }
 
     #[inline]
-    pub fn type_scheme(&self, tcx: TyCtxt<'a, 'tcx>) -> TypeScheme<'tcx> {
+    pub fn type_scheme(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> TypeScheme<'tcx> {
         tcx.lookup_item_type(self.did)
     }
 
     #[inline]
-    pub fn predicates(&self, tcx: TyCtxt<'a, 'tcx>) -> GenericPredicates<'tcx> {
+    pub fn predicates(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> GenericPredicates<'tcx> {
         tcx.lookup_predicates(self.did)
     }
 
@@ -1754,7 +1754,7 @@ impl<'a, 'tcx, 'container> AdtDefData<'tcx, 'container> {
     ///
     /// Due to normalization being eager, this applies even if
     /// the associated type is behind a pointer, e.g. issue #31299.
-    pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    pub fn sized_constraint(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         let dep_node = DepNode::SizedConstraint(self.did);
         match self.sized_constraint.get(dep_node) {
             None => {
@@ -1783,7 +1783,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
     ///       such.
     ///     - a TyError, if a type contained itself. The representability
     ///       check should catch this case.
-    fn calculate_sized_constraint_inner(&'tcx self, tcx: TyCtxt<'a, 'tcx>,
+    fn calculate_sized_constraint_inner(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         stack: &mut Vec<AdtDefMaster<'tcx>>)
     {
 
@@ -1836,7 +1836,7 @@ impl<'a, 'tcx> AdtDefData<'tcx, 'tcx> {
 
     fn sized_constraint_for_ty(
         &'tcx self,
-        tcx: TyCtxt<'a, 'tcx>,
+        tcx: TyCtxt<'a, 'tcx, 'tcx>,
         stack: &mut Vec<AdtDefMaster<'tcx>>,
         ty: Ty<'tcx>
     ) -> Vec<Ty<'tcx>> {
@@ -1963,7 +1963,7 @@ impl<'a, 'tcx, 'container> FieldDefData<'tcx, 'container> {
         }
     }
 
-    pub fn ty(&self, tcx: TyCtxt<'a, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
+    pub fn ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, subst: &Substs<'tcx>) -> Ty<'tcx> {
         self.unsubst_ty().subst(tcx, subst)
     }
 
@@ -1993,8 +1993,8 @@ pub enum ClosureKind {
     FnOnce,
 }
 
-impl ClosureKind {
-    pub fn trait_did(&self, tcx: TyCtxt) -> DefId {
+impl<'a, 'tcx> ClosureKind {
+    pub fn trait_did(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefId {
         let result = match *self {
             ClosureKind::Fn => tcx.lang_items.require(FnTraitLangItem),
             ClosureKind::FnMut => {
@@ -2144,7 +2144,7 @@ impl BorrowKind {
     }
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn node_id_to_type(self, id: NodeId) -> Ty<'tcx> {
         match self.node_id_to_type_opt(id) {
            Some(ty) => ty,
@@ -2941,7 +2941,7 @@ pub enum ExplicitSelfCategory {
     ByBox,
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, '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/outlives.rs b/src/librustc/ty/outlives.rs
index ed50d151a2a..7a16989bbb4 100644
--- a/src/librustc/ty/outlives.rs
+++ b/src/librustc/ty/outlives.rs
@@ -55,7 +55,7 @@ pub enum Component<'tcx> {
     EscapingProjection(Vec<Component<'tcx>>),
 }
 
-impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
+impl<'a, 'tcx> InferCtxt<'a, 'tcx, 'tcx> {
 /// Returns all the things that must outlive `'a` for the condition
 /// `ty0: 'a` to hold.
 pub fn outlives_components(&self, ty0: Ty<'tcx>)
diff --git a/src/librustc/ty/relate.rs b/src/librustc/ty/relate.rs
index 9bddd8383cd..417b6c5479e 100644
--- a/src/librustc/ty/relate.rs
+++ b/src/librustc/ty/relate.rs
@@ -29,7 +29,7 @@ pub enum Cause {
 }
 
 pub trait TypeRelation<'a,'tcx> : Sized {
-    fn tcx(&self) -> TyCtxt<'a, 'tcx>;
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx>;
 
     /// Returns a static string we can use for printouts.
     fn tag(&self) -> &'static str;
diff --git a/src/librustc/ty/structural_impls.rs b/src/librustc/ty/structural_impls.rs
index d20417714e5..e715732ceb2 100644
--- a/src/librustc/ty/structural_impls.rs
+++ b/src/librustc/ty/structural_impls.rs
@@ -24,14 +24,14 @@ use hir;
 
 impl<'tcx, A: Lift<'tcx>, B: Lift<'tcx>> Lift<'tcx> for (A, B) {
     type Lifted = (A::Lifted, B::Lifted);
-    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx>) -> Option<Self::Lifted> {
+    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Self::Lifted> {
         tcx.lift(&self.0).and_then(|a| tcx.lift(&self.1).map(|b| (a, b)))
     }
 }
 
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for [T] {
     type Lifted = Vec<T::Lifted>;
-    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx>) -> Option<Self::Lifted> {
+    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Self::Lifted> {
         // type annotation needed to inform `projection_must_outlive`
         let mut result : Vec<<T as Lift<'tcx>>::Lifted>
             = Vec::with_capacity(self.len());
@@ -55,7 +55,7 @@ impl<'tcx> Lift<'tcx> for ty::Region {
 
 impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> {
     type Lifted = TraitRef<'tcx>;
-    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx>) -> Option<TraitRef<'tcx>> {
+    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> Option<TraitRef<'tcx>> {
         tcx.lift(&self.substs).map(|substs| TraitRef {
             def_id: self.def_id,
             substs: substs
@@ -65,7 +65,7 @@ impl<'a, 'tcx> Lift<'tcx> for TraitRef<'a> {
 
 impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
     type Lifted = ty::TraitPredicate<'tcx>;
-    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
+    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> Option<ty::TraitPredicate<'tcx>> {
         tcx.lift(&self.trait_ref).map(|trait_ref| ty::TraitPredicate {
             trait_ref: trait_ref
         })
@@ -74,21 +74,22 @@ impl<'a, 'tcx> Lift<'tcx> for ty::TraitPredicate<'a> {
 
 impl<'a, 'tcx> Lift<'tcx> for ty::EquatePredicate<'a> {
     type Lifted = ty::EquatePredicate<'tcx>;
-    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx>) -> Option<ty::EquatePredicate<'tcx>> {
+    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> Option<ty::EquatePredicate<'tcx>> {
         tcx.lift(&(self.0, self.1)).map(|(a, b)| ty::EquatePredicate(a, b))
     }
 }
 
 impl<'tcx, A: Copy+Lift<'tcx>, B: Copy+Lift<'tcx>> Lift<'tcx> for ty::OutlivesPredicate<A, B> {
     type Lifted = ty::OutlivesPredicate<A::Lifted, B::Lifted>;
-    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx>) -> Option<Self::Lifted> {
+    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Self::Lifted> {
         tcx.lift(&(self.0, self.1)).map(|(a, b)| ty::OutlivesPredicate(a, b))
     }
 }
 
 impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> {
     type Lifted = ty::ProjectionPredicate<'tcx>;
-    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx>) -> Option<ty::ProjectionPredicate<'tcx>> {
+    fn lift_to_tcx<'b>(&self, tcx: TyCtxt<'b, 'tcx, 'tcx>)
+                       -> Option<ty::ProjectionPredicate<'tcx>> {
         tcx.lift(&(self.projection_ty.trait_ref, self.ty)).map(|(trait_ref, ty)| {
             ty::ProjectionPredicate {
                 projection_ty: ty::ProjectionTy {
@@ -103,7 +104,7 @@ impl<'a, 'tcx> Lift<'tcx> for ty::ProjectionPredicate<'a> {
 
 impl<'tcx, T: Lift<'tcx>> Lift<'tcx> for ty::Binder<T> {
     type Lifted = ty::Binder<T::Lifted>;
-    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx>) -> Option<Self::Lifted> {
+    fn lift_to_tcx<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<Self::Lifted> {
         tcx.lift(&self.0).map(|x| ty::Binder(x))
     }
 }
diff --git a/src/librustc/ty/sty.rs b/src/librustc/ty/sty.rs
index 6dd406c3f8c..b2aa359af07 100644
--- a/src/librustc/ty/sty.rs
+++ b/src/librustc/ty/sty.rs
@@ -279,7 +279,7 @@ impl<'a, 'tcx> TraitTy<'tcx> {
     /// we convert the principal trait-ref into a normal trait-ref,
     /// you must give *some* self-type. A common choice is `mk_err()`
     /// or some skolemized type.
-    pub fn principal_trait_ref_with_self_ty(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn principal_trait_ref_with_self_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                             self_ty: Ty<'tcx>)
                                             -> ty::PolyTraitRef<'tcx>
     {
@@ -292,7 +292,7 @@ impl<'a, 'tcx> TraitTy<'tcx> {
         })
     }
 
-    pub fn projection_bounds_with_self_ty(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn projection_bounds_with_self_ty(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                           self_ty: Ty<'tcx>)
                                           -> Vec<ty::PolyProjectionPredicate<'tcx>>
     {
@@ -537,7 +537,7 @@ impl<'a, 'tcx> ParamTy {
         ParamTy::new(def.space, def.index, def.name)
     }
 
-    pub fn to_ty(self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    pub fn to_ty(self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         tcx.mk_param(self.space, self.idx, self.name)
     }
 
@@ -771,7 +771,7 @@ impl<'a, 'tcx> BuiltinBounds {
         self.into_iter()
     }
 
-    pub fn to_predicates(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn to_predicates(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          self_ty: Ty<'tcx>)
                          -> Vec<ty::Predicate<'tcx>> {
         self.iter().filter_map(|builtin_bound|
@@ -819,7 +819,7 @@ impl CLike for BuiltinBound {
     }
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn try_add_builtin_trait(self,
                                  trait_def_id: DefId,
                                  builtin_bounds: &mut EnumSet<BuiltinBound>)
@@ -971,7 +971,7 @@ impl<'a, 'tcx> TyS<'tcx> {
         }
     }
 
-    pub fn sequence_element_type(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    pub fn sequence_element_type(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         match self.sty {
             TyArray(ty, _) | TySlice(ty) => ty,
             TyStr => tcx.mk_mach_uint(ast::UintTy::U8),
@@ -979,7 +979,7 @@ impl<'a, 'tcx> TyS<'tcx> {
         }
     }
 
-    pub fn simd_type(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    pub fn simd_type(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         match self.sty {
             TyStruct(def, substs) => {
                 def.struct_variant().fields[0].ty(tcx, substs)
diff --git a/src/librustc/ty/subst.rs b/src/librustc/ty/subst.rs
index bb6d06d49e4..655aa3e9693 100644
--- a/src/librustc/ty/subst.rs
+++ b/src/librustc/ty/subst.rs
@@ -122,7 +122,7 @@ impl<'a, 'tcx> Substs<'tcx> {
     }
 
     /// Creates a trait-ref out of this substs, ignoring the FnSpace substs
-    pub fn to_trait_ref(&self, tcx: TyCtxt<'a, 'tcx>, trait_id: DefId)
+    pub fn to_trait_ref(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, trait_id: DefId)
                         -> ty::TraitRef<'tcx> {
         let Substs { mut types, mut regions } = self.clone();
         types.truncate(FnSpace, 0);
@@ -532,18 +532,18 @@ impl<'a,T> IntoIterator for &'a VecPerParamSpace<T> {
 // there is more information available (for better errors).
 
 pub trait Subst<'tcx> : Sized {
-    fn subst<'a>(&self, tcx: TyCtxt<'a, 'tcx>, substs: &Substs<'tcx>) -> Self {
+    fn subst<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, substs: &Substs<'tcx>) -> Self {
         self.subst_spanned(tcx, substs, None)
     }
 
-    fn subst_spanned<'a>(&self, tcx: TyCtxt<'a, 'tcx>,
+    fn subst_spanned<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          substs: &Substs<'tcx>,
                          span: Option<Span>)
                          -> Self;
 }
 
 impl<'tcx, T:TypeFoldable<'tcx>> Subst<'tcx> for T {
-    fn subst_spanned<'a>(&self, tcx: TyCtxt<'a, 'tcx>,
+    fn subst_spanned<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          substs: &Substs<'tcx>,
                          span: Option<Span>)
                          -> T
@@ -562,7 +562,7 @@ impl<'tcx, T:TypeFoldable<'tcx>> Subst<'tcx> for T {
 // The actual substitution engine itself is a type folder.
 
 struct SubstFolder<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     substs: &'a Substs<'tcx>,
 
     // The location for which the substitution is performed, if available.
@@ -579,7 +579,7 @@ struct SubstFolder<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> { self.tcx }
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.tcx }
 
     fn fold_binder<T: TypeFoldable<'tcx>>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T> {
         self.region_binders_passed += 1;
diff --git a/src/librustc/ty/trait_def.rs b/src/librustc/ty/trait_def.rs
index 1b9f4909e2b..c08d2dc0848 100644
--- a/src/librustc/ty/trait_def.rs
+++ b/src/librustc/ty/trait_def.rs
@@ -117,18 +117,18 @@ impl<'a, 'tcx> TraitDef<'tcx> {
         );
     }
 
-    fn write_trait_impls(&self, tcx: TyCtxt<'a, 'tcx>) {
+    fn write_trait_impls(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         tcx.dep_graph.write(DepNode::TraitImpls(self.trait_ref.def_id));
     }
 
-    fn read_trait_impls(&self, tcx: TyCtxt<'a, 'tcx>) {
+    fn read_trait_impls(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         tcx.dep_graph.read(DepNode::TraitImpls(self.trait_ref.def_id));
     }
 
     /// Records a basic trait-to-implementation mapping.
     ///
     /// Returns `true` iff the impl has not previously been recorded.
-    fn record_impl(&self, tcx: TyCtxt<'a, 'tcx>,
+    fn record_impl(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    impl_def_id: DefId,
                    impl_trait_ref: TraitRef<'tcx>)
                    -> bool {
@@ -163,7 +163,7 @@ impl<'a, 'tcx> TraitDef<'tcx> {
     }
 
     /// Records a trait-to-implementation mapping for a crate-local impl.
-    pub fn record_local_impl(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn record_local_impl(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              impl_def_id: DefId,
                              impl_trait_ref: TraitRef<'tcx>) {
         assert!(impl_def_id.is_local());
@@ -176,7 +176,7 @@ impl<'a, 'tcx> TraitDef<'tcx> {
     /// The `parent_impl` is the immediately-less-specialized impl, or the
     /// trait's def ID if the impl is not a specialization -- information that
     /// should be pulled from the metadata.
-    pub fn record_remote_impl(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn record_remote_impl(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               impl_def_id: DefId,
                               impl_trait_ref: TraitRef<'tcx>,
                               parent_impl: DefId) {
@@ -194,9 +194,10 @@ impl<'a, 'tcx> TraitDef<'tcx> {
     /// Adds a local impl into the specialization graph, returning an error with
     /// overlap information if the impl overlaps but does not specialize an
     /// existing impl.
-    pub fn add_impl_for_specialization(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn add_impl_for_specialization(&self,
+                                       tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        impl_def_id: DefId)
-                                       -> Result<(), traits::Overlap<'a, 'tcx>> {
+                                       -> Result<(), traits::Overlap<'a, 'tcx, 'tcx>> {
         assert!(impl_def_id.is_local());
 
         self.specialization_graph.borrow_mut()
@@ -207,7 +208,7 @@ impl<'a, 'tcx> TraitDef<'tcx> {
         specialization_graph::ancestors(self, of_impl)
     }
 
-    pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: TyCtxt<'a, 'tcx>, mut f: F) {
+    pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, mut f: F) {
         self.read_trait_impls(tcx);
         tcx.populate_implementations_for_trait_if_necessary(self.trait_ref.def_id);
 
@@ -225,7 +226,7 @@ impl<'a, 'tcx> TraitDef<'tcx> {
     /// Iterate over every impl that could possibly match the
     /// self-type `self_ty`.
     pub fn for_each_relevant_impl<F: FnMut(DefId)>(&self,
-                                                   tcx: TyCtxt<'a, 'tcx>,
+                                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                    self_ty: Ty<'tcx>,
                                                    mut f: F)
     {
diff --git a/src/librustc/ty/util.rs b/src/librustc/ty/util.rs
index 70f03d3c8e8..8402efcabc6 100644
--- a/src/librustc/ty/util.rs
+++ b/src/librustc/ty/util.rs
@@ -32,14 +32,15 @@ use syntax::codemap::Span;
 use hir;
 
 pub trait IntTypeExt {
-    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx>;
-    fn disr_incr(&self, tcx: TyCtxt, val: Option<Disr>) -> Option<Disr>;
+    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx>;
+    fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>)
+                           -> Option<Disr>;
     fn assert_ty_matches(&self, val: Disr);
-    fn initial_discriminant(&self, tcx: TyCtxt) -> Disr;
+    fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr;
 }
 
 impl IntTypeExt for attr::IntType {
-    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx>) -> Ty<'tcx> {
+    fn to_ty<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Ty<'tcx> {
         match *self {
             SignedInt(ast::IntTy::I8)      => tcx.types.i8,
             SignedInt(ast::IntTy::I16)     => tcx.types.i16,
@@ -54,7 +55,7 @@ impl IntTypeExt for attr::IntType {
         }
     }
 
-    fn initial_discriminant(&self, tcx: TyCtxt) -> Disr {
+    fn initial_discriminant<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Disr {
         match *self {
             SignedInt(ast::IntTy::I8)    => ConstInt::I8(0),
             SignedInt(ast::IntTy::I16)   => ConstInt::I16(0),
@@ -93,7 +94,8 @@ impl IntTypeExt for attr::IntType {
         }
     }
 
-    fn disr_incr(&self, tcx: TyCtxt, val: Option<Disr>) -> Option<Disr> {
+    fn disr_incr<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, val: Option<Disr>)
+                           -> Option<Disr> {
         if let Some(val) = val {
             self.assert_ty_matches(val);
             (val + ConstInt::Infer(1)).ok()
@@ -170,7 +172,7 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> TyCtxt<'a, 'tcx, 'tcx> {
     pub fn pat_contains_ref_binding(self, pat: &hir::Pat) -> Option<hir::Mutability> {
         pat_util::pat_contains_ref_binding(&self.def_map, pat)
     }
@@ -337,7 +339,7 @@ impl<'a, 'tcx> TyCtxt<'a, 'tcx> {
         helper(self, ty, svh, &mut state);
         return state.finish();
 
-        fn helper<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, ty: Ty<'tcx>, svh: &Svh,
+        fn helper<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>, svh: &Svh,
                         state: &mut SipHasher) {
             macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } }
             macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
@@ -600,7 +602,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
     }
 
     #[inline]
-    pub fn layout(&'tcx self, infcx: &InferCtxt<'a, 'tcx>)
+    pub fn layout(&'tcx self, infcx: &InferCtxt<'a, 'tcx, 'tcx>)
                   -> Result<&'tcx Layout, LayoutError<'tcx>> {
         let can_cache = !self.has_param_types() && !self.has_self_ty();
         if can_cache {
@@ -620,10 +622,11 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
 
     /// Check whether a type is representable. This means it cannot contain unboxed
     /// structural recursion. This check is needed for structs and enums.
-    pub fn is_representable(&'tcx self, tcx: TyCtxt<'a, 'tcx>, sp: Span) -> Representability {
+    pub fn is_representable(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span)
+                            -> Representability {
 
         // Iterate until something non-representable is found
-        fn find_nonrepresentable<'a, 'tcx, It>(tcx: TyCtxt<'a, 'tcx>,
+        fn find_nonrepresentable<'a, 'tcx, It>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                sp: Span,
                                                seen: &mut Vec<Ty<'tcx>>,
                                                iter: It)
@@ -633,7 +636,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
                       |r, ty| cmp::max(r, is_type_structurally_recursive(tcx, sp, seen, ty)))
         }
 
-        fn are_inner_types_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, sp: Span,
+        fn are_inner_types_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span,
                                                seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
                                                -> Representability {
             match ty.sty {
@@ -692,7 +695,7 @@ impl<'a, 'tcx> ty::TyS<'tcx> {
 
         // Does the type `ty` directly (without indirection through a pointer)
         // contain any types on stack `seen`?
-        fn is_type_structurally_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+        fn is_type_structurally_recursive<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                     sp: Span,
                                                     seen: &mut Vec<Ty<'tcx>>,
                                                     ty: Ty<'tcx>) -> Representability {
diff --git a/src/librustc/ty/wf.rs b/src/librustc/ty/wf.rs
index 7fc1f159288..9b701c6abc0 100644
--- a/src/librustc/ty/wf.rs
+++ b/src/librustc/ty/wf.rs
@@ -25,7 +25,7 @@ use util::common::ErrorReported;
 /// inference variable, returns `None`, because we are not able to
 /// make any progress at all. This is to prevent "livelock" where we
 /// say "$0 is WF if $0 is WF".
-pub fn obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+pub fn obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                             body_id: ast::NodeId,
                             ty: Ty<'tcx>,
                             span: Span)
@@ -49,7 +49,7 @@ pub fn obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
 /// well-formed.  For example, if there is a trait `Set` defined like
 /// `trait Set<K:Eq>`, then the trait reference `Foo: Set<Bar>` is WF
 /// if `Bar: Eq`.
-pub fn trait_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+pub fn trait_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                   body_id: ast::NodeId,
                                   trait_ref: &ty::TraitRef<'tcx>,
                                   span: Span)
@@ -60,7 +60,7 @@ pub fn trait_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
     wf.normalize()
 }
 
-pub fn predicate_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx>,
+pub fn predicate_obligations<'a,'tcx>(infcx: &InferCtxt<'a, 'tcx, 'tcx>,
                                       body_id: ast::NodeId,
                                       predicate: &ty::Predicate<'tcx>,
                                       span: Span)
@@ -123,8 +123,8 @@ pub enum ImpliedBound<'tcx> {
 /// Compute the implied bounds that a callee/impl can assume based on
 /// the fact that caller/projector has ensured that `ty` is WF.  See
 /// the `ImpliedBound` type for more details.
-pub fn implied_bounds<'a,'tcx>(
-    infcx: &'a InferCtxt<'a,'tcx>,
+pub fn implied_bounds<'a, 'tcx>(
+    infcx: &'a InferCtxt<'a, 'tcx, 'tcx>,
     body_id: ast::NodeId,
     ty: Ty<'tcx>,
     span: Span)
@@ -228,7 +228,7 @@ fn implied_bounds_from_components<'tcx>(sub_region: ty::Region,
 }
 
 struct WfPredicates<'a,'tcx:'a> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
+    infcx: &'a InferCtxt<'a, 'tcx, 'tcx>,
     body_id: ast::NodeId,
     span: Span,
     out: Vec<traits::PredicateObligation<'tcx>>,
@@ -526,7 +526,7 @@ impl<'a,'tcx> WfPredicates<'a,'tcx> {
 /// `'static` would appear in the list. The hard work is done by
 /// `ty::required_region_bounds`, see that for more information.
 pub fn object_region_bounds<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     principal: &ty::PolyTraitRef<'tcx>,
     others: ty::BuiltinBounds)
     -> Vec<ty::Region>
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 56c0fc248af..47d7e3a0a3c 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -68,12 +68,12 @@ pub enum Ns {
     Value
 }
 
-fn number_of_supplied_defaults<'a, 'tcx, GG>(tcx: TyCtxt<'a, 'tcx>,
+fn number_of_supplied_defaults<'a, 'tcx, GG>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                              substs: &subst::Substs,
                                              space: subst::ParamSpace,
                                              get_generics: GG)
                                              -> usize
-    where GG: FnOnce(TyCtxt<'a, 'tcx>) -> ty::Generics<'tcx>
+    where GG: FnOnce(TyCtxt<'a, 'tcx, 'tcx>) -> ty::Generics<'tcx>
 {
     let generics = get_generics(tcx);
 
@@ -114,7 +114,7 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
                          projections: &[ty::ProjectionPredicate],
                          get_generics: GG)
                          -> fmt::Result
-    where GG: for<'a, 'tcx> FnOnce(TyCtxt<'a, 'tcx>) -> ty::Generics<'tcx>
+    where GG: for<'a, 'tcx> FnOnce(TyCtxt<'a, 'tcx, 'tcx>) -> ty::Generics<'tcx>
 {
     if let (Ns::Value, Some(self_ty)) = (ns, substs.self_ty()) {
         write!(f, "<{} as ", self_ty)?;
@@ -231,7 +231,7 @@ pub fn parameterized<GG>(f: &mut fmt::Formatter,
 }
 
 fn in_binder<'a, 'tcx, T, U>(f: &mut fmt::Formatter,
-                             tcx: TyCtxt<'a, 'tcx>,
+                             tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              original: &ty::Binder<T>,
                              lifted: Option<ty::Binder<U>>) -> fmt::Result
     where T: fmt::Display, U: fmt::Display + TypeFoldable<'tcx>
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index bec645c6ae0..50db6c9bfed 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -233,7 +233,7 @@ fn compatible_borrow_kinds(borrow_kind1: ty::BorrowKind,
 }
 
 impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
-    pub fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.bccx.tcx }
+    pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.bccx.tcx }
 
     pub fn each_issued_loan<F>(&self, node: ast::NodeId, mut op: F) -> bool where
         F: FnMut(&Loan<'tcx>) -> bool,
diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs
index 4a6bc411b91..6ab85d7d449 100644
--- a/src/librustc_borrowck/borrowck/fragments.rs
+++ b/src/librustc_borrowck/borrowck/fragments.rs
@@ -200,7 +200,7 @@ impl FragmentSets {
 }
 
 pub fn instrument_move_fragments<'a, 'tcx>(this: &MoveData<'tcx>,
-                                           tcx: TyCtxt<'a, 'tcx>,
+                                           tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            sp: Span,
                                            id: ast::NodeId) {
     let span_err = tcx.map.attrs(id).iter()
@@ -245,7 +245,7 @@ pub fn instrument_move_fragments<'a, 'tcx>(this: &MoveData<'tcx>,
 ///
 /// Note: "left-over fragments" means paths that were not directly referenced in moves nor
 /// assignments, but must nonetheless be tracked as potential drop obligations.
-pub fn fixup_fragment_sets<'a, 'tcx>(this: &MoveData<'tcx>, tcx: TyCtxt<'a, 'tcx>) {
+pub fn fixup_fragment_sets<'a, 'tcx>(this: &MoveData<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
 
     let mut fragments = this.fragments.borrow_mut();
 
@@ -347,7 +347,7 @@ pub fn fixup_fragment_sets<'a, 'tcx>(this: &MoveData<'tcx>, tcx: TyCtxt<'a, 'tcx
 /// example, if `lp` represents `s.x.j`, then adds moves paths for `s.x.i` and `s.x.k`, the
 /// siblings of `s.x.j`.
 fn add_fragment_siblings<'a, 'tcx>(this: &MoveData<'tcx>,
-                                   tcx: TyCtxt<'a, 'tcx>,
+                                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    gathered_fragments: &mut Vec<Fragment>,
                                    lp: Rc<LoanPath<'tcx>>,
                                    origin_id: Option<ast::NodeId>) {
@@ -406,7 +406,7 @@ fn add_fragment_siblings<'a, 'tcx>(this: &MoveData<'tcx>,
 /// We have determined that `origin_lp` destructures to LpExtend(parent, original_field_name).
 /// Based on this, add move paths for all of the siblings of `origin_lp`.
 fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>,
-                                                 tcx: TyCtxt<'a, 'tcx>,
+                                                 tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                  gathered_fragments: &mut Vec<Fragment>,
                                                  parent_lp: &Rc<LoanPath<'tcx>>,
                                                  mc: mc::MutabilityCategory,
@@ -505,7 +505,7 @@ fn add_fragment_siblings_for_extension<'a, 'tcx>(this: &MoveData<'tcx>,
 /// Adds the single sibling `LpExtend(parent, new_field_name)` of `origin_lp` (the original
 /// loan-path).
 fn add_fragment_sibling_core<'a, 'tcx>(this: &MoveData<'tcx>,
-                                       tcx: TyCtxt<'a, 'tcx>,
+                                       tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        gathered_fragments: &mut Vec<Fragment>,
                                        parent: Rc<LoanPath<'tcx>>,
                                        mc: mc::MutabilityCategory,
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index ef2fb9e4fc0..c6d329bb0ef 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -255,7 +255,7 @@ fn check_mutability<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
 }
 
 impl<'a, 'tcx> GatherLoanCtxt<'a, 'tcx> {
-    pub fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.bccx.tcx }
+    pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.bccx.tcx }
 
     /// Guarantees that `cmt` is assignable, or reports an error.
     fn guarantee_assignment_valid(&mut self,
diff --git a/src/librustc_borrowck/borrowck/mir/dataflow.rs b/src/librustc_borrowck/borrowck/mir/dataflow.rs
index de47fe86ed2..d6dd176e3ba 100644
--- a/src/librustc_borrowck/borrowck/mir/dataflow.rs
+++ b/src/librustc_borrowck/borrowck/mir/dataflow.rs
@@ -459,7 +459,7 @@ impl<D: BitDenotation> DataflowState<D> {
 
 
 impl<'a, 'tcx> DataflowState<MoveData<'tcx>> {
-    pub fn new_move_analysis(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx>) -> Self {
+    pub fn new_move_analysis(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
         let move_data = MoveData::gather_moves(mir, tcx);
         DataflowState::new(mir, move_data)
     }
diff --git a/src/librustc_borrowck/borrowck/mir/gather_moves.rs b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
index 2b835124fa1..bf3d671bdb5 100644
--- a/src/librustc_borrowck/borrowck/mir/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/mir/gather_moves.rs
@@ -483,7 +483,7 @@ impl<'a, 'tcx> MovePathDataBuilder<'a, 'tcx> {
 }
 
 impl<'a, 'tcx> MoveData<'tcx> {
-    pub fn gather_moves(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx>) -> Self {
+    pub fn gather_moves(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
         gather_moves(mir, tcx)
     }
 }
@@ -494,7 +494,7 @@ enum StmtKind {
     Aggregate, Drop, CallFn, CallArg, Return,
 }
 
-fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx>) -> MoveData<'tcx> {
+fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MoveData<'tcx> {
     use self::StmtKind as SK;
 
     let bbs = mir.all_basic_blocks();
@@ -667,7 +667,7 @@ fn gather_moves<'a, 'tcx>(mir: &Mir<'tcx>, tcx: TyCtxt<'a, 'tcx>) -> MoveData<'t
 }
 
 struct BlockContext<'b, 'a: 'b, 'tcx: 'a> {
-    tcx: TyCtxt<'b, 'tcx>,
+    tcx: TyCtxt<'b, 'tcx, 'tcx>,
     moves: &'b mut Vec<MoveOut>,
     builder: MovePathDataBuilder<'a, 'tcx>,
     path_map: &'b mut Vec<Vec<MoveOutIndex>>,
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index c9046374464..cfc12a71082 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -100,7 +100,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for BorrowckCtxt<'a, 'tcx> {
     }
 }
 
-pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, mir_map: &MirMap<'tcx>) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, mir_map: &MirMap<'tcx>) {
     let mut bccx = BorrowckCtxt {
         tcx: tcx,
         mir_map: Some(mir_map),
@@ -244,7 +244,7 @@ fn build_borrowck_dataflow_data<'a, 'tcx>(this: &mut BorrowckCtxt<'a, 'tcx>,
 /// Accessor for introspective clients inspecting `AnalysisData` and
 /// the `BorrowckCtxt` itself , e.g. the flowgraph visualizer.
 pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mir_map: Option<&'a MirMap<'tcx>>,
     fn_parts: FnParts<'a>,
     cfg: &cfg::CFG)
@@ -278,7 +278,7 @@ pub fn build_borrowck_dataflow_data_for_fn<'a, 'tcx>(
 // Type definitions
 
 pub struct BorrowckCtxt<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 
     // Hacky. As we visit various fns, we have to load up the
     // free-region map for each one. This map is computed by during
@@ -427,7 +427,7 @@ pub fn closure_to_block(closure_id: ast::NodeId,
 }
 
 impl<'a, 'tcx> LoanPath<'tcx> {
-    pub fn kill_scope(&self, tcx: TyCtxt<'a, 'tcx>) -> region::CodeExtent {
+    pub fn kill_scope(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> region::CodeExtent {
         match self.kind {
             LpVar(local_id) => tcx.region_maps.var_scope(local_id),
             LpUpvar(upvar_id) => {
diff --git a/src/librustc_borrowck/borrowck/move_data.rs b/src/librustc_borrowck/borrowck/move_data.rs
index 0f9e490322a..a7422600186 100644
--- a/src/librustc_borrowck/borrowck/move_data.rs
+++ b/src/librustc_borrowck/borrowck/move_data.rs
@@ -272,7 +272,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
 
     /// Returns the existing move path index for `lp`, if any, and otherwise adds a new index for
     /// `lp` and any of its base paths that do not yet have an index.
-    pub fn move_path(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn move_path(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                      lp: Rc<LoanPath<'tcx>>) -> MovePathIndex {
         match self.path_map.borrow().get(&lp) {
             Some(&index) => {
@@ -363,7 +363,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
     }
 
     /// Adds a new move entry for a move of `lp` that occurs at location `id` with kind `kind`.
-    pub fn add_move(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn add_move(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     lp: Rc<LoanPath<'tcx>>,
                     id: ast::NodeId,
                     kind: MoveKind) {
@@ -390,7 +390,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
 
     /// Adds a new record for an assignment to `lp` that occurs at location `id` with the given
     /// `span`.
-    pub fn add_assignment(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn add_assignment(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           lp: Rc<LoanPath<'tcx>>,
                           assign_id: ast::NodeId,
                           span: Span,
@@ -434,7 +434,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
     /// variant `lp`, that occurs at location `pattern_id`.  (One
     /// should be able to recover the span info from the
     /// `pattern_id` and the ast_map, I think.)
-    pub fn add_variant_match(&self, tcx: TyCtxt<'a, 'tcx>,
+    pub fn add_variant_match(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              lp: Rc<LoanPath<'tcx>>,
                              pattern_id: ast::NodeId,
                              base_lp: Rc<LoanPath<'tcx>>,
@@ -457,7 +457,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
         self.variant_matches.borrow_mut().push(variant_match);
     }
 
-    fn fixup_fragment_sets(&self, tcx: TyCtxt<'a, 'tcx>) {
+    fn fixup_fragment_sets(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) {
         fragments::fixup_fragment_sets(self, tcx)
     }
 
@@ -466,7 +466,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
     /// Moves are generated by moves and killed by assignments and
     /// scoping. Assignments are generated by assignment to variables and
     /// killed by scoping. See `README.md` for more details.
-    fn add_gen_kills(&self, tcx: TyCtxt<'a, 'tcx>,
+    fn add_gen_kills(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                      dfcx_moves: &mut MoveDataFlow,
                      dfcx_assign: &mut AssignDataFlow) {
         for (i, the_move) in self.moves.borrow().iter().enumerate() {
@@ -595,7 +595,7 @@ impl<'a, 'tcx> MoveData<'tcx> {
 
 impl<'a, 'tcx> FlowedMoveData<'a, 'tcx> {
     pub fn new(move_data: MoveData<'tcx>,
-               tcx: TyCtxt<'a, 'tcx>,
+               tcx: TyCtxt<'a, 'tcx, 'tcx>,
                cfg: &cfg::CFG,
                id_range: IdRange,
                decl: &hir::FnDecl,
diff --git a/src/librustc_const_eval/check_match.rs b/src/librustc_const_eval/check_match.rs
index 4a88b8c7d91..bde9a856cc4 100644
--- a/src/librustc_const_eval/check_match.rs
+++ b/src/librustc_const_eval/check_match.rs
@@ -106,7 +106,7 @@ impl<'a> FromIterator<Vec<&'a Pat>> for Matrix<'a> {
 
 //NOTE: appears to be the only place other then InferCtxt to contain a ParamEnv
 pub struct MatchCheckCtxt<'a, 'tcx: 'a> {
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub param_env: ParameterEnvironment<'a, 'tcx>,
 }
 
@@ -153,7 +153,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: TyCtxt) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     tcx.visit_all_items_in_krate(DepNode::MatchCheck, &mut MatchCheckCtxt {
         tcx: tcx,
         param_env: tcx.empty_parameter_environment(),
@@ -455,13 +455,13 @@ fn const_val_to_expr(value: &ConstVal) -> P<hir::Expr> {
 }
 
 pub struct StaticInliner<'a, 'tcx: 'a> {
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub failed: bool,
     pub renaming_map: Option<&'a mut FnvHashMap<(NodeId, Span), NodeId>>,
 }
 
 impl<'a, 'tcx> StaticInliner<'a, 'tcx> {
-    pub fn new<'b>(tcx: TyCtxt<'b, 'tcx>,
+    pub fn new<'b>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                    renaming_map: Option<&'b mut FnvHashMap<(NodeId, Span), NodeId>>)
                    -> StaticInliner<'b, 'tcx> {
         StaticInliner {
diff --git a/src/librustc_const_eval/eval.rs b/src/librustc_const_eval/eval.rs
index 445cb229bdb..eaf1d6ad6d2 100644
--- a/src/librustc_const_eval/eval.rs
+++ b/src/librustc_const_eval/eval.rs
@@ -54,7 +54,7 @@ macro_rules! math {
     }
 }
 
-fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   enum_def: DefId,
                                   variant_def: DefId)
                                   -> Option<&'tcx Expr> {
@@ -90,7 +90,7 @@ fn lookup_variant_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
 ///
 /// `substs` is optional and is used for associated constants.
 /// This generally happens in late/trans const evaluation.
-pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx>,
+pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         def_id: DefId,
                                         substs: Option<subst::Substs<'tcx>>)
                                         -> Option<(&'tcx Expr, Option<ty::Ty<'tcx>>)> {
@@ -182,8 +182,9 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx>,
     }
 }
 
-fn inline_const_fn_from_external_crate(tcx: TyCtxt, def_id: DefId)
-                                       -> Option<ast::NodeId> {
+fn inline_const_fn_from_external_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                 def_id: DefId)
+                                                 -> Option<ast::NodeId> {
     match tcx.extern_const_fns.borrow().get(&def_id) {
         Some(&ast::DUMMY_NODE_ID) => return None,
         Some(&fn_id) => return Some(fn_id),
@@ -205,7 +206,7 @@ fn inline_const_fn_from_external_crate(tcx: TyCtxt, def_id: DefId)
     fn_id
 }
 
-pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, def_id: DefId)
+pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId)
                                        -> Option<FnLikeNode<'tcx>>
 {
     let fn_id = if let Some(node_id) = tcx.map.as_local_node_id(def_id) {
@@ -238,8 +239,11 @@ pub fn lookup_const_fn_by_id<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, def_id: DefId)
     }
 }
 
-pub fn const_expr_to_pat(tcx: TyCtxt, expr: &Expr, pat_id: ast::NodeId, span: Span)
-                         -> Result<P<hir::Pat>, DefId> {
+pub fn const_expr_to_pat<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   expr: &Expr,
+                                   pat_id: ast::NodeId,
+                                   span: Span)
+                                   -> Result<P<hir::Pat>, DefId> {
     let pat_ty = tcx.expr_ty(expr);
     debug!("expr={:?} pat_ty={:?} pat_id={}", expr, pat_ty, pat_id);
     match pat_ty.sty {
@@ -339,7 +343,8 @@ pub fn const_expr_to_pat(tcx: TyCtxt, expr: &Expr, pat_id: ast::NodeId, span: Sp
     Ok(P(hir::Pat { id: expr.id, node: pat, span: span }))
 }
 
-pub fn eval_const_expr(tcx: TyCtxt, e: &Expr) -> ConstVal {
+pub fn eval_const_expr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 e: &Expr) -> ConstVal {
     match eval_const_expr_partial(tcx, e, ExprTypeChecked, None) {
         Ok(r) => r,
         // non-const path still needs to be a fatal error, because enums are funky
@@ -526,7 +531,7 @@ macro_rules! signal {
 /// guaranteed to be evaluatable. `ty_hint` is usually ExprTypeChecked,
 /// but a few places need to evaluate constants during type-checking, like
 /// computing the length of an array. (See also the FIXME above EvalHint.)
-pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                          e: &Expr,
                                          ty_hint: EvalHint<'tcx>,
                                          fn_args: FnArgMap) -> EvalResult {
@@ -932,7 +937,7 @@ pub fn eval_const_expr_partial<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
 }
 
 fn infer<'a, 'tcx>(i: ConstInt,
-                   tcx: TyCtxt<'a, 'tcx>,
+                   tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    ty_hint: &ty::TypeVariants<'tcx>)
                    -> Result<ConstInt, ErrKind> {
     use syntax::ast::*;
@@ -996,7 +1001,7 @@ fn infer<'a, 'tcx>(i: ConstInt,
     }
 }
 
-fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx>,
+fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                 ti: &'tcx hir::TraitItem,
                                                 trait_id: DefId,
                                                 rcvr_substs: subst::Substs<'tcx>)
@@ -1053,7 +1058,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: TyCtxt<'a, 'tcx>,
     }
 }
 
-fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, val: ConstInt, ty: ty::Ty) -> CastResult {
+fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstInt, ty: ty::Ty) -> CastResult {
     let v = val.to_u64_unchecked();
     match ty.sty {
         ty::TyBool if v == 0 => Ok(Bool(false)),
@@ -1098,7 +1103,7 @@ fn cast_const_int<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, val: ConstInt, ty: ty::Ty) ->
     }
 }
 
-fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, f: f64, ty: ty::Ty) -> CastResult {
+fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, f: f64, ty: ty::Ty) -> CastResult {
     match ty.sty {
         ty::TyInt(_) if f >= 0.0 => cast_const_int(tcx, Infer(f as u64), ty),
         ty::TyInt(_) => cast_const_int(tcx, InferSigned(f as i64), ty),
@@ -1109,7 +1114,7 @@ fn cast_const_float<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, f: f64, ty: ty::Ty) -> Cast
     }
 }
 
-fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult {
+fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, val: ConstVal, ty: ty::Ty) -> CastResult {
     match val {
         Integral(i) => cast_const_int(tcx, i, ty),
         Bool(b) => cast_const_int(tcx, Infer(b as u64), ty),
@@ -1127,7 +1132,7 @@ fn cast_const<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, val: ConstVal, ty: ty::Ty) -> Cas
 }
 
 fn lit_to_const<'a, 'tcx>(lit: &ast::LitKind,
-                          tcx: TyCtxt<'a, 'tcx>,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           ty_hint: Option<Ty<'tcx>>,
                           span: Span)
                           -> Result<ConstVal, ErrKind> {
@@ -1197,7 +1202,7 @@ pub fn compare_const_vals(a: &ConstVal, b: &ConstVal) -> Option<Ordering> {
     }
 }
 
-pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    a: &Expr,
                                    b: &Expr) -> Option<Ordering> {
     let a = match eval_const_expr_partial(tcx, a, ExprTypeChecked, None) {
@@ -1219,7 +1224,8 @@ pub fn compare_lit_exprs<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
 
 
 /// Returns the repeat count for a repeating vector expression.
-pub fn eval_repeat_count(tcx: TyCtxt, count_expr: &hir::Expr) -> usize {
+pub fn eval_repeat_count<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                   count_expr: &hir::Expr) -> usize {
     let hint = UncheckedExprHint(tcx.types.usize);
     match eval_const_expr_partial(tcx, count_expr, hint, None) {
         Ok(Integral(Usize(count))) => {
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index 7707376f0a0..f0c2de29327 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -367,7 +367,7 @@ pub struct CompileState<'a, 'b, 'ast: 'a, 'tcx: 'b> where 'ast: 'tcx {
     pub resolutions: Option<&'a Resolutions>,
     pub mir_map: Option<&'b MirMap<'tcx>>,
     pub analysis: Option<&'a ty::CrateAnalysis<'a>>,
-    pub tcx: Option<TyCtxt<'b, 'tcx>>,
+    pub tcx: Option<TyCtxt<'b, 'tcx, 'tcx>>,
     pub trans: Option<&'a trans::CrateTranslation>,
 }
 
@@ -464,7 +464,7 @@ impl<'a, 'b, 'ast, 'tcx> CompileState<'a, 'b, 'ast, 'tcx> {
                             hir_crate: &'a hir::Crate,
                             analysis: &'a ty::CrateAnalysis<'a>,
                             mir_map: Option<&'b MirMap<'tcx>>,
-                            tcx: TyCtxt<'b, 'tcx>,
+                            tcx: TyCtxt<'b, 'tcx, 'tcx>,
                             crate_name: &'a str)
                             -> CompileState<'a, 'b, 'ast, 'tcx> {
         CompileState {
@@ -817,7 +817,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
                                                name: &str,
                                                f: F)
                                                -> Result<R, usize>
-    where F: for<'a> FnOnce(TyCtxt<'a, 'tcx>,
+    where F: for<'a> FnOnce(TyCtxt<'a, 'tcx, 'tcx>,
                             Option<MirMap<'tcx>>,
                             ty::CrateAnalysis,
                             CompileResult) -> R
@@ -992,7 +992,7 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: &'tcx Session,
 }
 
 /// Run the translation phase to LLVM, after which the AST and analysis can
-pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn phase_4_translate_to_llvm<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                            mut mir_map: MirMap<'tcx>,
                                            analysis: ty::CrateAnalysis)
                                            -> trans::CrateTranslation {
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index bb90789c14a..d841f7c86a9 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -469,7 +469,7 @@ impl<'ast> pprust::PpAnn for HygieneAnnotation<'ast> {
 
 
 struct TypedAnnotation<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'b, 'tcx> HirPrinterSupport<'tcx> for TypedAnnotation<'b, 'tcx> {
@@ -690,7 +690,7 @@ impl fold::Folder for ReplaceBodyWithLoop {
 }
 
 fn print_flowgraph<'a, 'tcx, W: Write>(variants: Vec<borrowck_dot::Variant>,
-                                       tcx: TyCtxt<'a, 'tcx>,
+                                       tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        mir_map: Option<&MirMap<'tcx>>,
                                        code: blocks::Code,
                                        mode: PpFlowGraphMode,
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index c92ede68b99..b2de22583dc 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -43,7 +43,7 @@ use syntax::feature_gate::UnstableFeatures;
 use rustc::hir;
 
 struct Env<'a, 'tcx: 'a> {
-    infcx: &'a infer::InferCtxt<'a, 'tcx>,
+    infcx: &'a infer::InferCtxt<'a, 'tcx, 'tcx>,
 }
 
 struct RH<'a> {
@@ -160,7 +160,7 @@ fn test_env<F>(source_string: &str,
 }
 
 impl<'a, 'tcx> Env<'a, 'tcx> {
-    pub fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
@@ -354,25 +354,25 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
         infer::TypeTrace::dummy(self.tcx())
     }
 
-    pub fn sub(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
+    pub fn sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
         let trace = self.dummy_type_trace();
-        self.infcx.sub(true, trace, t1, t2)
+        self.infcx.sub(true, trace, &t1, &t2)
     }
 
-    pub fn lub(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
+    pub fn lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
         let trace = self.dummy_type_trace();
-        self.infcx.lub(true, trace, t1, t2)
+        self.infcx.lub(true, trace, &t1, &t2)
     }
 
-    pub fn glb(&self, t1: &Ty<'tcx>, t2: &Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
+    pub fn glb(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) -> InferResult<'tcx, Ty<'tcx>> {
         let trace = self.dummy_type_trace();
-        self.infcx.glb(true, trace, t1, t2)
+        self.infcx.glb(true, trace, &t1, &t2)
     }
 
     /// Checks that `t1 <: t2` is true (this may register additional
     /// region checks).
     pub fn check_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
-        match self.sub(&t1, &t2) {
+        match self.sub(t1, t2) {
             Ok(InferOk { obligations, .. }) => {
                 // FIXME(#32730) once obligations are being propagated, assert the right thing.
                 assert!(obligations.is_empty());
@@ -386,7 +386,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     /// Checks that `t1 <: t2` is false (this may register additional
     /// region checks).
     pub fn check_not_sub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>) {
-        match self.sub(&t1, &t2) {
+        match self.sub(t1, t2) {
             Err(_) => {}
             Ok(_) => {
                 panic!("unexpected success computing sub({:?},{:?})", t1, t2);
@@ -396,7 +396,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
 
     /// Checks that `LUB(t1,t2) == t_lub`
     pub fn check_lub(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_lub: Ty<'tcx>) {
-        match self.lub(&t1, &t2) {
+        match self.lub(t1, t2) {
             Ok(InferOk { obligations, value: t }) => {
                 // FIXME(#32730) once obligations are being propagated, assert the right thing.
                 assert!(obligations.is_empty());
@@ -412,7 +412,7 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     /// Checks that `GLB(t1,t2) == t_glb`
     pub fn check_glb(&self, t1: Ty<'tcx>, t2: Ty<'tcx>, t_glb: Ty<'tcx>) {
         debug!("check_glb(t1={}, t2={}, t_glb={})", t1, t2, t_glb);
-        match self.glb(&t1, &t2) {
+        match self.glb(t1, t2) {
             Err(e) => {
                 panic!("unexpected error computing LUB: {:?}", e)
             }
diff --git a/src/librustc_incremental/assert_dep_graph.rs b/src/librustc_incremental/assert_dep_graph.rs
index 3a41a377d20..b74e7e21226 100644
--- a/src/librustc_incremental/assert_dep_graph.rs
+++ b/src/librustc_incremental/assert_dep_graph.rs
@@ -63,7 +63,7 @@ const IF_THIS_CHANGED: &'static str = "rustc_if_this_changed";
 const THEN_THIS_WOULD_NEED: &'static str = "rustc_then_this_would_need";
 const ID: &'static str = "id";
 
-pub fn assert_dep_graph(tcx: TyCtxt) {
+pub fn assert_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _ignore = tcx.dep_graph.in_ignore();
 
     if tcx.sess.opts.debugging_opts.dump_dep_graph {
@@ -98,7 +98,7 @@ type TargetHashMap =
                FnvHashSet<(Span, InternedString, ast::NodeId, DepNode<DefId>)>>;
 
 struct IfThisChanged<'a, 'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     if_this_changed: SourceHashMap,
     then_this_would_need: TargetHashMap,
 }
@@ -172,9 +172,9 @@ impl<'a, 'tcx> Visitor<'tcx> for IfThisChanged<'a, 'tcx> {
     }
 }
 
-fn check_paths(tcx: TyCtxt,
-               if_this_changed: &SourceHashMap,
-               then_this_would_need: &TargetHashMap)
+fn check_paths<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         if_this_changed: &SourceHashMap,
+                         then_this_would_need: &TargetHashMap)
 {
     // Return early here so as not to construct the query, which is not cheap.
     if if_this_changed.is_empty() {
diff --git a/src/librustc_incremental/calculate_svh.rs b/src/librustc_incremental/calculate_svh.rs
index 73af4acfe49..ef3ac4c3426 100644
--- a/src/librustc_incremental/calculate_svh.rs
+++ b/src/librustc_incremental/calculate_svh.rs
@@ -27,7 +27,7 @@ pub trait SvhCalculate {
     fn calculate_item_hash(self, def_id: DefId) -> u64;
 }
 
-impl<'a, 'tcx> SvhCalculate for TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> SvhCalculate for TyCtxt<'a, 'tcx, 'tcx> {
     fn calculate_krate_hash(self) -> Svh {
         // FIXME (#14132): This is better than it used to be, but it still not
         // ideal. We now attempt to hash only the relevant portions of the
@@ -118,13 +118,13 @@ mod svh_visitor {
     use std::hash::{Hash, SipHasher};
 
     pub struct StrictVersionHashVisitor<'a, 'tcx: 'a> {
-        pub tcx: TyCtxt<'a, 'tcx>,
+        pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
         pub st: &'a mut SipHasher,
     }
 
     impl<'a, 'tcx> StrictVersionHashVisitor<'a, 'tcx> {
         pub fn new(st: &'a mut SipHasher,
-                   tcx: TyCtxt<'a, 'tcx>)
+                   tcx: TyCtxt<'a, 'tcx, 'tcx>)
                    -> Self {
             StrictVersionHashVisitor { st: st, tcx: tcx }
         }
diff --git a/src/librustc_incremental/persist/directory.rs b/src/librustc_incremental/persist/directory.rs
index 299254959c7..e256b7cf7d0 100644
--- a/src/librustc_incremental/persist/directory.rs
+++ b/src/librustc_incremental/persist/directory.rs
@@ -63,13 +63,13 @@ impl RetracedDefIdDirectory {
 }
 
 pub struct DefIdDirectoryBuilder<'a,'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     hash: DefIdMap<Option<DefPathIndex>>,
     directory: DefIdDirectory,
 }
 
 impl<'a,'tcx> DefIdDirectoryBuilder<'a,'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> DefIdDirectoryBuilder<'a, 'tcx> {
         DefIdDirectoryBuilder {
             tcx: tcx,
             hash: DefIdMap(),
diff --git a/src/librustc_incremental/persist/dirty_clean.rs b/src/librustc_incremental/persist/dirty_clean.rs
index 9c1452acb84..dee4d667b8d 100644
--- a/src/librustc_incremental/persist/dirty_clean.rs
+++ b/src/librustc_incremental/persist/dirty_clean.rs
@@ -38,7 +38,7 @@ const CLEAN: &'static str = "rustc_clean";
 const LABEL: &'static str = "label";
 const CFG: &'static str = "cfg";
 
-pub fn check_dirty_clean_annotations(tcx: TyCtxt) {
+pub fn check_dirty_clean_annotations<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _ignore = tcx.dep_graph.in_ignore();
     let query = tcx.dep_graph.query();
     let krate = tcx.map.krate();
@@ -49,7 +49,7 @@ pub fn check_dirty_clean_annotations(tcx: TyCtxt) {
 }
 
 pub struct DirtyCleanVisitor<'a, 'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     query: &'a DepGraphQuery<DefId>,
 }
 
diff --git a/src/librustc_incremental/persist/load.rs b/src/librustc_incremental/persist/load.rs
index fbebb732e99..f9e479745d1 100644
--- a/src/librustc_incremental/persist/load.rs
+++ b/src/librustc_incremental/persist/load.rs
@@ -37,7 +37,7 @@ type CleanEdges = Vec<(DepNode<DefId>, DepNode<DefId>)>;
 /// early in compilation, before we've really done any work, but
 /// actually it doesn't matter all that much.) See `README.md` for
 /// more general overview.
-pub fn load_dep_graph(tcx: TyCtxt) {
+pub fn load_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _ignore = tcx.dep_graph.in_ignore();
 
     if let Some(dep_graph) = dep_graph_path(tcx) {
@@ -47,7 +47,7 @@ pub fn load_dep_graph(tcx: TyCtxt) {
     }
 }
 
-pub fn load_dep_graph_if_exists(tcx: TyCtxt, path: &Path) {
+pub fn load_dep_graph_if_exists<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, path: &Path) {
     if !path.exists() {
         return;
     }
@@ -74,7 +74,9 @@ pub fn load_dep_graph_if_exists(tcx: TyCtxt, path: &Path) {
     }
 }
 
-pub fn decode_dep_graph(tcx: TyCtxt, data: &[u8]) -> Result<(), Error>
+pub fn decode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                  data: &[u8])
+                                  -> Result<(), Error>
 {
     // Deserialize the directory and dep-graph.
     let mut decoder = Decoder::new(data, 0);
@@ -128,10 +130,10 @@ pub fn decode_dep_graph(tcx: TyCtxt, data: &[u8]) -> Result<(), Error>
     Ok(())
 }
 
-fn initial_dirty_nodes(tcx: TyCtxt,
-                       hashed_items: &[SerializedHash],
-                       retraced: &RetracedDefIdDirectory)
-                       -> DirtyNodes {
+fn initial_dirty_nodes<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 hashed_items: &[SerializedHash],
+                                 retraced: &RetracedDefIdDirectory)
+                                 -> DirtyNodes {
     let mut items_removed = false;
     let mut dirty_nodes = FnvHashSet();
     for hashed_item in hashed_items {
diff --git a/src/librustc_incremental/persist/save.rs b/src/librustc_incremental/persist/save.rs
index 2d40e78dee2..cbb3464f3ef 100644
--- a/src/librustc_incremental/persist/save.rs
+++ b/src/librustc_incremental/persist/save.rs
@@ -20,7 +20,7 @@ use super::data::*;
 use super::directory::*;
 use super::util::*;
 
-pub fn save_dep_graph(tcx: TyCtxt) {
+pub fn save_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _ignore = tcx.dep_graph.in_ignore();
 
     if let Some(dep_graph) = dep_graph_path(tcx) {
@@ -68,7 +68,9 @@ pub fn save_dep_graph(tcx: TyCtxt) {
     }
 }
 
-pub fn encode_dep_graph(tcx: TyCtxt, encoder: &mut Encoder) -> io::Result<()> {
+pub fn encode_dep_graph<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                  encoder: &mut Encoder)
+                                  -> io::Result<()> {
     // Here we take advantage of how RBML allows us to skip around
     // and encode the depgraph as a two-part structure:
     //
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index c73d0f368b7..4e6b88eb434 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -792,9 +792,9 @@ impl LateLintPass for UnconditionalRecursion {
         }
 
         // Check if the expression `id` performs a call to `method`.
-        fn expr_refers_to_this_method(tcx: TyCtxt,
-                                      method: &ty::Method,
-                                      id: ast::NodeId) -> bool {
+        fn expr_refers_to_this_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                                method: &ty::Method,
+                                                id: ast::NodeId) -> bool {
             // Check for method calls and overloaded operators.
             let opt_m = tcx.tables.borrow().method_map.get(&ty::MethodCall::expr(id)).cloned();
             if let Some(m) = opt_m {
@@ -840,7 +840,7 @@ impl LateLintPass for UnconditionalRecursion {
 
         // Check if the method call to the method with the ID `callee_id`
         // and instantiated with `callee_substs` refers to method `method`.
-        fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+        fn method_call_refers_to_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                   method: &ty::Method,
                                                   callee_id: DefId,
                                                   callee_substs: &Substs<'tcx>,
diff --git a/src/librustc_lint/types.rs b/src/librustc_lint/types.rs
index ebb348164e1..892924db6fa 100644
--- a/src/librustc_lint/types.rs
+++ b/src/librustc_lint/types.rs
@@ -294,8 +294,10 @@ impl LateLintPass for TypeLimits {
             }
         }
 
-        fn check_limits(tcx: TyCtxt, binop: hir::BinOp,
-                        l: &hir::Expr, r: &hir::Expr) -> bool {
+        fn check_limits<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                  binop: hir::BinOp,
+                                  l: &hir::Expr,
+                                  r: &hir::Expr) -> bool {
             let (lit, expr, swap) = match (&l.node, &r.node) {
                 (&hir::ExprLit(_), _) => (l, r, true),
                 (_, &hir::ExprLit(_)) => (r, l, false),
@@ -375,7 +377,7 @@ enum FfiResult {
 /// to function pointers and references, but could be
 /// expanded to cover NonZero raw pointers and newtypes.
 /// FIXME: This duplicates code in trans.
-fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn is_repr_nullable_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   def: ty::AdtDef<'tcx>,
                                   substs: &Substs<'tcx>)
                                   -> bool {
diff --git a/src/librustc_metadata/astencode.rs b/src/librustc_metadata/astencode.rs
index 377b93c28b5..86e38274245 100644
--- a/src/librustc_metadata/astencode.rs
+++ b/src/librustc_metadata/astencode.rs
@@ -60,7 +60,7 @@ use rustc_serialize::{Encodable, EncoderHelpers};
 #[cfg(test)] use rustc::hir::lowering::{lower_item, LoweringContext, DummyResolver};
 
 struct DecodeContext<'a, 'b, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     cdata: &'b cstore::crate_metadata,
     from_id_range: IdRange,
     to_id_range: IdRange,
@@ -123,7 +123,7 @@ impl<'a, 'b, 'c, 'tcx> ast_map::FoldOps for &'a DecodeContext<'b, 'c, 'tcx> {
 /// Decodes an item from its AST in the cdata's metadata and adds it to the
 /// ast-map.
 pub fn decode_inlined_item<'a, 'tcx>(cdata: &cstore::crate_metadata,
-                                     tcx: TyCtxt<'a, 'tcx>,
+                                     tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      parent_def_path: ast_map::DefPath,
                                      parent_did: DefId,
                                      ast_doc: rbml::Doc,
@@ -861,17 +861,17 @@ trait rbml_decoder_decoder_helpers<'tcx> {
 
     // Versions of the type reading functions that don't need the full
     // DecodeContext.
-    fn read_ty_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>,
+    fn read_ty_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                          cdata: &cstore::crate_metadata) -> Ty<'tcx>;
-    fn read_tys_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>,
+    fn read_tys_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>>;
-    fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>,
+    fn read_substs_nodcx<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              cdata: &cstore::crate_metadata)
                              -> subst::Substs<'tcx>;
 }
 
 impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
-    fn read_ty_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx>,
+    fn read_ty_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
                          cdata: &cstore::crate_metadata)
                          -> Ty<'tcx> {
         self.read_opaque(|_, doc| {
@@ -882,7 +882,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
         }).unwrap()
     }
 
-    fn read_tys_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx>,
+    fn read_tys_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
                           cdata: &cstore::crate_metadata) -> Vec<Ty<'tcx>> {
         self.read_to_vec(|this| Ok(this.read_ty_nodcx(tcx, cdata)) )
             .unwrap()
@@ -890,7 +890,7 @@ impl<'a, 'tcx> rbml_decoder_decoder_helpers<'tcx> for reader::Decoder<'a> {
             .collect()
     }
 
-    fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx>,
+    fn read_substs_nodcx<'b>(&mut self, tcx: TyCtxt<'b, 'tcx, 'tcx>,
                              cdata: &cstore::crate_metadata)
                              -> subst::Substs<'tcx>
     {
diff --git a/src/librustc_metadata/csearch.rs b/src/librustc_metadata/csearch.rs
index 70d4078a106..8d464099783 100644
--- a/src/librustc_metadata/csearch.rs
+++ b/src/librustc_metadata/csearch.rs
@@ -61,7 +61,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         decoder::closure_kind(&cdata, def_id.index)
     }
 
-    fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx>
+    fn closure_ty<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> ty::ClosureTy<'tcx>
     {
         assert!(!def_id.is_local());
         let cdata = self.get_crate_data(def_id.krate);
@@ -78,21 +78,21 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         decoder::get_repr_attrs(&cdata, def.index)
     }
 
-    fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_type<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                      -> ty::TypeScheme<'tcx>
     {
         let cdata = self.get_crate_data(def.krate);
         decoder::get_type(&cdata, def.index, tcx)
     }
 
-    fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                            -> ty::GenericPredicates<'tcx>
     {
         let cdata = self.get_crate_data(def.krate);
         decoder::get_predicates(&cdata, def.index, tcx)
     }
 
-    fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn item_super_predicates<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                  -> ty::GenericPredicates<'tcx>
     {
         let cdata = self.get_crate_data(def.krate);
@@ -111,13 +111,13 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         decoder::get_symbol(&cdata, def.index)
     }
 
-    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId) -> ty::TraitDef<'tcx>
+    fn trait_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::TraitDef<'tcx>
     {
         let cdata = self.get_crate_data(def.krate);
         decoder::get_trait_def(&cdata, def.index, tcx)
     }
 
-    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>
+    fn adt_def<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId) -> ty::AdtDefMaster<'tcx>
     {
         let cdata = self.get_crate_data(def.krate);
         decoder::get_adt_def(&self.intr, &cdata, def.index, tcx)
@@ -155,7 +155,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         result
     }
 
-    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn provided_trait_methods<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                                   -> Vec<Rc<ty::Method<'tcx>>>
     {
         let cdata = self.get_crate_data(def.krate);
@@ -181,7 +181,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         decoder::get_impl_polarity(&cdata, def.index)
     }
 
-    fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn impl_trait_ref<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                           -> Option<ty::TraitRef<'tcx>>
     {
         let cdata = self.get_crate_data(def.krate);
@@ -196,7 +196,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
     }
 
     // FIXME: killme
-    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn associated_consts<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                              -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
         let cdata = self.get_crate_data(def.krate);
         decoder::get_associated_consts(self.intr.clone(), &cdata, def.index, tcx)
@@ -207,13 +207,13 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         decoder::get_parent_impl(&*cdata, impl_def.index)
     }
 
-    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def_id: DefId) -> Option<DefId>
+    fn trait_of_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Option<DefId>
     {
         let cdata = self.get_crate_data(def_id.krate);
         decoder::get_trait_of_item(&cdata, def_id.index, tcx)
     }
 
-    fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn impl_or_trait_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<ty::ImplOrTraitItem<'tcx>>
     {
         let cdata = self.get_crate_data(def.krate);
@@ -247,7 +247,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         decoder::is_default_impl(&cdata, impl_did.index)
     }
 
-    fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx>, did: DefId) -> bool {
+    fn is_extern_item<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, did: DefId) -> bool {
         let cdata = self.get_crate_data(did.krate);
         decoder::is_extern_item(&cdata, did.index, tcx)
     }
@@ -442,14 +442,14 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         result
     }
 
-    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn maybe_get_item_ast<'a>(&'tcx self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> FoundAst<'tcx>
     {
         let cdata = self.get_crate_data(def.krate);
         decoder::maybe_get_item_ast(&cdata, tcx, def.index)
     }
 
-    fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx>, def: DefId)
+    fn maybe_get_item_mir<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>, def: DefId)
                               -> Option<Mir<'tcx>> {
         let cdata = self.get_crate_data(def.krate);
         decoder::maybe_get_item_mir(&cdata, tcx, def.index)
@@ -487,9 +487,9 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         loader::meta_section_name(target)
     }
     fn encode_type<'a>(&self,
-                       tcx: TyCtxt<'a, 'tcx>,
+                       tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        ty: Ty<'tcx>,
-                       def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx>, DefId) -> String)
+                       def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String)
                        -> Vec<u8>
     {
         encoder::encoded_ty(tcx, ty, def_id_to_string)
@@ -510,7 +510,7 @@ impl<'tcx> CrateStore<'tcx> for cstore::CStore {
         self.do_extern_mod_stmt_cnum(emod_id)
     }
 
-    fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx>,
+    fn encode_metadata<'a>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            reexports: &def::ExportMap,
                            item_symbols: &RefCell<NodeMap<String>>,
                            link_meta: &LinkMeta,
diff --git a/src/librustc_metadata/decoder.rs b/src/librustc_metadata/decoder.rs
index ce0856ce5af..860b9f25023 100644
--- a/src/librustc_metadata/decoder.rs
+++ b/src/librustc_metadata/decoder.rs
@@ -223,14 +223,15 @@ fn variant_disr_val(d: rbml::Doc) -> Option<u64> {
     })
 }
 
-fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx>, cdata: Cmd) -> Ty<'tcx> {
+fn doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> {
     let tp = reader::get_doc(doc, tag_items_data_item_type);
     TyDecoder::with_doc(tcx, cdata.cnum, tp,
                         &mut |did| translate_def_id(cdata, did))
         .parse_ty()
 }
 
-fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx>, cdata: Cmd) -> Option<Ty<'tcx>> {
+fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd)
+                            -> Option<Ty<'tcx>> {
     reader::maybe_get_doc(doc, tag_items_data_item_type).map(|tp| {
         TyDecoder::with_doc(tcx, cdata.cnum, tp,
                             &mut |did| translate_def_id(cdata, did))
@@ -239,18 +240,18 @@ fn maybe_doc_type<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx>, cdata: Cmd) -
 }
 
 pub fn item_type<'a, 'tcx>(_item_id: DefId, item: rbml::Doc,
-                           tcx: TyCtxt<'a, 'tcx>, cdata: Cmd) -> Ty<'tcx> {
+                           tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd) -> Ty<'tcx> {
     doc_type(item, tcx, cdata)
 }
 
-fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx>, cdata: Cmd)
+fn doc_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd)
                            -> ty::TraitRef<'tcx> {
     TyDecoder::with_doc(tcx, cdata.cnum, doc,
                         &mut |did| translate_def_id(cdata, did))
         .parse_trait_ref()
 }
 
-fn item_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx>, cdata: Cmd)
+fn item_trait_ref<'a, 'tcx>(doc: rbml::Doc, tcx: TyCtxt<'a, 'tcx, 'tcx>, cdata: Cmd)
                             -> ty::TraitRef<'tcx> {
     let tp = reader::get_doc(doc, tag_item_trait_ref);
     doc_trait_ref(tp, tcx, cdata)
@@ -352,7 +353,7 @@ fn parse_associated_type_names(item_doc: rbml::Doc) -> Vec<ast::Name> {
 
 pub fn get_trait_def<'a, 'tcx>(cdata: Cmd,
                                item_id: DefIndex,
-                               tcx: TyCtxt<'a, 'tcx>) -> ty::TraitDef<'tcx>
+                               tcx: TyCtxt<'a, 'tcx, 'tcx>) -> ty::TraitDef<'tcx>
 {
     let item_doc = cdata.lookup_item(item_id);
     let generics = doc_generics(item_doc, tcx, cdata, tag_item_generics);
@@ -370,7 +371,7 @@ pub fn get_trait_def<'a, 'tcx>(cdata: Cmd,
 pub fn get_adt_def<'a, 'tcx>(intr: &IdentInterner,
                              cdata: Cmd,
                              item_id: DefIndex,
-                             tcx: TyCtxt<'a, 'tcx>)
+                             tcx: TyCtxt<'a, 'tcx, 'tcx>)
                              -> ty::AdtDefMaster<'tcx>
 {
     fn expect_variant_kind(family: Family) -> ty::VariantKind {
@@ -498,7 +499,7 @@ pub fn get_adt_def<'a, 'tcx>(intr: &IdentInterner,
 
 pub fn get_predicates<'a, 'tcx>(cdata: Cmd,
                                 item_id: DefIndex,
-                                tcx: TyCtxt<'a, 'tcx>)
+                                tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                 -> ty::GenericPredicates<'tcx>
 {
     let item_doc = cdata.lookup_item(item_id);
@@ -507,14 +508,14 @@ pub fn get_predicates<'a, 'tcx>(cdata: Cmd,
 
 pub fn get_super_predicates<'a, 'tcx>(cdata: Cmd,
                                       item_id: DefIndex,
-                                      tcx: TyCtxt<'a, 'tcx>)
+                                      tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                       -> ty::GenericPredicates<'tcx>
 {
     let item_doc = cdata.lookup_item(item_id);
     doc_predicates(item_doc, tcx, cdata, tag_item_super_predicates)
 }
 
-pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx>)
+pub fn get_type<'a, 'tcx>(cdata: Cmd, id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
                           -> ty::TypeScheme<'tcx>
 {
     let item_doc = cdata.lookup_item(id);
@@ -593,7 +594,7 @@ pub fn get_custom_coerce_unsized_kind<'tcx>(
 
 pub fn get_impl_trait<'a, 'tcx>(cdata: Cmd,
                                 id: DefIndex,
-                                tcx: TyCtxt<'a, 'tcx>)
+                                tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                 -> Option<ty::TraitRef<'tcx>>
 {
     let item_doc = cdata.lookup_item(id);
@@ -776,7 +777,7 @@ pub fn get_item_name(intr: &IdentInterner, cdata: Cmd, id: DefIndex) -> ast::Nam
     item_name(intr, cdata.lookup_item(id))
 }
 
-pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx>, id: DefIndex)
+pub fn maybe_get_item_ast<'a, 'tcx>(cdata: Cmd, tcx: TyCtxt<'a, 'tcx, 'tcx>, id: DefIndex)
                                     -> FoundAst<'tcx> {
     debug!("Looking up item: {:?}", id);
     let item_doc = cdata.lookup_item(id);
@@ -829,7 +830,7 @@ pub fn is_item_mir_available<'tcx>(cdata: Cmd, id: DefIndex) -> bool {
 }
 
 pub fn maybe_get_item_mir<'a, 'tcx>(cdata: Cmd,
-                                    tcx: TyCtxt<'a, 'tcx>,
+                                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     id: DefIndex)
                                     -> Option<mir::repr::Mir<'tcx>> {
     let item_doc = cdata.lookup_item(id);
@@ -947,7 +948,7 @@ pub fn is_static_method(cdata: Cmd, id: DefIndex) -> bool {
 pub fn get_impl_or_trait_item<'a, 'tcx>(intr: Rc<IdentInterner>,
                                         cdata: Cmd,
                                         id: DefIndex,
-                                        tcx: TyCtxt<'a, 'tcx>)
+                                        tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                         -> Option<ty::ImplOrTraitItem<'tcx>> {
     let item_doc = cdata.lookup_item(id);
 
@@ -1042,7 +1043,7 @@ pub fn get_item_variances(cdata: Cmd, id: DefIndex) -> ty::ItemVariances {
 pub fn get_provided_trait_methods<'a, 'tcx>(intr: Rc<IdentInterner>,
                                             cdata: Cmd,
                                             id: DefIndex,
-                                            tcx: TyCtxt<'a, 'tcx>)
+                                            tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                             -> Vec<Rc<ty::Method<'tcx>>> {
     let item = cdata.lookup_item(id);
 
@@ -1069,7 +1070,7 @@ pub fn get_provided_trait_methods<'a, 'tcx>(intr: Rc<IdentInterner>,
 pub fn get_associated_consts<'a, 'tcx>(intr: Rc<IdentInterner>,
                                        cdata: Cmd,
                                        id: DefIndex,
-                                       tcx: TyCtxt<'a, 'tcx>)
+                                       tcx: TyCtxt<'a, 'tcx, 'tcx>)
                                        -> Vec<Rc<ty::AssociatedConst<'tcx>>> {
     let item = cdata.lookup_item(id);
 
@@ -1443,8 +1444,10 @@ pub fn each_implementation_for_trait<F>(cdata: Cmd,
     }
 }
 
-pub fn get_trait_of_item(cdata: Cmd, id: DefIndex, tcx: TyCtxt)
-                         -> Option<DefId> {
+pub fn get_trait_of_item<'a, 'tcx>(cdata: Cmd,
+                                   id: DefIndex,
+                                   tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                                   -> Option<DefId> {
     let item_doc = cdata.lookup_item(id);
     let parent_item_id = match item_parent_item(cdata, item_doc) {
         None => return None,
@@ -1578,7 +1581,10 @@ pub fn is_const_fn(cdata: Cmd, id: DefIndex) -> bool {
     }
 }
 
-pub fn is_extern_item(cdata: Cmd, id: DefIndex, tcx: TyCtxt) -> bool {
+pub fn is_extern_item<'a, 'tcx>(cdata: Cmd,
+                                id: DefIndex,
+                                tcx: TyCtxt<'a, 'tcx, 'tcx>)
+                                -> bool {
     let item_doc = match cdata.get_item(id) {
         Some(doc) => doc,
         None => return false,
@@ -1614,7 +1620,7 @@ pub fn is_impl(cdata: Cmd, id: DefIndex) -> bool {
 }
 
 fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc,
-                          tcx: TyCtxt<'a, 'tcx>,
+                          tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           cdata: Cmd,
                           tag: usize)
                           -> ty::Generics<'tcx>
@@ -1663,7 +1669,7 @@ fn doc_generics<'a, 'tcx>(base_doc: rbml::Doc,
 
 fn doc_predicate<'a, 'tcx>(cdata: Cmd,
                            doc: rbml::Doc,
-                           tcx: TyCtxt<'a, 'tcx>)
+                           tcx: TyCtxt<'a, 'tcx, 'tcx>)
                            -> ty::Predicate<'tcx>
 {
     let predicate_pos = cdata.xref_index.lookup(
@@ -1675,7 +1681,7 @@ fn doc_predicate<'a, 'tcx>(cdata: Cmd,
 }
 
 fn doc_predicates<'a, 'tcx>(base_doc: rbml::Doc,
-                            tcx: TyCtxt<'a, 'tcx>,
+                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             cdata: Cmd,
                             tag: usize)
                             -> ty::GenericPredicates<'tcx>
@@ -1730,7 +1736,7 @@ pub fn closure_kind(cdata: Cmd, closure_id: DefIndex) -> ty::ClosureKind {
     ty::ClosureKind::decode(&mut decoder).unwrap()
 }
 
-pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx>)
+pub fn closure_ty<'a, 'tcx>(cdata: Cmd, closure_id: DefIndex, tcx: TyCtxt<'a, 'tcx, 'tcx>)
                             -> ty::ClosureTy<'tcx> {
     let closure_doc = cdata.lookup_item(closure_id);
     let closure_ty_doc = reader::get_doc(closure_doc, tag_items_closure_ty);
diff --git a/src/librustc_metadata/encoder.rs b/src/librustc_metadata/encoder.rs
index 7b39ec72ed2..020f12d753e 100644
--- a/src/librustc_metadata/encoder.rs
+++ b/src/librustc_metadata/encoder.rs
@@ -56,7 +56,7 @@ use rustc::hir::map::DefKey;
 
 pub struct EncodeContext<'a, 'tcx: 'a> {
     pub diag: &'a Handler,
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub reexports: &'a def::ExportMap,
     pub item_symbols: &'a RefCell<NodeMap<String>>,
     pub link_meta: &'a LinkMeta,
@@ -1697,7 +1697,7 @@ fn encode_struct_field_attrs(ecx: &EncodeContext,
 
 
 struct ImplVisitor<'a, 'tcx:'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     impls: FnvHashMap<DefId, Vec<DefId>>
 }
 
@@ -2016,9 +2016,9 @@ fn encode_metadata_inner(rbml_w: &mut Encoder,
 }
 
 // Get the encoded string for a type
-pub fn encoded_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn encoded_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             t: Ty<'tcx>,
-                            def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx>, DefId) -> String)
+                            def_id_to_string: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String)
                             -> Vec<u8> {
     let mut wr = Cursor::new(Vec::new());
     tyencode::enc_ty(&mut wr, &tyencode::ctxt {
diff --git a/src/librustc_metadata/tls_context.rs b/src/librustc_metadata/tls_context.rs
index e1354307f7a..23142ca80ef 100644
--- a/src/librustc_metadata/tls_context.rs
+++ b/src/librustc_metadata/tls_context.rs
@@ -25,7 +25,7 @@ use tyencode;
 
 impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tcx> {
 
-    fn tcx<'s>(&'s self) -> TyCtxt<'s, 'tcx> {
+    fn tcx<'s>(&'s self) -> TyCtxt<'s, 'tcx, 'tcx> {
         self.tcx
     }
 
@@ -40,12 +40,12 @@ impl<'a, 'tcx: 'a> tls::EncodingContext<'tcx> for encoder::EncodeContext<'a, 'tc
 
 pub struct DecodingContext<'a, 'tcx: 'a> {
     pub crate_metadata: Cmd<'a>,
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'a, 'tcx: 'a> tls::DecodingContext<'tcx> for DecodingContext<'a, 'tcx> {
 
-    fn tcx<'s>(&'s self) -> TyCtxt<'s, 'tcx> {
+    fn tcx<'s>(&'s self) -> TyCtxt<'s, 'tcx, 'tcx> {
         self.tcx
     }
 
diff --git a/src/librustc_metadata/tydecode.rs b/src/librustc_metadata/tydecode.rs
index 7d2f86c8768..8f33042be01 100644
--- a/src/librustc_metadata/tydecode.rs
+++ b/src/librustc_metadata/tydecode.rs
@@ -41,12 +41,12 @@ pub struct TyDecoder<'a, 'tcx: 'a> {
     data: &'a [u8],
     krate: ast::CrateNum,
     pos: usize,
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     conv_def_id: DefIdConvert<'a>,
 }
 
 impl<'a,'tcx> TyDecoder<'a,'tcx> {
-    pub fn with_doc(tcx: TyCtxt<'a, 'tcx>,
+    pub fn with_doc(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     crate_num: ast::CrateNum,
                     doc: rbml::Doc<'a>,
                     conv: DefIdConvert<'a>)
@@ -57,7 +57,7 @@ impl<'a,'tcx> TyDecoder<'a,'tcx> {
     pub fn new(data: &'a [u8],
                crate_num: ast::CrateNum,
                pos: usize,
-               tcx: TyCtxt<'a, 'tcx>,
+               tcx: TyCtxt<'a, 'tcx, 'tcx>,
                conv: DefIdConvert<'a>)
                -> TyDecoder<'a, 'tcx> {
         TyDecoder {
diff --git a/src/librustc_metadata/tyencode.rs b/src/librustc_metadata/tyencode.rs
index 03f2e2cfd37..b663ba4f0d2 100644
--- a/src/librustc_metadata/tyencode.rs
+++ b/src/librustc_metadata/tyencode.rs
@@ -37,9 +37,9 @@ use encoder;
 pub struct ctxt<'a, 'tcx: 'a> {
     pub diag: &'a Handler,
     // Def -> str Callback:
-    pub ds: for<'b> fn(TyCtxt<'b, 'tcx>, DefId) -> String,
+    pub ds: for<'b> fn(TyCtxt<'b, 'tcx, 'tcx>, DefId) -> String,
     // The type context.
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub abbrevs: &'a abbrev_map<'tcx>
 }
 
diff --git a/src/librustc_mir/build/mod.rs b/src/librustc_mir/build/mod.rs
index c6765f95d33..ac64d1eb65b 100644
--- a/src/librustc_mir/build/mod.rs
+++ b/src/librustc_mir/build/mod.rs
@@ -22,7 +22,7 @@ use syntax::codemap::Span;
 use syntax::parse::token::keywords;
 
 pub struct Builder<'a, 'tcx: 'a> {
-    hir: Cx<'a, 'tcx>,
+    hir: Cx<'a, 'tcx, 'tcx>,
     cfg: CFG<'tcx>,
 
     fn_span: Span,
@@ -160,7 +160,7 @@ macro_rules! unpack {
 ///////////////////////////////////////////////////////////////////////////
 /// the main entry point for building MIR for a function
 
-pub fn construct_fn<'a, 'tcx, A>(hir: Cx<'a,'tcx>,
+pub fn construct_fn<'a, 'tcx, A>(hir: Cx<'a, 'tcx, 'tcx>,
                                  fn_id: ast::NodeId,
                                  arguments: A,
                                  return_ty: ty::FnOutput<'tcx>,
@@ -232,7 +232,7 @@ pub fn construct_fn<'a, 'tcx, A>(hir: Cx<'a,'tcx>,
     builder.finish(upvar_decls, arg_decls, return_ty)
 }
 
-pub fn construct_const<'a, 'tcx>(hir: Cx<'a,'tcx>,
+pub fn construct_const<'a, 'tcx>(hir: Cx<'a, 'tcx, 'tcx>,
                                  item_id: ast::NodeId,
                                  ast_expr: &'tcx hir::Expr)
                                  -> (Mir<'tcx>, ScopeAuxiliaryVec) {
@@ -260,7 +260,7 @@ pub fn construct_const<'a, 'tcx>(hir: Cx<'a,'tcx>,
 }
 
 impl<'a,'tcx> Builder<'a,'tcx> {
-    fn new(hir: Cx<'a, 'tcx>, span: Span) -> Builder<'a, 'tcx> {
+    fn new(hir: Cx<'a, 'tcx, 'tcx>, span: Span) -> Builder<'a, 'tcx> {
         let mut builder = Builder {
             hir: hir,
             cfg: CFG { basic_blocks: vec![] },
diff --git a/src/librustc_mir/build/scope.rs b/src/librustc_mir/build/scope.rs
index 98c2ece6f39..d07a58b981b 100644
--- a/src/librustc_mir/build/scope.rs
+++ b/src/librustc_mir/build/scope.rs
@@ -662,7 +662,7 @@ fn build_scope_drops<'tcx>(cfg: &mut CFG<'tcx>,
     block.unit()
 }
 
-fn build_diverge_scope<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn build_diverge_scope<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  cfg: &mut CFG<'tcx>,
                                  unit_temp: &Lvalue<'tcx>,
                                  scope: &mut Scope<'tcx>,
@@ -721,7 +721,7 @@ fn build_diverge_scope<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
     target
 }
 
-fn build_free<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn build_free<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                         unit_temp: &Lvalue<'tcx>,
                         data: &FreeData<'tcx>,
                         target: BasicBlock)
diff --git a/src/librustc_mir/graphviz.rs b/src/librustc_mir/graphviz.rs
index bbd741c6880..6a34d9ff0b4 100644
--- a/src/librustc_mir/graphviz.rs
+++ b/src/librustc_mir/graphviz.rs
@@ -16,7 +16,7 @@ use std::io::{self, Write};
 use syntax::ast::NodeId;
 
 /// Write a graphviz DOT graph of a list of MIRs.
-pub fn write_mir_graphviz<'a, 'b, 'tcx, W, I>(tcx: TyCtxt<'b, 'tcx>,
+pub fn write_mir_graphviz<'a, 'b, 'tcx, W, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                                               iter: I, w: &mut W)
                                               -> io::Result<()>
 where W: Write, I: Iterator<Item=(&'a NodeId, &'a Mir<'a>)> {
@@ -118,8 +118,11 @@ fn write_edges<W: Write>(source: BasicBlock, mir: &Mir, w: &mut W) -> io::Result
 /// Write the graphviz DOT label for the overall graph. This is essentially a block of text that
 /// will appear below the graph, showing the type of the `fn` this MIR represents and the types of
 /// all the variables and temporaries.
-fn write_graph_label<W: Write>(tcx: TyCtxt, nid: NodeId, mir: &Mir, w: &mut W)
--> io::Result<()> {
+fn write_graph_label<'a, 'tcx, W: Write>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                         nid: NodeId,
+                                         mir: &Mir,
+                                         w: &mut W)
+                                         -> io::Result<()> {
     write!(w, "    label=<fn {}(", dot::escape_html(&tcx.node_path_str(nid)))?;
 
     // fn argument types.
diff --git a/src/librustc_mir/hair/cx/block.rs b/src/librustc_mir/hair/cx/block.rs
index f0ed25902f7..fd568aebea4 100644
--- a/src/librustc_mir/hair/cx/block.rs
+++ b/src/librustc_mir/hair/cx/block.rs
@@ -18,7 +18,7 @@ use syntax::ast;
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
     type Output = Block<'tcx>;
 
-    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
+    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx, 'tcx>) -> Block<'tcx> {
         // We have to eagerly translate the "spine" of the statements
         // in order to get the lexical scoping correctly.
         let stmts = mirror_stmts(cx, self.id, &*self.stmts);
@@ -31,10 +31,10 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Block {
     }
 }
 
-fn mirror_stmts<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
-                            block_id: ast::NodeId,
-                            stmts: &'tcx [hir::Stmt])
-                            -> Vec<StmtRef<'tcx>>
+fn mirror_stmts<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                          block_id: ast::NodeId,
+                          stmts: &'tcx [hir::Stmt])
+                          -> Vec<StmtRef<'tcx>>
 {
     let mut result = vec![];
     for (index, stmt) in stmts.iter().enumerate() {
@@ -74,7 +74,9 @@ fn mirror_stmts<'a,'tcx:'a>(cx: &mut Cx<'a,'tcx>,
     return result;
 }
 
-pub fn to_expr_ref<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, block: &'tcx hir::Block) -> ExprRef<'tcx> {
+pub fn to_expr_ref<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                             block: &'tcx hir::Block)
+                             -> ExprRef<'tcx> {
     let block_ty = cx.tcx.node_id_to_type(block.id);
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(block.id);
     let expr = Expr {
diff --git a/src/librustc_mir/hair/cx/expr.rs b/src/librustc_mir/hair/cx/expr.rs
index 049426db2f4..bc1197b449b 100644
--- a/src/librustc_mir/hair/cx/expr.rs
+++ b/src/librustc_mir/hair/cx/expr.rs
@@ -29,7 +29,7 @@ use syntax::ptr::P;
 impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
     type Output = Expr<'tcx>;
 
-    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
+    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx, 'tcx>) -> Expr<'tcx> {
         let temp_lifetime = cx.tcx.region_maps.temporary_scope(self.id);
         let expr_extent = cx.tcx.region_maps.node_extent(self.id);
 
@@ -202,7 +202,9 @@ impl<'tcx> Mirror<'tcx> for &'tcx hir::Expr {
     }
 }
 
-fn make_mirror_unadjusted<'a, 'tcx>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> Expr<'tcx> {
+fn make_mirror_unadjusted<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                                    expr: &'tcx hir::Expr)
+                                    -> Expr<'tcx> {
     let expr_ty = cx.tcx.expr_ty(expr);
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
 
@@ -620,10 +622,10 @@ fn make_mirror_unadjusted<'a, 'tcx>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr
     }
 }
 
-fn method_callee<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
-                               expr: &hir::Expr,
-                               method_call: ty::MethodCall)
-                               -> Expr<'tcx> {
+fn method_callee<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                           expr: &hir::Expr,
+                           method_call: ty::MethodCall)
+                           -> Expr<'tcx> {
     let tables = cx.tcx.tables.borrow();
     let callee = &tables.method_map[&method_call];
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
@@ -647,7 +649,8 @@ fn to_borrow_kind(m: hir::Mutability) -> BorrowKind {
     }
 }
 
-fn convert_arm<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<'tcx> {
+fn convert_arm<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                         arm: &'tcx hir::Arm) -> Arm<'tcx> {
     let mut map;
     let opt_map = if arm.pats.len() == 1 {
         None
@@ -666,7 +669,9 @@ fn convert_arm<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, arm: &'tcx hir::Arm) -> Arm<
     }
 }
 
-fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> ExprKind<'tcx> {
+fn convert_path_expr<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                               expr: &'tcx hir::Expr)
+                               -> ExprKind<'tcx> {
     let substs = cx.tcx.mk_substs(cx.tcx.node_id_item_substs(expr.id).substs);
     // Otherwise there may be def_map borrow conflicts
     let def = cx.tcx.def_map.borrow()[&expr.id].full_def();
@@ -738,10 +743,10 @@ fn convert_path_expr<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr)
     }
 }
 
-fn convert_var<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
-                             expr: &'tcx hir::Expr,
-                             def: Def)
-                             -> ExprKind<'tcx> {
+fn convert_var<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                         expr: &'tcx hir::Expr,
+                         def: Def)
+                         -> ExprKind<'tcx> {
     let temp_lifetime = cx.tcx.region_maps.temporary_scope(expr.id);
 
     match def {
@@ -903,13 +908,13 @@ enum PassArgs {
     ByRef,
 }
 
-fn overloaded_operator<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
-                                     expr: &'tcx hir::Expr,
-                                     method_call: ty::MethodCall,
-                                     pass_args: PassArgs,
-                                     receiver: ExprRef<'tcx>,
-                                     args: Vec<&'tcx P<hir::Expr>>)
-                                     -> ExprKind<'tcx> {
+fn overloaded_operator<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                                 expr: &'tcx hir::Expr,
+                                 method_call: ty::MethodCall,
+                                 pass_args: PassArgs,
+                                 receiver: ExprRef<'tcx>,
+                                 args: Vec<&'tcx P<hir::Expr>>)
+                                 -> ExprKind<'tcx> {
     // the receiver has all the adjustments that are needed, so we can
     // just push a reference to it
     let mut argrefs = vec![receiver];
@@ -954,13 +959,13 @@ fn overloaded_operator<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
     }
 }
 
-fn overloaded_lvalue<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
-                                   expr: &'tcx hir::Expr,
-                                   method_call: ty::MethodCall,
-                                   pass_args: PassArgs,
-                                   receiver: ExprRef<'tcx>,
-                                   args: Vec<&'tcx P<hir::Expr>>)
-                                   -> ExprKind<'tcx> {
+fn overloaded_lvalue<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                               expr: &'tcx hir::Expr,
+                               method_call: ty::MethodCall,
+                               pass_args: PassArgs,
+                               receiver: ExprRef<'tcx>,
+                               args: Vec<&'tcx P<hir::Expr>>)
+                               -> ExprKind<'tcx> {
     // For an overloaded *x or x[y] expression of type T, the method
     // call returns an &T and we must add the deref so that the types
     // line up (this is because `*x` and `x[y]` represent lvalues):
@@ -989,11 +994,11 @@ fn overloaded_lvalue<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
     ExprKind::Deref { arg: ref_expr.to_ref() }
 }
 
-fn capture_freevar<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
-                                 closure_expr: &'tcx hir::Expr,
-                                 freevar: &hir::Freevar,
-                                 freevar_ty: Ty<'tcx>)
-                                 -> ExprRef<'tcx> {
+fn capture_freevar<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                             closure_expr: &'tcx hir::Expr,
+                             freevar: &hir::Freevar,
+                             freevar_ty: Ty<'tcx>)
+                             -> ExprRef<'tcx> {
     let id_var = freevar.def.var_id();
     let upvar_id = ty::UpvarId {
         var_id: id_var,
@@ -1030,7 +1035,8 @@ fn capture_freevar<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>,
     }
 }
 
-fn loop_label<'a, 'tcx: 'a>(cx: &mut Cx<'a, 'tcx>, expr: &'tcx hir::Expr) -> CodeExtent {
+fn loop_label<'a, 'tcx>(cx: &mut Cx<'a, 'tcx, 'tcx>,
+                        expr: &'tcx hir::Expr) -> CodeExtent {
     match cx.tcx.def_map.borrow().get(&expr.id).map(|d| d.full_def()) {
         Some(Def::Label(loop_id)) => cx.tcx.region_maps.node_extent(loop_id),
         d => {
diff --git a/src/librustc_mir/hair/cx/mod.rs b/src/librustc_mir/hair/cx/mod.rs
index eda0d4da4f4..8f79b6e68ee 100644
--- a/src/librustc_mir/hair/cx/mod.rs
+++ b/src/librustc_mir/hair/cx/mod.rs
@@ -29,16 +29,16 @@ use rustc::hir;
 use rustc_const_math::{ConstInt, ConstUsize};
 
 #[derive(Copy, Clone)]
-pub struct Cx<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
-    infcx: &'a InferCtxt<'a, 'tcx>,
+pub struct Cx<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     constness: hir::Constness
 }
 
-impl<'a,'tcx> Cx<'a,'tcx> {
-    pub fn new(infcx: &'a InferCtxt<'a, 'tcx>,
+impl<'a, 'tcx> Cx<'a, 'tcx, 'tcx> {
+    pub fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>,
                constness: hir::Constness)
-               -> Cx<'a, 'tcx> {
+               -> Cx<'a, 'tcx, 'tcx> {
         Cx {
             tcx: infcx.tcx,
             infcx: infcx,
@@ -47,7 +47,7 @@ impl<'a,'tcx> Cx<'a,'tcx> {
     }
 }
 
-impl<'a,'tcx:'a> Cx<'a, 'tcx> {
+impl<'a, 'tcx: 'a> Cx<'a, 'tcx, 'tcx> {
     /// Normalizes `ast` into the appropriate `mirror` type.
     pub fn mirror<M: Mirror<'tcx>>(&mut self, ast: M) -> M::Output {
         ast.make_mirror(self)
@@ -144,7 +144,7 @@ impl<'a,'tcx:'a> Cx<'a, 'tcx> {
         self.tcx.type_needs_drop_given_env(ty, &self.infcx.parameter_environment)
     }
 
-    pub fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.tcx
     }
 }
diff --git a/src/librustc_mir/hair/cx/pattern.rs b/src/librustc_mir/hair/cx/pattern.rs
index 990ba9e786c..3fbfead0c08 100644
--- a/src/librustc_mir/hair/cx/pattern.rs
+++ b/src/librustc_mir/hair/cx/pattern.rs
@@ -35,11 +35,11 @@ use syntax::ptr::P;
 /// }
 /// ```
 struct PatCx<'patcx, 'cx: 'patcx, 'tcx: 'cx> {
-    cx: &'patcx mut Cx<'cx, 'tcx>,
+    cx: &'patcx mut Cx<'cx, 'tcx, 'tcx>,
     binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>,
 }
 
-impl<'cx, 'tcx> Cx<'cx, 'tcx> {
+impl<'cx, 'tcx> Cx<'cx, 'tcx, 'tcx> {
     pub fn irrefutable_pat(&mut self, pat: &hir::Pat) -> Pattern<'tcx> {
         PatCx::new(self, None).to_pattern(pat)
     }
@@ -53,7 +53,7 @@ impl<'cx, 'tcx> Cx<'cx, 'tcx> {
 }
 
 impl<'patcx, 'cx, 'tcx> PatCx<'patcx, 'cx, 'tcx> {
-    fn new(cx: &'patcx mut Cx<'cx, 'tcx>,
+    fn new(cx: &'patcx mut Cx<'cx, 'tcx, 'tcx>,
                binding_map: Option<&'patcx FnvHashMap<ast::Name, ast::NodeId>>)
                -> PatCx<'patcx, 'cx, 'tcx> {
         PatCx {
diff --git a/src/librustc_mir/hair/mod.rs b/src/librustc_mir/hair/mod.rs
index 51f2cc2687a..d29e931f593 100644
--- a/src/librustc_mir/hair/mod.rs
+++ b/src/librustc_mir/hair/mod.rs
@@ -358,13 +358,13 @@ pub struct FieldPattern<'tcx> {
 pub trait Mirror<'tcx> {
     type Output;
 
-    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx>) -> Self::Output;
+    fn make_mirror<'a>(self, cx: &mut Cx<'a, 'tcx, 'tcx>) -> Self::Output;
 }
 
 impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
     type Output = Expr<'tcx>;
 
-    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
+    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx, 'tcx>) -> Expr<'tcx> {
         self
     }
 }
@@ -372,7 +372,7 @@ impl<'tcx> Mirror<'tcx> for Expr<'tcx> {
 impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
     type Output = Expr<'tcx>;
 
-    fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx>) -> Expr<'tcx> {
+    fn make_mirror<'a>(self, hir: &mut Cx<'a, 'tcx, 'tcx>) -> Expr<'tcx> {
         match self {
             ExprRef::Hair(h) => h.make_mirror(hir),
             ExprRef::Mirror(m) => *m,
@@ -383,7 +383,7 @@ impl<'tcx> Mirror<'tcx> for ExprRef<'tcx> {
 impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
     type Output = Stmt<'tcx>;
 
-    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Stmt<'tcx> {
+    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx, 'tcx>) -> Stmt<'tcx> {
         self
     }
 }
@@ -391,7 +391,7 @@ impl<'tcx> Mirror<'tcx> for Stmt<'tcx> {
 impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
     type Output = Stmt<'tcx>;
 
-    fn make_mirror<'a>(self, _: &mut Cx<'a,'tcx>) -> Stmt<'tcx> {
+    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx, 'tcx>) -> Stmt<'tcx> {
         match self {
             StmtRef::Mirror(m) => *m,
         }
@@ -401,7 +401,7 @@ impl<'tcx> Mirror<'tcx> for StmtRef<'tcx> {
 impl<'tcx> Mirror<'tcx> for Block<'tcx> {
     type Output = Block<'tcx>;
 
-    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx>) -> Block<'tcx> {
+    fn make_mirror<'a>(self, _: &mut Cx<'a, 'tcx, 'tcx>) -> Block<'tcx> {
         self
     }
 }
diff --git a/src/librustc_mir/mir_map.rs b/src/librustc_mir/mir_map.rs
index 0114ee3c029..139bb755ad1 100644
--- a/src/librustc_mir/mir_map.rs
+++ b/src/librustc_mir/mir_map.rs
@@ -34,7 +34,7 @@ use rustc::hir::map::blocks::FnLikeNode;
 use syntax::ast;
 use syntax::codemap::Span;
 
-pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>) -> MirMap<'tcx> {
+pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> MirMap<'tcx> {
     let mut map = MirMap {
         map: NodeMap(),
     };
@@ -52,13 +52,13 @@ pub fn build_mir_for_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>) -> MirMap<'tcx> {
 // BuildMir -- walks a crate, looking for fn items and methods to build MIR from
 
 struct BuildMir<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     map: &'a mut MirMap<'tcx>,
 }
 
 impl<'a, 'tcx> BuildMir<'a, 'tcx> {
     fn build<F>(&mut self, src: MirSource, f: F)
-        where F: for<'b> FnOnce(Cx<'b, 'tcx>) -> (Mir<'tcx>, build::ScopeAuxiliaryVec)
+        where F: for<'b> FnOnce(Cx<'b, 'tcx, 'tcx>) -> (Mir<'tcx>, build::ScopeAuxiliaryVec)
     {
         let constness = match src {
             MirSource::Const(_) |
@@ -202,7 +202,7 @@ impl<'a, 'tcx> Visitor<'tcx> for BuildMir<'a, 'tcx> {
     }
 }
 
-fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn closure_self_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              closure_expr_id: ast::NodeId,
                              body_id: ast::NodeId)
                              -> Ty<'tcx> {
diff --git a/src/librustc_mir/pretty.rs b/src/librustc_mir/pretty.rs
index 8fb36c2e10c..bf6689de236 100644
--- a/src/librustc_mir/pretty.rs
+++ b/src/librustc_mir/pretty.rs
@@ -36,7 +36,7 @@ const INDENT: &'static str = "    ";
 /// - `substring1&substring2,...` -- `&`-separated list of substrings
 ///   that can appear in the pass-name or the `item_path_str` for the given
 ///   node-id. If any one of the substrings match, the data is dumped out.
-pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           pass_name: &str,
                           disambiguator: &Display,
                           src: MirSource,
@@ -73,7 +73,7 @@ pub fn dump_mir<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
 }
 
 /// Write out a human-readable textual representation for the given MIR.
-pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx>,
+pub fn write_mir_pretty<'a, 'b, 'tcx, I>(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                                          iter: I,
                                          w: &mut Write)
                                          -> io::Result<()>
@@ -95,7 +95,7 @@ enum Annotation {
     ExitScope(ScopeId),
 }
 
-pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn write_mir_fn<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               src: MirSource,
                               mir: &Mir<'tcx>,
                               w: &mut Write,
@@ -219,8 +219,11 @@ fn write_scope_tree(tcx: TyCtxt,
 
 /// Write out a human-readable textual representation of the MIR's `fn` type and the types of its
 /// local variables (both user-defined bindings and compiler temporaries).
-fn write_mir_intro(tcx: TyCtxt, src: MirSource, mir: &Mir, w: &mut Write)
-                   -> io::Result<()> {
+fn write_mir_intro<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             src: MirSource,
+                             mir: &Mir,
+                             w: &mut Write)
+                             -> io::Result<()> {
     match src {
         MirSource::Fn(_) => write!(w, "fn")?,
         MirSource::Const(_) => write!(w, "const")?,
diff --git a/src/librustc_mir/transform/break_critical_edges.rs b/src/librustc_mir/transform/break_critical_edges.rs
index 1d8b9f39662..a6af30b7eec 100644
--- a/src/librustc_mir/transform/break_critical_edges.rs
+++ b/src/librustc_mir/transform/break_critical_edges.rs
@@ -42,7 +42,8 @@ pub struct BreakCriticalEdges;
  */
 
 impl<'tcx> MirPass<'tcx> for BreakCriticalEdges {
-    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) {
+    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>,
+                    _: MirSource, mir: &mut Mir<'tcx>) {
         break_critical_edges(mir);
     }
 }
diff --git a/src/librustc_mir/transform/erase_regions.rs b/src/librustc_mir/transform/erase_regions.rs
index 17a849c4cce..1ee1ee737aa 100644
--- a/src/librustc_mir/transform/erase_regions.rs
+++ b/src/librustc_mir/transform/erase_regions.rs
@@ -19,11 +19,11 @@ use rustc::mir::visit::MutVisitor;
 use rustc::mir::transform::{MirPass, MirSource, Pass};
 
 struct EraseRegionsVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'a, 'tcx> EraseRegionsVisitor<'a, 'tcx> {
-    pub fn new(tcx: TyCtxt<'a, 'tcx>) -> Self {
+    pub fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Self {
         EraseRegionsVisitor {
             tcx: tcx
         }
@@ -46,7 +46,8 @@ pub struct EraseRegions;
 impl Pass for EraseRegions {}
 
 impl<'tcx> MirPass<'tcx> for EraseRegions {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) {
+    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    _: MirSource, mir: &mut Mir<'tcx>) {
         EraseRegionsVisitor::new(tcx).visit_mir(mir);
     }
 }
diff --git a/src/librustc_mir/transform/no_landing_pads.rs b/src/librustc_mir/transform/no_landing_pads.rs
index 1f6318ab724..de05032fa55 100644
--- a/src/librustc_mir/transform/no_landing_pads.rs
+++ b/src/librustc_mir/transform/no_landing_pads.rs
@@ -41,7 +41,8 @@ impl<'tcx> MutVisitor<'tcx> for NoLandingPads {
 }
 
 impl<'tcx> MirPass<'tcx> for NoLandingPads {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) {
+    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    _: MirSource, mir: &mut Mir<'tcx>) {
         if tcx.sess.no_landing_pads() {
             self.visit_mir(mir);
         }
diff --git a/src/librustc_mir/transform/promote_consts.rs b/src/librustc_mir/transform/promote_consts.rs
index 0f08c4af71f..431568b004d 100644
--- a/src/librustc_mir/transform/promote_consts.rs
+++ b/src/librustc_mir/transform/promote_consts.rs
@@ -331,7 +331,7 @@ impl<'a, 'tcx> MutVisitor<'tcx> for Promoter<'a, 'tcx> {
 }
 
 pub fn promote_candidates<'a, 'tcx>(mir: &mut Mir<'tcx>,
-                                    tcx: TyCtxt<'a, 'tcx>,
+                                    tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     mut temps: Vec<TempState>,
                                     candidates: Vec<Candidate>) {
     // Visit candidates in reverse, in case they're nested.
diff --git a/src/librustc_mir/transform/qualify_consts.rs b/src/librustc_mir/transform/qualify_consts.rs
index 1af9cf8376e..2f44786aa0e 100644
--- a/src/librustc_mir/transform/qualify_consts.rs
+++ b/src/librustc_mir/transform/qualify_consts.rs
@@ -126,13 +126,13 @@ fn is_const_fn(tcx: TyCtxt, def_id: DefId) -> bool {
     }
 }
 
-struct Qualifier<'a, 'tcx: 'a> {
+struct Qualifier<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     mode: Mode,
     span: Span,
     def_id: DefId,
     mir: &'a Mir<'tcx>,
     rpo: ReversePostorder<'a, 'tcx>,
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'gcx, 'tcx>,
     param_env: ty::ParameterEnvironment<'a, 'tcx>,
     qualif_map: &'a mut DefIdMap<Qualif>,
     mir_map: Option<&'a MirMap<'tcx>>,
@@ -145,14 +145,14 @@ struct Qualifier<'a, 'tcx: 'a> {
     promotion_candidates: Vec<Candidate>
 }
 
-impl<'a, 'tcx> Qualifier<'a, 'tcx> {
+impl<'a, 'tcx> Qualifier<'a, 'tcx, 'tcx> {
     fn new(param_env: ty::ParameterEnvironment<'a, 'tcx>,
            qualif_map: &'a mut DefIdMap<Qualif>,
            mir_map: Option<&'a MirMap<'tcx>>,
            def_id: DefId,
            mir: &'a Mir<'tcx>,
            mode: Mode)
-           -> Qualifier<'a, 'tcx> {
+           -> Qualifier<'a, 'tcx, 'tcx> {
         let mut rpo = traversal::reverse_postorder(mir);
         let temps = promote_consts::collect_temps(mir, &mut rpo);
         rpo.reset();
@@ -492,7 +492,7 @@ impl<'a, 'tcx> Qualifier<'a, 'tcx> {
 /// Accumulates an Rvalue or Call's effects in self.qualif.
 /// For functions (constant or not), it also records
 /// candidates for promotion in promotion_candidates.
-impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx, 'tcx> {
     fn visit_lvalue(&mut self, lvalue: &Lvalue<'tcx>, context: LvalueContext) {
         match *lvalue {
             Lvalue::Arg(_) => {
@@ -908,7 +908,7 @@ impl<'a, 'tcx> Visitor<'tcx> for Qualifier<'a, 'tcx> {
     }
 }
 
-fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn qualify_const_item_cached<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        qualif_map: &mut DefIdMap<Qualif>,
                                        mir_map: Option<&MirMap<'tcx>>,
                                        def_id: DefId)
@@ -951,7 +951,7 @@ pub struct QualifyAndPromoteConstants;
 impl Pass for QualifyAndPromoteConstants {}
 
 impl<'tcx> MirMapPass<'tcx> for QualifyAndPromoteConstants {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>, map: &mut MirMap<'tcx>) {
+    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>, map: &mut MirMap<'tcx>) {
         let mut qualif_map = DefIdMap();
 
         // First, visit `const` items, potentially recursing, to get
diff --git a/src/librustc_mir/transform/remove_dead_blocks.rs b/src/librustc_mir/transform/remove_dead_blocks.rs
index 1cd8a569fe3..44f3ce7361c 100644
--- a/src/librustc_mir/transform/remove_dead_blocks.rs
+++ b/src/librustc_mir/transform/remove_dead_blocks.rs
@@ -40,7 +40,8 @@ use rustc::mir::transform::{Pass, MirPass, MirSource};
 pub struct RemoveDeadBlocks;
 
 impl<'tcx> MirPass<'tcx> for RemoveDeadBlocks {
-    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) {
+    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>,
+                    _: MirSource, mir: &mut Mir<'tcx>) {
         let mut seen = BitVector::new(mir.basic_blocks.len());
         // This block is always required.
         seen.insert(START_BLOCK.index());
diff --git a/src/librustc_mir/transform/simplify_cfg.rs b/src/librustc_mir/transform/simplify_cfg.rs
index 93534a694e4..fa897384a54 100644
--- a/src/librustc_mir/transform/simplify_cfg.rs
+++ b/src/librustc_mir/transform/simplify_cfg.rs
@@ -111,7 +111,8 @@ impl SimplifyCfg {
 }
 
 impl<'tcx> MirPass<'tcx> for SimplifyCfg {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
+    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    src: MirSource, mir: &mut Mir<'tcx>) {
         let mut counter = 0;
         let mut changed = true;
         while changed {
diff --git a/src/librustc_mir/transform/type_check.rs b/src/librustc_mir/transform/type_check.rs
index 8ccc621d224..aed20dd7654 100644
--- a/src/librustc_mir/transform/type_check.rs
+++ b/src/librustc_mir/transform/type_check.rs
@@ -54,14 +54,14 @@ enum FieldAccessError {
 /// The sanitize_XYZ methods here take an MIR object and compute its
 /// type, calling `span_mirbug` and returning an error type if there
 /// is a problem.
-struct TypeVerifier<'a, 'b: 'a, 'tcx: 'b> {
-    cx: &'a mut TypeChecker<'b, 'tcx>,
+struct TypeVerifier<'a, 'b: 'a, 'gcx: 'b+'tcx, 'tcx: 'b> {
+    cx: &'a mut TypeChecker<'b, 'gcx, 'tcx>,
     mir: &'a Mir<'tcx>,
     last_span: Span,
     errors_reported: bool
 }
 
-impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
+impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx, 'tcx> {
     fn visit_span(&mut self, span: &Span) {
         if *span != DUMMY_SP {
             self.last_span = *span;
@@ -104,8 +104,8 @@ impl<'a, 'b, 'tcx> Visitor<'tcx> for TypeVerifier<'a, 'b, 'tcx> {
     }
 }
 
-impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
-    fn new(cx: &'a mut TypeChecker<'b, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
+impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx, 'tcx> {
+    fn new(cx: &'a mut TypeChecker<'b, 'tcx, 'tcx>, mir: &'a Mir<'tcx>) -> Self {
         TypeVerifier {
             cx: cx,
             mir: mir,
@@ -114,11 +114,11 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
         }
     }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.cx.infcx.tcx
     }
 
-    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
+    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx, 'tcx> {
         self.cx.infcx
     }
 
@@ -318,14 +318,14 @@ impl<'a, 'b, 'tcx> TypeVerifier<'a, 'b, 'tcx> {
     }
 }
 
-pub struct TypeChecker<'a, 'tcx: 'a> {
-    infcx: &'a InferCtxt<'a, 'tcx>,
+pub struct TypeChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    infcx: &'a InferCtxt<'a, 'gcx, 'tcx>,
     fulfillment_cx: traits::FulfillmentContext<'tcx>,
     last_span: Span
 }
 
-impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
-    fn new(infcx: &'a InferCtxt<'a, 'tcx>) -> Self {
+impl<'a, 'tcx> TypeChecker<'a, 'tcx, 'tcx> {
+    fn new(infcx: &'a InferCtxt<'a, 'tcx, 'tcx>) -> Self {
         TypeChecker {
             infcx: infcx,
             fulfillment_cx: traits::FulfillmentContext::new(),
@@ -349,7 +349,7 @@ impl<'a, 'tcx> TypeChecker<'a, 'tcx> {
             .map(|InferOk { obligations, .. }| assert!(obligations.is_empty()))
     }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.infcx.tcx
     }
 
@@ -576,7 +576,8 @@ impl TypeckMir {
 }
 
 impl<'tcx> MirPass<'tcx> for TypeckMir {
-    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx>, src: MirSource, mir: &mut Mir<'tcx>) {
+    fn run_pass<'a>(&mut self, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                    src: MirSource, mir: &mut Mir<'tcx>) {
         if tcx.sess.err_count() > 0 {
             // compiling a broken program can obviously result in a
             // broken MIR, so try not to report duplicate errors.
diff --git a/src/librustc_passes/consts.rs b/src/librustc_passes/consts.rs
index dfc59a6db50..98aff8e27f1 100644
--- a/src/librustc_passes/consts.rs
+++ b/src/librustc_passes/consts.rs
@@ -68,7 +68,7 @@ enum Mode {
 }
 
 struct CheckCrateVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     mode: Mode,
     qualif: ConstQualif,
     rvalue_borrows: NodeMap<hir::Mutability>
@@ -88,7 +88,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
     }
 
     fn with_euv<'b, F, R>(&'b mut self, item_id: Option<ast::NodeId>, f: F) -> R where
-        F: for<'t> FnOnce(&mut euv::ExprUseVisitor<'b, 't, 'b, 'tcx>) -> R,
+        F: for<'c> FnOnce(&mut euv::ExprUseVisitor<'b, 'c, 'tcx, 'tcx>) -> R,
     {
         let param_env = match item_id {
             Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
@@ -663,7 +663,7 @@ fn check_adjustments<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>, e: &hir::Exp
     }
 }
 
-pub fn check_crate(tcx: TyCtxt) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     tcx.visit_all_items_in_krate(DepNode::CheckConst, &mut CheckCrateVisitor {
         tcx: tcx,
         mode: Mode::Var,
diff --git a/src/librustc_passes/rvalues.rs b/src/librustc_passes/rvalues.rs
index 11ce3a17e9e..b8d63368726 100644
--- a/src/librustc_passes/rvalues.rs
+++ b/src/librustc_passes/rvalues.rs
@@ -23,13 +23,13 @@ use rustc::hir::intravisit;
 use syntax::ast;
 use syntax::codemap::Span;
 
-pub fn check_crate(tcx: TyCtxt) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut rvcx = RvalueContext { tcx: tcx };
     tcx.visit_all_items_in_krate(DepNode::RvalueCheck, &mut rvcx);
 }
 
 struct RvalueContext<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
@@ -54,7 +54,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for RvalueContext<'a, 'tcx> {
 }
 
 struct RvalueContextDelegate<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     param_env: &'a ty::ParameterEnvironment<'a,'tcx>,
 }
 
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index d224c88d0ff..0b2763baf4f 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -58,7 +58,7 @@ type CheckResult = Option<(Span, String, Option<(Span, String)>)>;
 ////////////////////////////////////////////////////////////////////////////////
 
 struct EmbargoVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     export_map: &'a def::ExportMap,
 
     // Accessibility levels for reachable nodes
@@ -376,7 +376,7 @@ impl<'b, 'a, 'tcx: 'a, 'v> Visitor<'v> for ReachEverythingInTheInterfaceVisitor<
 ////////////////////////////////////////////////////////////////////////////////
 
 struct PrivacyVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     curitem: ast::NodeId,
     in_foreign: bool,
 }
@@ -526,7 +526,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
 ////////////////////////////////////////////////////////////////////////////////
 
 struct SanePrivacyVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'a, 'tcx, 'v> Visitor<'v> for SanePrivacyVisitor<'a, 'tcx> {
@@ -597,7 +597,7 @@ impl<'a, 'tcx> SanePrivacyVisitor<'a, 'tcx> {
 ///////////////////////////////////////////////////////////////////////////////
 
 struct ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     access_levels: &'a AccessLevels,
     in_variant: bool,
     // set of errors produced by this obsolete visitor
@@ -937,7 +937,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ObsoleteVisiblePrivateTypesVisitor<'a, 'tcx>
 ///////////////////////////////////////////////////////////////////////////////
 
 struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     /// The visitor checks that each component type is at least this visible
     required_visibility: ty::Visibility,
     /// The visibility of the least visible component that has been visited
@@ -946,7 +946,7 @@ struct SearchInterfaceForPrivateItemsVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx: 'a> SearchInterfaceForPrivateItemsVisitor<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx>, old_error_set: &'a NodeSet) -> Self {
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>, old_error_set: &'a NodeSet) -> Self {
         SearchInterfaceForPrivateItemsVisitor {
             tcx: tcx,
             min_visibility: ty::Visibility::Public,
@@ -1082,7 +1082,7 @@ impl<'a, 'tcx: 'a, 'v> Visitor<'v> for SearchInterfaceForPrivateItemsVisitor<'a,
 }
 
 struct PrivateItemsInPublicInterfacesVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     old_error_set: &'a NodeSet,
 }
 
@@ -1173,7 +1173,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivateItemsInPublicInterfacesVisitor<'a, 'tc
     }
 }
 
-pub fn check_crate(tcx: TyCtxt, export_map: &def::ExportMap) -> AccessLevels {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             export_map: &def::ExportMap)
+                             -> AccessLevels {
     let _task = tcx.dep_graph.in_task(DepNode::Privacy);
 
     let krate = tcx.map.krate();
diff --git a/src/librustc_save_analysis/dump_visitor.rs b/src/librustc_save_analysis/dump_visitor.rs
index cb4a9b20dea..f0dd7b8b9bb 100644
--- a/src/librustc_save_analysis/dump_visitor.rs
+++ b/src/librustc_save_analysis/dump_visitor.rs
@@ -62,7 +62,7 @@ macro_rules! down_cast_data {
 pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> {
     save_ctxt: SaveContext<'l, 'tcx>,
     sess: &'l Session,
-    tcx: TyCtxt<'l, 'tcx>,
+    tcx: TyCtxt<'l, 'tcx, 'tcx>,
     analysis: &'l ty::CrateAnalysis<'l>,
     dumper: &'ll mut D,
 
@@ -79,7 +79,7 @@ pub struct DumpVisitor<'l, 'tcx: 'l, 'll, D: 'll> {
 }
 
 impl<'l, 'tcx: 'l, 'll, D: Dump + 'll> DumpVisitor<'l, 'tcx, 'll, D> {
-    pub fn new(tcx: TyCtxt<'l, 'tcx>,
+    pub fn new(tcx: TyCtxt<'l, 'tcx, 'tcx>,
                save_ctxt: SaveContext<'l, 'tcx>,
                analysis: &'l ty::CrateAnalysis<'l>,
                dumper: &'ll mut D)
diff --git a/src/librustc_save_analysis/lib.rs b/src/librustc_save_analysis/lib.rs
index f64aa4347a8..d62c14d2c57 100644
--- a/src/librustc_save_analysis/lib.rs
+++ b/src/librustc_save_analysis/lib.rs
@@ -75,7 +75,7 @@ pub mod recorder {
 }
 
 pub struct SaveContext<'l, 'tcx: 'l> {
-    tcx: TyCtxt<'l, 'tcx>,
+    tcx: TyCtxt<'l, 'tcx, 'tcx>,
     span_utils: SpanUtils<'tcx>,
 }
 
@@ -84,12 +84,12 @@ macro_rules! option_try(
 );
 
 impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
-    pub fn new(tcx: TyCtxt<'l, 'tcx>) -> SaveContext<'l, 'tcx> {
+    pub fn new(tcx: TyCtxt<'l, 'tcx, 'tcx>) -> SaveContext<'l, 'tcx> {
         let span_utils = SpanUtils::new(&tcx.sess);
         SaveContext::from_span_utils(tcx, span_utils)
     }
 
-    pub fn from_span_utils(tcx: TyCtxt<'l, 'tcx>,
+    pub fn from_span_utils(tcx: TyCtxt<'l, 'tcx, 'tcx>,
                            span_utils: SpanUtils<'tcx>)
                            -> SaveContext<'l, 'tcx> {
         SaveContext {
@@ -699,7 +699,7 @@ impl Format {
     }
 }
 
-pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx>,
+pub fn process_crate<'l, 'tcx>(tcx: TyCtxt<'l, 'tcx, 'tcx>,
                                krate: &ast::Crate,
                                analysis: &'l ty::CrateAnalysis<'l>,
                                cratename: &str,
diff --git a/src/librustc_trans/_match.rs b/src/librustc_trans/_match.rs
index 83a7b52dfbd..08d1c33b1a5 100644
--- a/src/librustc_trans/_match.rs
+++ b/src/librustc_trans/_match.rs
@@ -239,7 +239,7 @@ use syntax::ptr::P;
 struct ConstantExpr<'a>(&'a hir::Expr);
 
 impl<'a> ConstantExpr<'a> {
-    fn eq(self, other: ConstantExpr<'a>, tcx: TyCtxt) -> bool {
+    fn eq<'b, 'tcx>(self, other: ConstantExpr<'a>, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> bool {
         match compare_lit_exprs(tcx, self.0, other.0) {
             Some(result) => result == Ordering::Equal,
             None => bug!("compare_list_exprs: type mismatch"),
@@ -260,7 +260,7 @@ enum Opt<'a, 'tcx> {
 }
 
 impl<'a, 'b, 'tcx> Opt<'a, 'tcx> {
-    fn eq(&self, other: &Opt<'a, 'tcx>, tcx: TyCtxt<'b, 'tcx>) -> bool {
+    fn eq(&self, other: &Opt<'a, 'tcx>, tcx: TyCtxt<'b, 'tcx, 'tcx>) -> bool {
         match (self, other) {
             (&ConstantValue(a, _), &ConstantValue(b, _)) => a.eq(b, tcx),
             (&ConstantRange(a1, a2, _), &ConstantRange(b1, b2, _)) => {
diff --git a/src/librustc_trans/adt.rs b/src/librustc_trans/adt.rs
index ceb5f6ae9e3..49775388038 100644
--- a/src/librustc_trans/adt.rs
+++ b/src/librustc_trans/adt.rs
@@ -237,7 +237,7 @@ fn dtor_to_init_u8(dtor: bool) -> u8 {
 }
 
 pub trait GetDtorType<'tcx> { fn dtor_type(self) -> Ty<'tcx>; }
-impl<'a, 'tcx> GetDtorType<'tcx> for TyCtxt<'a, 'tcx> {
+impl<'a, 'tcx> GetDtorType<'tcx> for TyCtxt<'a, 'tcx, 'tcx> {
     fn dtor_type(self) -> Ty<'tcx> { self.types.u8 }
 }
 
@@ -442,7 +442,7 @@ struct Case<'tcx> {
 /// This represents the (GEP) indices to follow to get to the discriminant field
 pub type DiscrField = Vec<usize>;
 
-fn find_discr_field_candidate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn find_discr_field_candidate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         ty: Ty<'tcx>,
                                         mut path: DiscrField)
                                         -> Option<DiscrField> {
@@ -545,7 +545,7 @@ impl<'tcx> Case<'tcx> {
     }
 }
 
-fn get_cases<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn get_cases<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                        adt: ty::AdtDef<'tcx>,
                        substs: &subst::Substs<'tcx>)
                        -> Vec<Case<'tcx>> {
@@ -669,7 +669,7 @@ fn bounds_usable(cx: &CrateContext, ity: IntType, bounds: &IntBounds) -> bool {
     }
 }
 
-pub fn ty_of_inttype<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, ity: IntType) -> Ty<'tcx> {
+pub fn ty_of_inttype<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ity: IntType) -> Ty<'tcx> {
     match ity {
         attr::SignedInt(t) => tcx.mk_mach_int(t),
         attr::UnsignedInt(t) => tcx.mk_mach_uint(t)
diff --git a/src/librustc_trans/back/link.rs b/src/librustc_trans/back/link.rs
index ec728da4747..00d9658cb59 100644
--- a/src/librustc_trans/back/link.rs
+++ b/src/librustc_trans/back/link.rs
@@ -124,7 +124,9 @@ pub fn find_crate_name(sess: Option<&Session>,
 
 }
 
-pub fn build_link_meta(tcx: TyCtxt, name: &str) -> LinkMeta {
+pub fn build_link_meta<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 name: &str)
+                                 -> LinkMeta {
     let r = LinkMeta {
         crate_name: name.to_owned(),
         crate_hash: tcx.calculate_krate_hash(),
diff --git a/src/librustc_trans/back/symbol_names.rs b/src/librustc_trans/back/symbol_names.rs
index cc353af81f5..0cf82d66b2b 100644
--- a/src/librustc_trans/back/symbol_names.rs
+++ b/src/librustc_trans/back/symbol_names.rs
@@ -111,12 +111,12 @@ use std::fmt::Write;
 use syntax::parse::token::{self, InternedString};
 use serialize::hex::ToHex;
 
-pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, def_id: DefId) -> String {
+pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> String {
     let def_path = tcx.def_path(def_id);
     def_path_to_string(tcx, &def_path)
 }
 
-pub fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, def_path: &DefPath) -> String {
+pub fn def_path_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_path: &DefPath) -> String {
     let mut s = String::with_capacity(def_path.data.len() * 16);
 
     s.push_str(&tcx.crate_name(def_path.krate));
diff --git a/src/librustc_trans/base.rs b/src/librustc_trans/base.rs
index 221d32528de..7665b730cad 100644
--- a/src/librustc_trans/base.rs
+++ b/src/librustc_trans/base.rs
@@ -1308,7 +1308,9 @@ impl<'v> Visitor<'v> for FindNestedReturn {
     }
 }
 
-fn build_cfg(tcx: TyCtxt, id: ast::NodeId) -> (ast::NodeId, Option<cfg::CFG>) {
+fn build_cfg<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                       id: ast::NodeId)
+                       -> (ast::NodeId, Option<cfg::CFG>) {
     let blk = match tcx.map.find(id) {
         Some(hir_map::NodeItem(i)) => {
             match i.node {
@@ -2688,7 +2690,7 @@ pub fn filter_reachable_ids(scx: &SharedCrateContext) -> NodeSet {
     }).collect()
 }
 
-pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn trans_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                              mir_map: &MirMap<'tcx>,
                              analysis: ty::CrateAnalysis)
                              -> CrateTranslation {
diff --git a/src/librustc_trans/callee.rs b/src/librustc_trans/callee.rs
index fd026067b88..0d012ba6391 100644
--- a/src/librustc_trans/callee.rs
+++ b/src/librustc_trans/callee.rs
@@ -275,7 +275,7 @@ impl<'tcx> Callee<'tcx> {
 }
 
 /// Given a DefId and some Substs, produces the monomorphic item type.
-fn def_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn def_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                     def_id: DefId,
                     substs: &'tcx subst::Substs<'tcx>)
                     -> Ty<'tcx> {
diff --git a/src/librustc_trans/closure.rs b/src/librustc_trans/closure.rs
index 1bc99a9a6e9..c9a04ede6b1 100644
--- a/src/librustc_trans/closure.rs
+++ b/src/librustc_trans/closure.rs
@@ -119,7 +119,7 @@ impl ClosureEnv {
     }
 }
 
-fn get_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn get_self_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                            closure_id: DefId,
                            fn_ty: Ty<'tcx>)
                            -> Ty<'tcx> {
diff --git a/src/librustc_trans/collector.rs b/src/librustc_trans/collector.rs
index 19b4e65b470..14b7e5803a8 100644
--- a/src/librustc_trans/collector.rs
+++ b/src/librustc_trans/collector.rs
@@ -432,7 +432,7 @@ fn collect_items_rec<'a, 'tcx: 'a>(scx: &SharedCrateContext<'a, 'tcx>,
     debug!("END collect_items_rec({})", starting_point.to_string(scx.tcx()));
 }
 
-fn record_references<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn record_references<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                caller: TransItem<'tcx>,
                                callees: &[TransItem<'tcx>],
                                reference_map: &mut ReferenceMap<'tcx>) {
@@ -445,7 +445,7 @@ fn record_references<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
     reference_map.record_references(caller, iter);
 }
 
-fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn check_recursion_limit<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                    instance: Instance<'tcx>,
                                    recursion_depths: &mut DefIdMap<usize>)
                                    -> (DefId, usize) {
@@ -606,7 +606,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
 
         self.super_operand(operand);
 
-        fn can_result_in_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+        fn can_result_in_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                               def_id: DefId)
                                               -> bool {
             if !match tcx.lookup_item_type(def_id).ty.sty {
@@ -635,7 +635,7 @@ impl<'a, 'tcx> MirVisitor<'tcx> for MirNeighborCollector<'a, 'tcx> {
     }
 }
 
-fn can_have_local_instance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn can_have_local_instance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      def_id: DefId)
                                      -> bool {
     // Take a look if we have the definition available. If not, we
@@ -960,7 +960,7 @@ fn find_vtable_types_for_unsizing<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
     }
 }
 
-fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn create_fn_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                   def_id: DefId,
                                   fn_substs: &Substs<'tcx>,
                                   param_substs: &Substs<'tcx>)
@@ -1146,7 +1146,7 @@ impl<'b, 'a, 'v> hir_visit::Visitor<'v> for RootCollector<'b, 'a, 'v> {
     }
 }
 
-fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                   item: &'tcx hir::Item,
                                                   output: &mut Vec<TransItem<'tcx>>) {
     match item.node {
@@ -1225,7 +1225,7 @@ fn create_trans_items_for_default_impls<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
 
 /// Same as `unique_type_name()` but with the result pushed onto the given
 /// `output` parameter.
-pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        t: ty::Ty<'tcx>,
                                        output: &mut String) {
     match t.sty {
@@ -1363,9 +1363,9 @@ pub fn push_unique_type_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
     }
 }
 
-fn push_item_name(tcx: TyCtxt,
-                  def_id: DefId,
-                  output: &mut String) {
+fn push_item_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            def_id: DefId,
+                            output: &mut String) {
     let def_path = tcx.def_path(def_id);
 
     // some_crate::
@@ -1384,7 +1384,7 @@ fn push_item_name(tcx: TyCtxt,
     output.pop();
 }
 
-fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               types: &'tcx subst::VecPerParamSpace<Ty<'tcx>>,
                               projections: &[ty::PolyProjectionPredicate<'tcx>],
                               output: &mut String) {
@@ -1414,20 +1414,21 @@ fn push_type_params<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
     output.push('>');
 }
 
-fn push_instance_as_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn push_instance_as_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                      instance: Instance<'tcx>,
                                      output: &mut String) {
     push_item_name(tcx, instance.def, output);
     push_type_params(tcx, &instance.substs.types, &[], output);
 }
 
-pub fn def_id_to_string(tcx: TyCtxt, def_id: DefId) -> String {
+pub fn def_id_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                  def_id: DefId) -> String {
     let mut output = String::new();
     push_item_name(tcx, def_id, &mut output);
     output
 }
 
-fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                             ty: ty::Ty<'tcx>)
                             -> String {
     let mut output = String::new();
@@ -1436,7 +1437,7 @@ fn type_to_string<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
 }
 
 impl<'a, 'tcx> TransItem<'tcx> {
-    pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx>) -> bool {
+    pub fn requests_inline(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> bool {
         match *self {
             TransItem::Fn(ref instance) => {
                 let attributes = tcx.get_attrs(instance.def);
@@ -1463,7 +1464,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
         }
     }
 
-    pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx>) -> Option<llvm::Linkage> {
+    pub fn explicit_linkage(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Option<llvm::Linkage> {
         let def_id = match *self {
             TransItem::Fn(ref instance) => instance.def,
             TransItem::Static(node_id) => tcx.map.local_def_id(node_id),
@@ -1487,7 +1488,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
         }
     }
 
-    pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx>) -> String {
+    pub fn to_string(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> String {
         let hir_map = &tcx.map;
 
         return match *self {
@@ -1510,7 +1511,7 @@ impl<'a, 'tcx> TransItem<'tcx> {
             },
         };
 
-        fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+        fn to_string_internal<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                         prefix: &str,
                                         instance: Instance<'tcx>)
                                         -> String {
diff --git a/src/librustc_trans/common.rs b/src/librustc_trans/common.rs
index 5e69c775634..a4728f40b31 100644
--- a/src/librustc_trans/common.rs
+++ b/src/librustc_trans/common.rs
@@ -58,11 +58,11 @@ use syntax::parse::token;
 pub use context::{CrateContext, SharedCrateContext};
 
 /// Is the type's representation size known at compile time?
-pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
+pub fn type_is_sized<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
     ty.is_sized(&tcx.empty_parameter_environment(), DUMMY_SP)
 }
 
-pub fn type_is_fat_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
+pub fn type_is_fat_ptr<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.sty {
         ty::TyRawPtr(ty::TypeAndMut{ty, ..}) |
         ty::TyRef(_, ty::TypeAndMut{ty, ..}) |
@@ -165,7 +165,7 @@ pub struct VariantInfo<'tcx> {
 }
 
 impl<'a, 'tcx> VariantInfo<'tcx> {
-    pub fn from_ty(tcx: TyCtxt<'a, 'tcx>,
+    pub fn from_ty(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                    ty: Ty<'tcx>,
                    opt_def: Option<Def>)
                    -> Self
@@ -201,7 +201,7 @@ impl<'a, 'tcx> VariantInfo<'tcx> {
     }
 
     /// Return the variant corresponding to a given node (e.g. expr)
-    pub fn of_node(tcx: TyCtxt<'a, 'tcx>, ty: Ty<'tcx>, id: ast::NodeId) -> Self {
+    pub fn of_node(tcx: TyCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>, id: ast::NodeId) -> Self {
         let node_def = tcx.def_map.borrow().get(&id).map(|v| v.full_def());
         Self::from_ty(tcx, ty, node_def)
     }
@@ -568,7 +568,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
     pub fn fcx(&self) -> &'blk FunctionContext<'blk, 'tcx> {
         self.fcx
     }
-    pub fn tcx(&self) -> TyCtxt<'blk, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'blk, 'tcx, 'tcx> {
         self.fcx.ccx.tcx()
     }
     pub fn sess(&self) -> &'blk Session { self.fcx.ccx.sess() }
@@ -694,7 +694,7 @@ impl<'blk, 'tcx> BlockAndBuilder<'blk, 'tcx> {
     pub fn fcx(&self) -> &'blk FunctionContext<'blk, 'tcx> {
         self.bcx.fcx()
     }
-    pub fn tcx(&self) -> TyCtxt<'blk, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'blk, 'tcx, 'tcx> {
         self.bcx.tcx()
     }
     pub fn sess(&self) -> &'blk Session {
@@ -1119,7 +1119,7 @@ pub fn fulfill_obligation<'a, 'tcx>(scx: &SharedCrateContext<'a, 'tcx>,
 /// returns false, then either normalize encountered an error or one
 /// of the predicates did not hold. Used when creating vtables to
 /// check for unsatisfiable methods.
-pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn normalize_and_test_predicates<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                predicates: Vec<ty::Predicate<'tcx>>)
                                                -> bool
 {
diff --git a/src/librustc_trans/context.rs b/src/librustc_trans/context.rs
index 49b71ae5889..61137d7f377 100644
--- a/src/librustc_trans/context.rs
+++ b/src/librustc_trans/context.rs
@@ -73,7 +73,7 @@ pub struct SharedCrateContext<'a, 'tcx: 'a> {
     item_symbols: RefCell<NodeMap<String>>,
     link_meta: LinkMeta,
     symbol_hasher: RefCell<Sha256>,
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     stats: Stats,
     check_overflow: bool,
     check_drop_flag_for_sanity: bool,
@@ -331,7 +331,7 @@ unsafe fn create_context_and_module(sess: &Session, mod_name: &str) -> (ContextR
 }
 
 impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
-    pub fn new(tcx: TyCtxt<'b, 'tcx>,
+    pub fn new(tcx: TyCtxt<'b, 'tcx, 'tcx>,
                mir_map: &'b MirMap<'tcx>,
                export_map: ExportMap,
                symbol_hasher: Sha256,
@@ -450,7 +450,7 @@ impl<'b, 'tcx> SharedCrateContext<'b, 'tcx> {
         &self.link_meta
     }
 
-    pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx> {
+    pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.tcx
     }
 
@@ -640,7 +640,7 @@ impl<'b, 'tcx> CrateContext<'b, 'tcx> {
         }
     }
 
-    pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx> {
+    pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.shared.tcx
     }
 
diff --git a/src/librustc_trans/expr.rs b/src/librustc_trans/expr.rs
index a5416c2fed1..03a3e753d82 100644
--- a/src/librustc_trans/expr.rs
+++ b/src/librustc_trans/expr.rs
@@ -722,7 +722,7 @@ fn trans_field<'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
                               base: &hir::Expr,
                               get_idx: F)
                               -> DatumBlock<'blk, 'tcx, Expr> where
-    F: FnOnce(TyCtxt<'blk, 'tcx>, &VariantInfo<'tcx>) -> usize,
+    F: FnOnce(TyCtxt<'blk, 'tcx, 'tcx>, &VariantInfo<'tcx>) -> usize,
 {
     let mut bcx = bcx;
     let _icx = push_ctxt("trans_rec_field");
@@ -1826,7 +1826,7 @@ fn trans_binary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-pub fn cast_is_noop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn cast_is_noop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               expr: &hir::Expr,
                               t_in: Ty<'tcx>,
                               t_out: Ty<'tcx>)
@@ -2377,7 +2377,7 @@ enum ExprKind {
     RvalueStmt
 }
 
-fn expr_kind(tcx: TyCtxt, expr: &hir::Expr) -> ExprKind {
+fn expr_kind<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, expr: &hir::Expr) -> ExprKind {
     if tcx.is_method_call(expr.id) {
         // Overloaded operations are generally calls, and hence they are
         // generated via DPS, but there are a few exceptions:
diff --git a/src/librustc_trans/glue.rs b/src/librustc_trans/glue.rs
index 660ce0e0fce..4574c590a62 100644
--- a/src/librustc_trans/glue.rs
+++ b/src/librustc_trans/glue.rs
@@ -89,11 +89,12 @@ pub fn trans_exchange_free_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     }
 }
 
-pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
+pub fn type_needs_drop<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                 ty: Ty<'tcx>) -> bool {
     tcx.type_needs_drop_given_env(ty, &tcx.empty_parameter_environment())
 }
 
-pub fn get_drop_glue_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn get_drop_glue_type<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     t: Ty<'tcx>) -> Ty<'tcx> {
     // Even if there is no dtor for t, there might be one deeper down and we
     // might need to pass in the vtable ptr.
diff --git a/src/librustc_trans/meth.rs b/src/librustc_trans/meth.rs
index e5f0f358f96..231c301503e 100644
--- a/src/librustc_trans/meth.rs
+++ b/src/librustc_trans/meth.rs
@@ -215,7 +215,7 @@ pub fn get_vtable<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     vtable
 }
 
-pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn get_vtable_methods<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                     impl_id: DefId,
                                     substs: &'tcx subst::Substs<'tcx>)
                                     -> Vec<Option<ImplMethod<'tcx>>>
@@ -304,7 +304,7 @@ pub struct ImplMethod<'tcx> {
 }
 
 /// Locates the applicable definition of a method, given its name.
-pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn get_impl_method<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                  impl_def_id: DefId,
                                  substs: &'tcx Substs<'tcx>,
                                  name: Name)
diff --git a/src/librustc_trans/monomorphize.rs b/src/librustc_trans/monomorphize.rs
index 97e9af5fb6e..7c3feba5de7 100644
--- a/src/librustc_trans/monomorphize.rs
+++ b/src/librustc_trans/monomorphize.rs
@@ -182,14 +182,14 @@ impl<'tcx> Instance<'tcx> {
         assert!(substs.regions.iter().all(|&r| r == ty::ReStatic));
         Instance { def: def_id, substs: substs }
     }
-    pub fn mono<'a>(tcx: TyCtxt<'a, 'tcx>, def_id: DefId) -> Instance<'tcx> {
+    pub fn mono<'a>(tcx: TyCtxt<'a, 'tcx, 'tcx>, def_id: DefId) -> Instance<'tcx> {
         Instance::new(def_id, tcx.mk_substs(Substs::empty()))
     }
 }
 
 /// Monomorphizes a type from the AST by first applying the in-scope
 /// substitutions and then normalizing any associated types.
-pub fn apply_param_substs<'a, 'tcx, T>(tcx: TyCtxt<'a, 'tcx>,
+pub fn apply_param_substs<'a, 'tcx, T>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        param_substs: &Substs<'tcx>,
                                        value: &T)
                                        -> T
@@ -201,7 +201,7 @@ pub fn apply_param_substs<'a, 'tcx, T>(tcx: TyCtxt<'a, 'tcx>,
 
 
 /// Returns the normalized type of a struct field
-pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+pub fn field_ty<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                           param_substs: &Substs<'tcx>,
                           f: ty::FieldDef<'tcx>)
                           -> Ty<'tcx>
diff --git a/src/librustc_trans/partitioning.rs b/src/librustc_trans/partitioning.rs
index efeb0abe28c..18a860f9357 100644
--- a/src/librustc_trans/partitioning.rs
+++ b/src/librustc_trans/partitioning.rs
@@ -153,7 +153,7 @@ pub enum PartitioningStrategy {
 // Anything we can't find a proper codegen unit for goes into this.
 const FALLBACK_CODEGEN_UNIT: &'static str = "__rustc_fallback_codegen_unit";
 
-pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx>,
+pub fn partition<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                               trans_items: I,
                               strategy: PartitioningStrategy,
                               reference_map: &ReferenceMap<'tcx>)
@@ -193,7 +193,7 @@ struct PreInliningPartitioning<'tcx> {
 struct PostInliningPartitioning<'tcx>(Vec<CodegenUnit<'tcx>>);
 struct PostDeclarationsPartitioning<'tcx>(Vec<CodegenUnit<'tcx>>);
 
-fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx>,
+fn place_root_translation_items<'a, 'tcx, I>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                              trans_items: I)
                                              -> PreInliningPartitioning<'tcx>
     where I: Iterator<Item = TransItem<'tcx>>
@@ -375,7 +375,7 @@ fn place_declarations<'tcx>(codegen_units: PostInliningPartitioning<'tcx>,
     PostDeclarationsPartitioning(codegen_units)
 }
 
-fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                                  trans_item: TransItem<'tcx>)
                                                  -> Option<DefId> {
     match trans_item {
@@ -410,7 +410,7 @@ fn characteristic_def_id_of_trans_item<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
     }
 }
 
-fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn compute_codegen_unit_name<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                                        def_id: DefId,
                                        volatile: bool)
                                        -> InternedString {
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index 1ed09be8ae9..dcb40b0b418 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -78,8 +78,8 @@ use rustc::hir::print as pprust;
 use rustc::hir;
 use rustc_back::slice;
 
-pub trait AstConv<'tcx> {
-    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx>;
+pub trait AstConv<'gcx, 'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'gcx, 'tcx>;
 
     /// Identify the type scheme for an item with a type, like a type
     /// alias, fn, or struct. This allows you to figure out the set of
@@ -112,16 +112,14 @@ pub trait AstConv<'tcx> {
     /// are in scope into free ones. This function should only return Some
     /// within a fn body.
     /// See ParameterEnvironment::free_substs for more information.
-    fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
-        None
-    }
+    fn get_free_substs(&self) -> Option<&Substs<'tcx>>;
 
     /// What type should we use when a type is omitted?
-        fn ty_infer(&self,
-                    param_and_substs: Option<ty::TypeParameterDef<'tcx>>,
-                    substs: Option<&mut Substs<'tcx>>,
-                    space: Option<ParamSpace>,
-                    span: Span) -> Ty<'tcx>;
+    fn ty_infer(&self,
+                param_and_substs: Option<ty::TypeParameterDef<'tcx>>,
+                substs: Option<&mut Substs<'tcx>>,
+                space: Option<ParamSpace>,
+                span: Span) -> Ty<'tcx>;
 
     /// Projecting an associated type from a (potentially)
     /// higher-ranked trait reference is more complicated, because of
@@ -134,18 +132,7 @@ pub trait AstConv<'tcx> {
                                         span: Span,
                                         poly_trait_ref: ty::PolyTraitRef<'tcx>,
                                         item_name: ast::Name)
-                                        -> Ty<'tcx>
-    {
-        if let Some(trait_ref) = self.tcx().no_late_bound_regions(&poly_trait_ref) {
-            self.projected_ty(span, trait_ref, item_name)
-        } else {
-            // no late-bound regions, we can just ignore the binder
-            span_err!(self.tcx().sess, span, E0212,
-                "cannot extract an associated type from a higher-ranked trait bound \
-                 in this context");
-            self.tcx().types.err
-        }
-    }
+                                        -> Ty<'tcx>;
 
     /// Project an associated type from a non-higher-ranked trait reference.
     /// This is fairly straightforward and can be accommodated in any context.
@@ -268,7 +255,7 @@ fn report_elision_failure(
 }
 
 pub fn opt_ast_region_to_region<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     default_span: Span,
     opt_lifetime: &Option<hir::Lifetime>) -> ty::Region
@@ -302,7 +289,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>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     span: Span,
     param_mode: PathParamMode,
@@ -357,7 +344,7 @@ pub enum PathParamMode {
 }
 
 fn create_region_substs<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     span: Span,
     decl_generics: &ty::Generics<'tcx>,
@@ -401,7 +388,7 @@ fn create_region_substs<'tcx>(
 /// -- that is, a substitution with no types but the correct number of
 /// regions.
 fn create_substs_for_ast_path<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     span: Span,
     param_mode: PathParamMode,
     decl_generics: &ty::Generics<'tcx>,
@@ -502,7 +489,7 @@ 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>,
+fn get_type_substs_for_defs<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                   span: Span,
                                   types_provided: Vec<Ty<'tcx>>,
                                   param_mode: PathParamMode,
@@ -542,7 +529,7 @@ struct ConvertedBinding<'tcx> {
     span: Span,
 }
 
-fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>,
+fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                             rscope: &RegionScope,
                                             span: Span,
                                             decl_generics: &ty::Generics<'tcx>,
@@ -579,7 +566,7 @@ fn convert_angle_bracketed_parameters<'tcx>(this: &AstConv<'tcx>,
 /// Returns the appropriate lifetime to use for any output lifetimes
 /// (if one exists) and a vector of the (pattern, number of lifetimes)
 /// corresponding to each input type/pattern.
-fn find_implied_output_region<'tcx>(this: &AstConv<'tcx>,
+fn find_implied_output_region<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                     input_tys: &[Ty<'tcx>],
                                     input_pats: Vec<String>) -> ElidedLifetime
 {
@@ -615,7 +602,7 @@ fn find_implied_output_region<'tcx>(this: &AstConv<'tcx>,
     }
 }
 
-fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>,
+fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                           elided_lifetime: ElidedLifetime,
                                           ty: &hir::Ty)
                                           -> Ty<'tcx>
@@ -635,7 +622,7 @@ fn convert_ty_with_lifetime_elision<'tcx>(this: &AstConv<'tcx>,
     }
 }
 
-fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
+fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                           rscope: &RegionScope,
                                           span: Span,
                                           decl_generics: &ty::Generics<'tcx>,
@@ -681,7 +668,7 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
 }
 
 pub fn instantiate_poly_trait_ref<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     ast_trait_ref: &hir::PolyTraitRef,
     self_ty: Option<Ty<'tcx>>,
@@ -707,7 +694,7 @@ 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>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     trait_ref: &hir::TraitRef,
     self_ty: Option<Ty<'tcx>>)
@@ -723,7 +710,7 @@ pub fn instantiate_mono_trait_ref<'tcx>(
                                trait_ref.path.segments.last().unwrap())
 }
 
-fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &hir::TraitRef) -> DefId {
+fn trait_def_id<'tcx>(this: &AstConv<'tcx, 'tcx>, trait_ref: &hir::TraitRef) -> DefId {
     let path = &trait_ref.path;
     match ::lookup_full_def(this.tcx(), path.span, trait_ref.ref_id) {
         Def::Trait(trait_def_id) => trait_def_id,
@@ -738,7 +725,7 @@ fn trait_def_id<'tcx>(this: &AstConv<'tcx>, trait_ref: &hir::TraitRef) -> DefId
 }
 
 fn object_path_to_poly_trait_ref<'a,'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     span: Span,
     param_mode: PathParamMode,
@@ -758,7 +745,7 @@ fn object_path_to_poly_trait_ref<'a,'tcx>(
 }
 
 fn ast_path_to_poly_trait_ref<'a,'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     span: Span,
     param_mode: PathParamMode,
@@ -807,7 +794,7 @@ fn ast_path_to_poly_trait_ref<'a,'tcx>(
     poly_trait_ref
 }
 
-fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
+fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx, 'tcx>,
                                        rscope: &RegionScope,
                                        span: Span,
                                        param_mode: PathParamMode,
@@ -828,7 +815,7 @@ fn ast_path_to_mono_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
     ty::TraitRef::new(trait_def_id, substs)
 }
 
-fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
+fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx, 'tcx>,
                                             rscope: &RegionScope,
                                             span: Span,
                                             param_mode: PathParamMode,
@@ -889,7 +876,7 @@ fn create_substs_for_ast_trait_ref<'a,'tcx>(this: &AstConv<'tcx>,
 }
 
 fn ast_type_binding_to_poly_projection_predicate<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     mut trait_ref: ty::PolyTraitRef<'tcx>,
     self_ty: Option<Ty<'tcx>>,
     binding: &ConvertedBinding<'tcx>)
@@ -976,7 +963,7 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
 }
 
 fn ast_path_to_ty<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     span: Span,
     param_mode: PathParamMode,
@@ -1012,7 +999,7 @@ fn ast_path_to_ty<'tcx>(
 
 type TraitAndProjections<'tcx> = (ty::PolyTraitRef<'tcx>, Vec<ty::PolyProjectionPredicate<'tcx>>);
 
-fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
+fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx, 'tcx>,
                              rscope: &RegionScope,
                              ty: &hir::Ty,
                              bounds: &[hir::TyParamBound])
@@ -1096,7 +1083,7 @@ fn ast_ty_to_trait_ref<'tcx>(this: &AstConv<'tcx>,
     }
 }
 
-fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
+fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                   rscope: &RegionScope,
                                   span: Span,
                                   trait_ref: ty::PolyTraitRef<'tcx>,
@@ -1118,7 +1105,7 @@ fn trait_ref_to_object_type<'tcx>(this: &AstConv<'tcx>,
     result
 }
 
-fn make_object_type<'tcx>(this: &AstConv<'tcx>,
+fn make_object_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
                           span: Span,
                           principal: ty::PolyTraitRef<'tcx>,
                           bounds: ty::ExistentialBounds<'tcx>)
@@ -1191,7 +1178,7 @@ 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>,
+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,
@@ -1229,7 +1216,7 @@ fn find_bound_for_assoc_item<'tcx>(this: &AstConv<'tcx>,
 
 // Checks that bounds contains exactly one element and reports appropriate
 // errors otherwise.
-fn one_bound_for_assoc_type<'tcx>(this: &AstConv<'tcx>,
+fn one_bound_for_assoc_type<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                   bounds: Vec<ty::PolyTraitRef<'tcx>>,
                                   ty_param_name: &str,
                                   assoc_name: &str,
@@ -1268,7 +1255,7 @@ fn one_bound_for_assoc_type<'tcx>(this: &AstConv<'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>,
+fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                    span: Span,
                                    ty: Ty<'tcx>,
                                    ty_path_def: Def,
@@ -1370,7 +1357,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
     (ty, Def::AssociatedTy(trait_did, item_did))
 }
 
-fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
+fn qpath_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
                      rscope: &RegionScope,
                      span: Span,
                      param_mode: PathParamMode,
@@ -1425,7 +1412,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'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>,
+pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
                               rscope: &RegionScope,
                               decl_generics: &ty::Generics<'tcx>,
                               index: usize,
@@ -1447,7 +1434,7 @@ pub fn ast_ty_arg_to_ty<'tcx>(this: &AstConv<'tcx>,
 // 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>,
+fn base_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
                         rscope: &RegionScope,
                         span: Span,
                         param_mode: PathParamMode,
@@ -1552,7 +1539,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
 
 // 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>,
+pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
                                         rscope: &RegionScope,
                                         span: Span,
                                         param_mode: PathParamMode,
@@ -1588,7 +1575,7 @@ pub fn finish_resolving_def_to_ty<'tcx>(this: &AstConv<'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>,
+pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx, 'tcx>,
                           rscope: &RegionScope,
                           ast_ty: &hir::Ty)
                           -> Ty<'tcx>
@@ -1734,7 +1721,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
     return typ;
 }
 
-pub fn ty_of_arg<'tcx>(this: &AstConv<'tcx>,
+pub fn ty_of_arg<'tcx>(this: &AstConv<'tcx, 'tcx>,
                        rscope: &RegionScope,
                        a: &hir::Arg,
                        expected_ty: Option<Ty<'tcx>>)
@@ -1752,7 +1739,7 @@ struct SelfInfo<'a, 'tcx> {
     explicit_self: &'a hir::ExplicitSelf,
 }
 
-pub fn ty_of_method<'tcx>(this: &AstConv<'tcx>,
+pub fn ty_of_method<'tcx>(this: &AstConv<'tcx, 'tcx>,
                           sig: &hir::MethodSig,
                           untransformed_self_ty: Ty<'tcx>)
                           -> (ty::BareFnTy<'tcx>, ty::ExplicitSelfCategory) {
@@ -1769,13 +1756,13 @@ pub fn ty_of_method<'tcx>(this: &AstConv<'tcx>,
     (bare_fn_ty, optional_explicit_self_category.unwrap())
 }
 
-pub fn ty_of_bare_fn<'tcx>(this: &AstConv<'tcx>, unsafety: hir::Unsafety, abi: abi::Abi,
+pub fn ty_of_bare_fn<'tcx>(this: &AstConv<'tcx, 'tcx>, unsafety: hir::Unsafety, abi: abi::Abi,
                                               decl: &hir::FnDecl) -> ty::BareFnTy<'tcx> {
     let (bare_fn_ty, _) = ty_of_method_or_bare_fn(this, unsafety, abi, None, decl);
     bare_fn_ty
 }
 
-fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
+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>>,
@@ -1837,7 +1824,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
     }, explicit_self_category)
 }
 
-fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx>,
+fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx, 'tcx>,
                                  rscope: &RegionScope,
                                  self_info: SelfInfo<'a, 'tcx>)
                                  -> (Option<Ty<'tcx>>, Option<ty::ExplicitSelfCategory>)
@@ -1929,7 +1916,7 @@ fn determine_self_type<'a, 'tcx>(this: &AstConv<'tcx>,
 }
 
 pub fn ty_of_closure<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     unsafety: hir::Unsafety,
     decl: &hir::FnDecl,
     abi: abi::Abi,
@@ -1992,7 +1979,7 @@ pub fn ty_of_closure<'tcx>(
 /// 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>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     span: Span,
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
@@ -2008,7 +1995,7 @@ fn conv_existential_bounds<'tcx>(
 }
 
 fn conv_ty_poly_trait_ref<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     span: Span,
     ast_bounds: &[hir::TyParamBound])
@@ -2042,7 +2029,7 @@ fn conv_ty_poly_trait_ref<'tcx>(
 }
 
 pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
-    this: &AstConv<'tcx>,
+    this: &AstConv<'tcx, 'tcx>,
     rscope: &RegionScope,
     span: Span,
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
@@ -2093,7 +2080,7 @@ pub fn conv_existential_bounds_from_partitioned_bounds<'tcx>(
 /// 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>,
+    this: &AstConv<'tcx, 'tcx>,
     span: Span,
     explicit_region_bounds: &[&hir::Lifetime],
     principal_trait_ref: ty::PolyTraitRef<'tcx>,
@@ -2159,10 +2146,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>(tcx: TyCtxt,
-                            _span: Span,
-                            ast_bounds: &'a [hir::TyParamBound])
-                            -> PartitionedBounds<'a>
+pub fn partition_bounds<'a, 'b, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                      _span: Span,
+                                      ast_bounds: &'b [hir::TyParamBound])
+                                      -> PartitionedBounds<'b>
 {
     let mut builtin_bounds = ty::BuiltinBounds::empty();
     let mut region_bounds = Vec::new();
@@ -2250,7 +2237,7 @@ pub struct Bounds<'tcx> {
 }
 
 impl<'a, 'tcx> Bounds<'tcx> {
-    pub fn predicates(&self, tcx: TyCtxt<'a, 'tcx>, param_ty: Ty<'tcx>)
+    pub fn predicates(&self, tcx: TyCtxt<'a, 'tcx, '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 8e9138cf779..537f1e33c36 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -30,13 +30,13 @@ use syntax::ptr::P;
 use rustc::hir::{self, PatKind};
 use rustc::hir::print as pprust;
 
-pub struct PatCtxt<'a, 'tcx: 'a> {
-    pub fcx: &'a FnCtxt<'a, 'tcx>,
+pub struct PatCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    pub fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     pub map: PatIdMap,
 }
 
-impl<'a, 'tcx> Deref for PatCtxt<'a, 'tcx> {
-    type Target = FnCtxt<'a, 'tcx>;
+impl<'a, 'gcx, 'tcx> Deref for PatCtxt<'a, 'gcx, 'tcx> {
+    type Target = FnCtxt<'a, 'gcx, 'tcx>;
     fn deref(&self) -> &Self::Target {
         self.fcx
     }
@@ -56,7 +56,7 @@ fn bad_struct_kind_err(sess: &Session, pat: &hir::Pat, path: &hir::Path, lint: b
     }
 }
 
-impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
+impl<'a, 'tcx> PatCtxt<'a, 'tcx, 'tcx> {
 pub fn check_pat(&self, pat: &'tcx hir::Pat, expected: Ty<'tcx>) {
     let tcx = self.tcx();
 
@@ -456,7 +456,7 @@ pub fn check_dereferencable(&self, span: Span, expected: Ty<'tcx>, inner: &hir::
 }
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 pub fn check_match(&self,
                    expr: &'tcx hir::Expr,
                    discrim: &'tcx hir::Expr,
@@ -579,7 +579,7 @@ pub fn check_match(&self,
 }
 }
 
-impl<'a, 'tcx> PatCtxt<'a, 'tcx> {
+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>],
                         etc: bool, expected: Ty<'tcx>) {
diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs
index f7726bc9cf4..fbc5a0b33aa 100644
--- a/src/librustc_typeck/check/assoc.rs
+++ b/src/librustc_typeck/check/assoc.rs
@@ -16,7 +16,7 @@ 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>,
+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,
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index 15307864a42..f46e6204ea4 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -63,7 +63,7 @@ enum CallStep<'tcx> {
     Overloaded(ty::MethodCallee<'tcx>)
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 pub fn check_call(&self,
                   call_expr: &'tcx hir::Expr,
                   callee_expr: &'tcx hir::Expr,
@@ -338,7 +338,7 @@ struct CallResolution<'tcx> {
 }
 
 impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
-    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>) {
+    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx, 'tcx>) {
         debug!("DeferredCallResolution::resolve() {:?}",
                self);
 
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index 506347679a4..e4cd9540e96 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> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, '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>> {
@@ -110,7 +110,7 @@ enum CastError {
 }
 
 impl<'a, 'tcx> CastCheck<'tcx> {
-    pub fn new(fcx: &FnCtxt<'a, 'tcx>,
+    pub fn new(fcx: &FnCtxt<'a, 'tcx, '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>, e: CastError) {
+    fn report_cast_error(&self, fcx: &FnCtxt<'a, 'tcx, '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>) {
+    fn report_cast_to_unsized_type(&self, fcx: &FnCtxt<'a, 'tcx, '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>) {
+    fn trivial_cast_lint(&self, fcx: &FnCtxt<'a, 'tcx, '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>) {
+    pub fn check(mut self, fcx: &FnCtxt<'a, 'tcx, '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>) -> Result<CastKind, CastError> {
+    fn do_check(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Result<CastKind, CastError> {
         use rustc::ty::cast::IntTy::*;
         use rustc::ty::cast::CastTy::*;
 
@@ -377,7 +377,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_ptr_ptr_cast(&self,
-                          fcx: &FnCtxt<'a, 'tcx>,
+                          fcx: &FnCtxt<'a, 'tcx, 'tcx>,
                           m_expr: &'tcx ty::TypeAndMut<'tcx>,
                           m_cast: &'tcx ty::TypeAndMut<'tcx>)
                           -> Result<CastKind, CastError>
@@ -404,7 +404,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_fptr_ptr_cast(&self,
-                           fcx: &FnCtxt<'a, 'tcx>,
+                           fcx: &FnCtxt<'a, 'tcx, 'tcx>,
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError>
     {
@@ -418,7 +418,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_ptr_addr_cast(&self,
-                           fcx: &FnCtxt<'a, 'tcx>,
+                           fcx: &FnCtxt<'a, 'tcx, 'tcx>,
                            m_expr: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError>
     {
@@ -432,7 +432,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_ref_cast(&self,
-                      fcx: &FnCtxt<'a, 'tcx>,
+                      fcx: &FnCtxt<'a, 'tcx, 'tcx>,
                       m_expr: &'tcx ty::TypeAndMut<'tcx>,
                       m_cast: &'tcx ty::TypeAndMut<'tcx>)
                       -> Result<CastKind, CastError>
@@ -458,7 +458,7 @@ impl<'a, 'tcx> CastCheck<'tcx> {
     }
 
     fn check_addr_ptr_cast(&self,
-                           fcx: &FnCtxt<'a, 'tcx>,
+                           fcx: &FnCtxt<'a, 'tcx, 'tcx>,
                            m_cast: &'tcx ty::TypeAndMut<'tcx>)
                            -> Result<CastKind, CastError>
     {
@@ -470,13 +470,13 @@ impl<'a, 'tcx> CastCheck<'tcx> {
         }
     }
 
-    fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx>) -> bool {
+    fn try_coercion_cast(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> bool {
         fcx.try_coerce(self.expr, self.cast_ty).is_ok()
     }
 
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, '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 7632f58f057..e6ec47f1364 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -19,7 +19,7 @@ use std::cmp;
 use syntax::abi::Abi;
 use rustc::hir;
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 pub fn check_expr_closure(&self,
                           expr: &hir::Expr,
                           _capture: hir::CaptureClause,
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index d534e48dd05..6e24df481bd 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -77,8 +77,8 @@ use std::cell::RefCell;
 use std::collections::VecDeque;
 use rustc::hir;
 
-struct Coerce<'a, 'tcx: 'a> {
-    fcx: &'a FnCtxt<'a, 'tcx>,
+struct Coerce<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     origin: TypeOrigin,
     use_lub: bool,
     unsizing_obligations: RefCell<Vec<traits::PredicateObligation<'tcx>>>,
@@ -97,8 +97,8 @@ fn coerce_mutbls<'tcx>(from_mutbl: hir::Mutability,
     }
 }
 
-impl<'f, 'tcx> Coerce<'f, 'tcx> {
-    fn new(fcx: &'f FnCtxt<'f, 'tcx>, origin: TypeOrigin) -> Self {
+impl<'f, 'tcx> Coerce<'f, 'tcx, 'tcx> {
+    fn new(fcx: &'f FnCtxt<'f, 'tcx, 'tcx>, origin: TypeOrigin) -> Self {
         Coerce {
             fcx: fcx,
             origin: origin,
@@ -107,7 +107,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         }
     }
 
-    fn tcx(&self) -> TyCtxt<'f, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'f, 'tcx, 'tcx> {
         self.fcx.tcx()
     }
 
@@ -591,7 +591,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
     }
 }
 
-fn apply<'a, 'b, 'tcx, E, I>(coerce: &mut Coerce<'a, 'tcx>,
+fn apply<'a, 'b, 'tcx, E, I>(coerce: &mut Coerce<'a, 'tcx, 'tcx>,
                              exprs: &E,
                              a: Ty<'tcx>,
                              b: Ty<'tcx>)
@@ -614,7 +614,7 @@ fn apply<'a, 'b, 'tcx, E, I>(coerce: &mut Coerce<'a, 'tcx>,
     Ok((ty, adjustment))
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, '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 8dfd62e1a66..f80e715721c 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> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, '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>) {
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index 9d4a58aab06..e5f14478025 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -274,7 +274,7 @@ 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>,
+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) {
@@ -343,8 +343,8 @@ enum TypeContext {
     }
 }
 
-struct DropckContext<'a, 'b: 'a, 'tcx: 'b> {
-    rcx: &'a mut RegionCtxt<'b, 'tcx>,
+struct DropckContext<'a, 'b: 'a, 'gcx: 'b+'tcx, 'tcx: 'b> {
+    rcx: &'a mut RegionCtxt<'b, 'gcx, 'tcx>,
     /// types that have already been traversed
     breadcrumbs: FnvHashSet<Ty<'tcx>>,
     /// span for error reporting
@@ -355,7 +355,7 @@ struct DropckContext<'a, 'b: 'a, '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>,
+    cx: &mut DropckContext<'a, 'b, 'tcx, 'tcx>,
     context: TypeContext,
     ty: Ty<'tcx>,
     depth: usize) -> Result<(), Error<'tcx>>
@@ -500,7 +500,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'b, 'tcx>(
     }
 }
 
-fn has_dtor_of_interest<'a, 'b, 'tcx>(cx: &DropckContext<'a, 'b, 'tcx>,
+fn has_dtor_of_interest<'a, 'b, 'tcx>(cx: &DropckContext<'a, 'b, 'tcx, 'tcx>,
                                       ty: ty::Ty<'tcx>) -> bool {
     match ty.sty {
         ty::TyEnum(def, _) | ty::TyStruct(def, _) => {
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index ab5342bfa1a..a2570ef8eef 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -23,11 +23,11 @@ use rustc::infer::{InferCtxt, InferOk, TypeOrigin};
 use syntax::codemap::Span;
 use rustc::hir;
 
-struct ConfirmContext<'a, 'tcx:'a> {
-    fcx: &'a FnCtxt<'a, 'tcx>,
+struct ConfirmContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a>{
+    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     span: Span,
-    self_expr: &'tcx hir::Expr,
-    call_expr: &'tcx hir::Expr,
+    self_expr: &'gcx hir::Expr,
+    call_expr: &'gcx hir::Expr,
 }
 
 struct InstantiatedMethodSig<'tcx> {
@@ -44,7 +44,7 @@ struct InstantiatedMethodSig<'tcx> {
     method_predicates: ty::InstantiatedPredicates<'tcx>,
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 pub fn confirm_method(&self,
                       span: Span,
                       self_expr: &'tcx hir::Expr,
@@ -64,12 +64,12 @@ pub fn confirm_method(&self,
 }
 }
 
-impl<'a,'tcx> ConfirmContext<'a,'tcx> {
-    fn new(fcx: &'a FnCtxt<'a, 'tcx>,
+impl<'a,'tcx> ConfirmContext<'a,'tcx, 'tcx> {
+    fn new(fcx: &'a FnCtxt<'a, 'tcx, 'tcx>,
            span: Span,
            self_expr: &'tcx hir::Expr,
            call_expr: &'tcx hir::Expr)
-           -> ConfirmContext<'a, 'tcx>
+           -> ConfirmContext<'a, 'tcx, 'tcx>
     {
         ConfirmContext { fcx: fcx, span: span, self_expr: self_expr, call_expr: call_expr }
     }
@@ -278,7 +278,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     }
 
     fn extract_trait_ref<R, F>(&mut self, self_ty: Ty<'tcx>, mut closure: F) -> R where
-        F: FnMut(&mut ConfirmContext<'a, 'tcx>, Ty<'tcx>, &ty::TraitTy<'tcx>) -> R,
+        F: FnMut(&mut ConfirmContext<'a, 'tcx, '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
@@ -617,11 +617,11 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     ///////////////////////////////////////////////////////////////////////////
     // MISCELLANY
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.fcx.tcx()
     }
 
-    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
+    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx, 'tcx> {
         self.fcx.infcx()
     }
 
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 63df0021852..ae3446bbde8 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> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 /// Determines whether the type `self_ty` supports a method name `method_name` or not.
 pub fn method_exists(&self,
                      span: Span,
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 3e997bc140f..00c90dcbee4 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -31,8 +31,8 @@ use std::rc::Rc;
 use self::CandidateKind::*;
 pub use self::PickKind::*;
 
-struct ProbeContext<'a, 'tcx:'a> {
-    fcx: &'a FnCtxt<'a, 'tcx>,
+struct ProbeContext<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     span: Span,
     mode: Mode,
     item_name: ast::Name,
@@ -128,7 +128,7 @@ pub enum Mode {
     Path
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 pub fn probe_method(&self,
                     span: Span,
                     mode: Mode,
@@ -233,14 +233,14 @@ fn create_steps(&self,
 }
 }
 
-impl<'a,'tcx> ProbeContext<'a,'tcx> {
-    fn new(fcx: &'a FnCtxt<'a,'tcx>,
+impl<'a,'tcx> ProbeContext<'a,'tcx, 'tcx> {
+    fn new(fcx: &'a FnCtxt<'a,'tcx, '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>
+           -> ProbeContext<'a,'tcx, 'tcx>
     {
         ProbeContext {
             fcx: fcx,
@@ -267,11 +267,11 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         self.private_candidate = None;
     }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.fcx.tcx()
     }
 
-    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx> {
+    fn infcx(&self) -> &'a InferCtxt<'a, 'tcx, 'tcx> {
         self.fcx.infcx()
     }
 
@@ -554,7 +554,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
         mut mk_cand: F,
     ) where
         F: for<'b> FnMut(
-            &mut ProbeContext<'b, 'tcx>,
+            &mut ProbeContext<'b, 'tcx, '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 d9af3552d85..ab3c6b4513d 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> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, '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 76b0e9342bd..486b353488e 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -154,8 +154,8 @@ mod op;
 /// Here, the function `foo()` and the closure passed to
 /// `bar()` will each have their own `FnCtxt`, but they will
 /// share the inherited fields.
-pub struct Inherited<'a, 'tcx: 'a> {
-    infcx: InferCtxt<'a, 'tcx>,
+pub struct Inherited<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    infcx: InferCtxt<'a, 'gcx, 'tcx>,
     locals: RefCell<NodeMap<Ty<'tcx>>>,
 
     fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
@@ -175,7 +175,7 @@ pub struct Inherited<'a, 'tcx: 'a> {
 }
 
 trait DeferredCallResolution<'tcx> {
-    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx>);
+    fn resolve<'a>(&mut self, fcx: &FnCtxt<'a,'tcx, 'tcx>);
 }
 
 type DeferredCallResolutionHandler<'tcx> = Box<DeferredCallResolution<'tcx>+'tcx>;
@@ -215,7 +215,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>) -> Expectation<'tcx> {
+    fn adjust_for_branches(&self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Expectation<'tcx> {
         match *self {
             ExpectHasType(ety) => {
                 let ety = fcx.infcx().shallow_resolve(ety);
@@ -251,7 +251,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>, ty: Ty<'tcx>) -> Expectation<'tcx> {
+    fn rvalue_hint(fcx: &FnCtxt<'a, 'tcx, 'tcx>, ty: Ty<'tcx>) -> Expectation<'tcx> {
         match fcx.tcx().struct_tail(ty).sty {
             ty::TySlice(_) | ty::TyStr | ty::TyTrait(..) => {
                 ExpectRvalueLikeUnsized(ty)
@@ -263,7 +263,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>) -> Expectation<'tcx> {
+    fn resolve(self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Expectation<'tcx> {
         match self {
             NoExpectation => {
                 NoExpectation
@@ -283,7 +283,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
         }
     }
 
-    fn to_option(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
+    fn to_option(self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Option<Ty<'tcx>> {
         match self.resolve(fcx) {
             NoExpectation => None,
             ExpectCastableToType(ty) |
@@ -292,7 +292,7 @@ impl<'a, 'tcx> Expectation<'tcx> {
         }
     }
 
-    fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx>) -> Option<Ty<'tcx>> {
+    fn only_has_type(self, fcx: &FnCtxt<'a, 'tcx, 'tcx>) -> Option<Ty<'tcx>> {
         match self.resolve(fcx) {
             ExpectHasType(ty) => Some(ty),
             _ => None
@@ -342,7 +342,7 @@ impl UnsafetyState {
 }
 
 #[derive(Clone)]
-pub struct FnCtxt<'a, 'tcx: 'a> {
+pub struct FnCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
     body_id: ast::NodeId,
 
     // This flag is set to true if, during the writeback phase, we encounter
@@ -359,16 +359,16 @@ pub struct FnCtxt<'a, 'tcx: 'a> {
 
     ps: RefCell<UnsafetyState>,
 
-    inh: &'a Inherited<'a, 'tcx>,
+    inh: &'a Inherited<'a, 'gcx, 'tcx>,
 
-    ccx: &'a CrateCtxt<'a, 'tcx>,
+    ccx: &'a CrateCtxt<'a, 'gcx>,
 }
 
-impl<'a, 'tcx> Inherited<'a, 'tcx> {
-    fn new(tcx: TyCtxt<'a, 'tcx>,
+impl<'a, 'tcx> Inherited<'a, 'tcx, 'tcx> {
+    fn new(tcx: TyCtxt<'a, 'tcx, 'tcx>,
            tables: &'a RefCell<ty::Tables<'tcx>>,
            param_env: ty::ParameterEnvironment<'a, 'tcx>)
-           -> Inherited<'a, 'tcx> {
+           -> Inherited<'a, 'tcx, 'tcx> {
 
         Inherited {
             infcx: InferCtxt::new(tcx, tables, Some(param_env), ProjectionMode::AnyFinal),
@@ -398,7 +398,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
 
 fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
                                      tables: &'a RefCell<ty::Tables<'tcx>>)
-                                    -> Inherited<'a, 'tcx> {
+                                    -> Inherited<'a, 'tcx, 'tcx> {
     // It's kind of a kludge to manufacture a fake function context
     // and statement context, but we might as well do write the code only once
     let param_env = ccx.tcx.empty_parameter_environment();
@@ -513,11 +513,11 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 }
 
-struct GatherLocalsVisitor<'a, 'tcx: 'a> {
-    fcx: &'a FnCtxt<'a, 'tcx>
+struct GatherLocalsVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>
 }
 
-impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
+impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx, 'tcx> {
     fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
         match ty_opt {
             None => {
@@ -535,7 +535,7 @@ impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx> {
+impl<'a, 'tcx> Visitor<'tcx> for GatherLocalsVisitor<'a, 'tcx, 'tcx> {
     // Add explicitly-declared locals.
     fn visit_local(&mut self, local: &'tcx hir::Local) {
         let o_ty = match local.ty {
@@ -610,8 +610,8 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
                       decl: &'tcx hir::FnDecl,
                       fn_id: ast::NodeId,
                       body: &'tcx hir::Block,
-                      inherited: &'a Inherited<'a, 'tcx>)
-                      -> FnCtxt<'a, 'tcx>
+                      inherited: &'a Inherited<'a, 'tcx, 'tcx>)
+                      -> FnCtxt<'a, 'tcx, 'tcx>
 {
     let tcx = ccx.tcx;
 
@@ -902,9 +902,9 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
 }
 
-fn report_forbidden_specialization(tcx: TyCtxt,
-                                   impl_item: &hir::ImplItem,
-                                   parent_impl: DefId)
+fn report_forbidden_specialization<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                             impl_item: &hir::ImplItem,
+                                             parent_impl: DefId)
 {
     let mut err = struct_span_err!(
         tcx.sess, impl_item.span, E0520,
@@ -925,8 +925,10 @@ fn report_forbidden_specialization(tcx: TyCtxt,
     err.emit();
 }
 
-fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>, trait_def: &ty::TraitDef<'tcx>,
-                                           impl_id: DefId, impl_item: &hir::ImplItem)
+fn check_specialization_validity<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                           trait_def: &ty::TraitDef<'tcx>,
+                                           impl_id: DefId,
+                                           impl_item: &hir::ImplItem)
 {
     let ancestors = trait_def.ancestors(impl_id);
 
@@ -1143,10 +1145,10 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 /// Checks whether a type can be represented in memory. In particular, it
 /// identifies types that contain themselves without indirection through a
 /// pointer, which would mean their size is unbounded.
-pub fn check_representable(tcx: TyCtxt,
-                           sp: Span,
-                           item_id: ast::NodeId,
-                           _designation: &str) -> bool {
+pub fn check_representable<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     sp: Span,
+                                     item_id: ast::NodeId,
+                                     _designation: &str) -> bool {
     let rty = tcx.node_id_to_type(item_id);
 
     // Check that it is possible to represent this type. This call identifies
@@ -1165,7 +1167,7 @@ pub fn check_representable(tcx: TyCtxt,
     return true
 }
 
-pub fn check_simd(tcx: TyCtxt, sp: Span, id: ast::NodeId) {
+pub fn check_simd<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>, sp: Span, id: ast::NodeId) {
     let t = tcx.node_id_to_type(id);
     match t.sty {
         ty::TyStruct(def, substs) => {
@@ -1252,8 +1254,8 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
     check_representable(ccx.tcx, sp, id, "enum");
 }
 
-impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> { self.infcx().tcx }
+impl<'a, 'tcx> AstConv<'tcx, 'tcx> for FnCtxt<'a, 'tcx, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.infcx().tcx }
 
     fn get_item_type_scheme(&self, _: Span, id: DefId)
                             -> Result<ty::TypeScheme<'tcx>, ErrorReported>
@@ -1364,7 +1366,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> RegionScope for FnCtxt<'a, 'tcx, 'tcx> {
     fn object_lifetime_default(&self, span: Span) -> Option<ty::Region> {
         Some(self.base_object_lifetime_default(span))
     }
@@ -1421,12 +1423,12 @@ enum TupleArgumentsFlag {
     TupleArguments,
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
     pub fn new(ccx: &'a CrateCtxt<'a, 'tcx>,
-               inh: &'a Inherited<'a, 'tcx>,
+               inh: &'a Inherited<'a, 'tcx, 'tcx>,
                rty: ty::FnOutput<'tcx>,
                body_id: ast::NodeId)
-               -> FnCtxt<'a, 'tcx> {
+               -> FnCtxt<'a, 'tcx, 'tcx> {
         FnCtxt {
             body_id: body_id,
             writeback_errors: Cell::new(false),
@@ -1438,9 +1440,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn tcx(&self) -> TyCtxt<'a, 'tcx> { self.infcx().tcx }
+    pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> { self.infcx().tcx }
 
-    pub fn infcx(&self) -> &InferCtxt<'a,'tcx> {
+    pub fn infcx(&self) -> &InferCtxt<'a,'tcx, 'tcx> {
         &self.inh.infcx
     }
 
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index d86813e2807..977eb4b35ff 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -17,7 +17,7 @@ use syntax::ast;
 use syntax::parse::token;
 use rustc::hir;
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 /// Check a `a <op>= b`
 pub fn check_binop_assign(&self,
                           expr: &'tcx hir::Expr,
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index 3972bfce3fa..c16a00e723e 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -112,7 +112,7 @@ macro_rules! ignore_err {
 ///////////////////////////////////////////////////////////////////////////
 // PUBLIC ENTRY POINTS
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, '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 {
@@ -166,8 +166,8 @@ pub fn regionck_fn(&self,
 ///////////////////////////////////////////////////////////////////////////
 // INTERNALS
 
-pub struct RegionCtxt<'a, 'tcx: 'a> {
-    pub fcx: &'a FnCtxt<'a, 'tcx>,
+pub struct RegionCtxt<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    pub fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
 
     region_bound_pairs: Vec<(ty::Region, GenericKind<'tcx>)>,
 
@@ -190,11 +190,11 @@ pub struct RegionCtxt<'a, 'tcx: 'a> {
 pub struct RepeatingScope(ast::NodeId);
 pub enum SubjectNode { Subject(ast::NodeId), None }
 
-impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
-    pub fn new(fcx: &'a FnCtxt<'a, 'tcx>,
+impl<'a, 'tcx> RegionCtxt<'a, 'tcx, 'tcx> {
+    pub fn new(fcx: &'a FnCtxt<'a, 'tcx, 'tcx>,
                initial_repeating_scope: RepeatingScope,
                initial_body_id: ast::NodeId,
-               subject: SubjectNode) -> RegionCtxt<'a, 'tcx> {
+               subject: SubjectNode) -> RegionCtxt<'a, 'tcx, 'tcx> {
         let RepeatingScope(initial_repeating_scope) = initial_repeating_scope;
         RegionCtxt {
             fcx: fcx,
@@ -207,11 +207,11 @@ impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
         }
     }
 
-    pub fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    pub fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.fcx.tcx()
     }
 
-    pub fn infcx(&self) -> &InferCtxt<'a,'tcx> {
+    pub fn infcx(&self) -> &InferCtxt<'a,'tcx, 'tcx> {
         self.fcx.infcx()
     }
 
@@ -489,7 +489,7 @@ fn constrain_bindings_in_pat(&mut self, pat: &hir::Pat) {
 }
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'tcx> {
+impl<'a, 'tcx, 'v> Visitor<'v> for RegionCtxt<'a, 'tcx, '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
@@ -798,7 +798,7 @@ fn visit_expr(&mut self, expr: &hir::Expr) {
 }
 }
 
-impl<'a, 'tcx> RegionCtxt<'a, 'tcx> {
+impl<'a, 'tcx> RegionCtxt<'a, 'tcx, 'tcx> {
 fn constrain_cast(&mut self,
                   cast_expr: &hir::Expr,
                   source_expr: &hir::Expr)
@@ -1155,7 +1155,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<'t, 'a, 'tcx>,
+                    mc: mc::MemCategorizationContext<'a, 'tcx, '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 940e662d5ce..414a3157c0e 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> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 pub fn closure_analyze_fn(&self, body: &hir::Block) {
     let mut seed = SeedBorrowKind::new(self);
     seed.visit_block(body);
@@ -85,12 +85,12 @@ pub fn closure_analyze_const(&self, body: &hir::Expr) {
 ///////////////////////////////////////////////////////////////////////////
 // SEED BORROW KIND
 
-struct SeedBorrowKind<'a,'tcx:'a> {
-    fcx: &'a FnCtxt<'a,'tcx>,
+struct SeedBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     closures_with_inferred_kinds: HashSet<ast::NodeId>,
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx> {
+impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx, 'tcx> {
     fn visit_expr(&mut self, expr: &hir::Expr) {
         match expr.node {
             hir::ExprClosure(cc, _, ref body, _) => {
@@ -104,16 +104,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for SeedBorrowKind<'a, 'tcx> {
     }
 }
 
-impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
-    fn new(fcx: &'a FnCtxt<'a,'tcx>) -> SeedBorrowKind<'a,'tcx> {
+impl<'a,'tcx> SeedBorrowKind<'a,'tcx, 'tcx> {
+    fn new(fcx: &'a FnCtxt<'a,'tcx, 'tcx>) -> SeedBorrowKind<'a,'tcx, 'tcx> {
         SeedBorrowKind { fcx: fcx, closures_with_inferred_kinds: HashSet::new() }
     }
 
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.fcx.tcx()
     }
 
-    fn infcx(&self) -> &'a InferCtxt<'a,'tcx> {
+    fn infcx(&self) -> &'a InferCtxt<'a,'tcx, 'tcx> {
         self.fcx.infcx()
     }
 
@@ -160,15 +160,15 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
 ///////////////////////////////////////////////////////////////////////////
 // ADJUST BORROW KIND
 
-struct AdjustBorrowKind<'a,'tcx:'a> {
-    fcx: &'a FnCtxt<'a,'tcx>,
+struct AdjustBorrowKind<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    fcx: &'a FnCtxt<'a, 'gcx, 'tcx>,
     closures_with_inferred_kinds: &'a HashSet<ast::NodeId>,
 }
 
-impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
-    fn new(fcx: &'a FnCtxt<'a,'tcx>,
+impl<'a,'tcx> AdjustBorrowKind<'a,'tcx, 'tcx> {
+    fn new(fcx: &'a FnCtxt<'a,'tcx, 'tcx>,
            closures_with_inferred_kinds: &'a HashSet<ast::NodeId>)
-           -> AdjustBorrowKind<'a,'tcx> {
+           -> AdjustBorrowKind<'a,'tcx, 'tcx> {
         AdjustBorrowKind { fcx: fcx, closures_with_inferred_kinds: closures_with_inferred_kinds }
     }
 
@@ -500,7 +500,7 @@ impl<'a,'tcx> AdjustBorrowKind<'a,'tcx> {
     }
 }
 
-impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx> {
+impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx, 'tcx> {
     fn visit_fn(&mut self,
                 fn_kind: intravisit::FnKind<'v>,
                 decl: &'v hir::FnDecl,
@@ -513,7 +513,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for AdjustBorrowKind<'a, 'tcx> {
     }
 }
 
-impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx> {
+impl<'a,'tcx> euv::Delegate<'tcx> for AdjustBorrowKind<'a,'tcx, '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 53c47b85fbe..bc99fd7fb64 100644
--- a/src/librustc_typeck/check/wfcheck.rs
+++ b/src/librustc_typeck/check/wfcheck.rs
@@ -40,7 +40,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         }
     }
 
-    fn tcx(&self) -> TyCtxt<'ccx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'ccx, 'tcx, 'tcx> {
         self.ccx.tcx
     }
 
@@ -168,14 +168,14 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn with_item_fcx<F>(&mut self, item: &hir::Item, f: F) where
-        F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>,
+        F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx, 'tcx>,
                            &mut CheckTypeWellFormedVisitor<'ccx,'tcx>) -> Vec<Ty<'tcx>>,
     {
         self.with_fcx(item.id, item.span, f)
     }
 
     fn with_fcx<F>(&mut self, id: ast::NodeId, span: Span, mut f: F) where
-        F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>,
+        F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx, 'tcx>,
                            &mut CheckTypeWellFormedVisitor<'ccx,'tcx>) -> Vec<Ty<'tcx>>,
     {
         let ccx = self.ccx;
@@ -190,7 +190,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 
     /// In a type definition, we check that to ensure that the types of the fields are well-formed.
     fn check_type_defn<F>(&mut self, item: &hir::Item, mut lookup_fields: F) where
-        F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
+        F: for<'fcx> FnMut(&FnCtxt<'fcx, 'tcx, 'tcx>) -> Vec<AdtVariant<'tcx>>,
     {
         self.with_item_fcx(item, |fcx, this| {
             let variants = lookup_fields(fcx);
@@ -332,7 +332,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_where_clauses<'fcx>(&mut self,
-                                 fcx: &FnCtxt<'fcx,'tcx>,
+                                 fcx: &FnCtxt<'fcx,'tcx, 'tcx>,
                                  span: Span,
                                  predicates: &ty::InstantiatedPredicates<'tcx>)
     {
@@ -350,7 +350,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_fn_or_method<'fcx>(&mut self,
-                                fcx: &FnCtxt<'fcx,'tcx>,
+                                fcx: &FnCtxt<'fcx,'tcx, 'tcx>,
                                 span: Span,
                                 fty: &ty::BareFnTy<'tcx>,
                                 predicates: &ty::InstantiatedPredicates<'tcx>,
@@ -380,7 +380,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     }
 
     fn check_method_receiver<'fcx>(&mut self,
-                                   fcx: &FnCtxt<'fcx,'tcx>,
+                                   fcx: &FnCtxt<'fcx,'tcx, 'tcx>,
                                    span: Span,
                                    method: &ty::Method<'tcx>,
                                    free_id_outlive: CodeExtent,
@@ -554,7 +554,7 @@ struct AdtField<'tcx> {
     span: Span,
 }
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, 'tcx> {
 fn struct_variant(&self, struct_def: &hir::VariantData) -> AdtVariant<'tcx> {
     let fields =
         struct_def.fields().iter()
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 16e9297ec15..d1d653df034 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -19,7 +19,7 @@ use hir::pat_util;
 use rustc::ty::{self, Ty, TyCtxt, MethodCall, MethodCallee};
 use rustc::ty::adjustment;
 use rustc::ty::fold::{TypeFolder,TypeFoldable};
-use rustc::infer;
+use rustc::infer::{InferCtxt, FixupError};
 use write_substs_to_tcx;
 use write_ty_to_tcx;
 
@@ -34,7 +34,7 @@ use rustc::hir;
 ///////////////////////////////////////////////////////////////////////////
 // Entry point functions
 
-impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
+impl<'a, 'tcx> FnCtxt<'a, 'tcx, '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);
@@ -74,16 +74,16 @@ pub fn resolve_type_vars_in_fn(&self, decl: &hir::FnDecl, blk: &hir::Block) {
 // there, it applies a few ad-hoc checks that were not convenient to
 // do elsewhere.
 
-struct WritebackCx<'cx, 'tcx: 'cx> {
-    fcx: &'cx FnCtxt<'cx, 'tcx>,
+struct WritebackCx<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
+    fcx: &'cx FnCtxt<'cx, 'gcx, 'tcx>,
 }
 
-impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
-    fn new(fcx: &'cx FnCtxt<'cx, 'tcx>) -> WritebackCx<'cx, 'tcx> {
+impl<'cx, 'tcx> WritebackCx<'cx, 'tcx, 'tcx> {
+    fn new(fcx: &'cx FnCtxt<'cx, 'tcx, 'tcx>) -> WritebackCx<'cx, 'tcx, 'tcx> {
         WritebackCx { fcx: fcx }
     }
 
-    fn tcx(&self) -> TyCtxt<'cx, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'cx, 'tcx, 'tcx> {
         self.fcx.tcx()
     }
 
@@ -134,7 +134,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, '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> {
+impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx, '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> {
     }
 }
 
-impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
+impl<'cx, 'tcx> WritebackCx<'cx, 'tcx, 'tcx> {
     fn visit_upvar_borrow_map(&self) {
         if self.fcx.writeback_errors.get() {
             return;
@@ -379,7 +379,7 @@ enum ResolveReason {
 }
 
 impl ResolveReason {
-    fn span(&self, tcx: TyCtxt) -> Span {
+    fn span<'a, 'tcx>(&self, tcx: TyCtxt<'a, 'tcx, 'tcx>) -> Span {
         match *self {
             ResolvingExpr(s) => s,
             ResolvingLocal(s) => s,
@@ -408,25 +408,25 @@ impl ResolveReason {
 // The Resolver. This is the type folding engine that detects
 // unresolved types and so forth.
 
-struct Resolver<'cx, 'tcx: 'cx> {
-    tcx: TyCtxt<'cx, 'tcx>,
-    infcx: &'cx infer::InferCtxt<'cx, 'tcx>,
+struct Resolver<'cx, 'gcx: 'cx+'tcx, 'tcx: 'cx> {
+    tcx: TyCtxt<'cx, 'gcx, 'tcx>,
+    infcx: &'cx InferCtxt<'cx, 'gcx, 'tcx>,
     writeback_errors: &'cx Cell<bool>,
     reason: ResolveReason,
 }
 
-impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
-    fn new(fcx: &'cx FnCtxt<'cx, 'tcx>,
+impl<'cx, 'tcx> Resolver<'cx, 'tcx, 'tcx> {
+    fn new(fcx: &'cx FnCtxt<'cx, 'tcx, 'tcx>,
            reason: ResolveReason)
-           -> Resolver<'cx, 'tcx>
+           -> Resolver<'cx, 'tcx, 'tcx>
     {
         Resolver::from_infcx(fcx.infcx(), &fcx.writeback_errors, reason)
     }
 
-    fn from_infcx(infcx: &'cx infer::InferCtxt<'cx, 'tcx>,
+    fn from_infcx(infcx: &'cx InferCtxt<'cx, 'tcx, 'tcx>,
                   writeback_errors: &'cx Cell<bool>,
                   reason: ResolveReason)
-                  -> Resolver<'cx, 'tcx>
+                  -> Resolver<'cx, 'tcx, 'tcx>
     {
         Resolver { infcx: infcx,
                    tcx: infcx.tcx,
@@ -434,7 +434,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
                    reason: reason }
     }
 
-    fn report_error(&self, e: infer::FixupError) {
+    fn report_error(&self, e: FixupError) {
         self.writeback_errors.set(true);
         if !self.tcx.sess.has_errors() {
             match self.reason {
@@ -480,8 +480,8 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
     }
 }
 
-impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx> {
-    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx> {
+impl<'cx, 'tcx> TypeFolder<'tcx> for Resolver<'cx, 'tcx, 'tcx> {
+    fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.tcx
     }
 
diff --git a/src/librustc_typeck/check_unused.rs b/src/librustc_typeck/check_unused.rs
index 7f3ff367994..c3538ace347 100644
--- a/src/librustc_typeck/check_unused.rs
+++ b/src/librustc_typeck/check_unused.rs
@@ -19,7 +19,7 @@ use rustc::hir;
 use rustc::hir::intravisit::Visitor;
 
 struct UnusedTraitImportVisitor<'a, 'tcx: 'a> {
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 impl<'a, 'tcx> UnusedTraitImportVisitor<'a, 'tcx> {
@@ -57,7 +57,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for UnusedTraitImportVisitor<'a, 'tcx> {
     }
 }
 
-pub fn check_crate(tcx: TyCtxt) {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let _task = tcx.dep_graph.in_task(DepNode::UnusedTraitCheck);
     let mut visitor = UnusedTraitImportVisitor { tcx: tcx };
     tcx.map.krate().visit_all_items(&mut visitor);
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index 95b7ce63e20..71450c84141 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -46,17 +46,17 @@ mod orphan;
 mod overlap;
 mod unsafety;
 
-struct CoherenceChecker<'a, 'tcx: 'a> {
-    crate_context: &'a CrateCtxt<'a, 'tcx>,
-    inference_context: InferCtxt<'a, 'tcx>,
+struct CoherenceChecker<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    crate_context: &'a CrateCtxt<'a, 'gcx>,
+    inference_context: InferCtxt<'a, 'gcx, 'tcx>,
     inherent_impls: RefCell<DefIdMap<Rc<RefCell<Vec<DefId>>>>>,
 }
 
-struct CoherenceCheckVisitor<'a, 'tcx: 'a> {
-    cc: &'a CoherenceChecker<'a, 'tcx>
+struct CoherenceCheckVisitor<'a, 'gcx: 'a+'tcx, 'tcx: 'a> {
+    cc: &'a CoherenceChecker<'a, 'gcx, 'tcx>
 }
 
-impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
+impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx, 'tcx> {
     fn visit_item(&mut self, item: &Item) {
         if let ItemImpl(..) = item.node {
             self.cc.check_implementation(item)
@@ -64,7 +64,7 @@ impl<'a, 'tcx, 'v> intravisit::Visitor<'v> for CoherenceCheckVisitor<'a, 'tcx> {
     }
 }
 
-impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
+impl<'a, 'tcx> CoherenceChecker<'a, 'tcx, 'tcx> {
 
 // Returns the def ID of the base type, if there is one.
 fn get_base_type_def_id(&self, span: Span, ty: Ty<'tcx>) -> Option<DefId> {
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 7426b5ce277..d9ad0322202 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -21,13 +21,13 @@ use rustc::dep_graph::DepNode;
 use rustc::hir::intravisit;
 use rustc::hir;
 
-pub fn check(tcx: TyCtxt) {
+pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut orphan = OrphanChecker { tcx: tcx };
     tcx.visit_all_items_in_krate(DepNode::CoherenceOrphanCheck, &mut orphan);
 }
 
 struct OrphanChecker<'cx, 'tcx:'cx> {
-    tcx: TyCtxt<'cx, 'tcx>
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>
 }
 
 impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index d71ca657b81..a1af84d620f 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -23,7 +23,7 @@ use rustc::hir::intravisit;
 use util::nodemap::DefIdMap;
 use lint;
 
-pub fn check(tcx: TyCtxt) {
+pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut overlap = OverlapChecker { tcx: tcx,
                                        default_impls: DefIdMap() };
 
@@ -33,7 +33,7 @@ pub fn check(tcx: TyCtxt) {
 }
 
 struct OverlapChecker<'cx, 'tcx:'cx> {
-    tcx: TyCtxt<'cx, 'tcx>,
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>,
 
     // maps from a trait def-id to an impl id
     default_impls: DefIdMap<ast::NodeId>,
@@ -44,8 +44,9 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
         #[derive(Copy, Clone, PartialEq)]
         enum Namespace { Type, Value }
 
-        fn name_and_namespace(tcx: TyCtxt, item: &ty::ImplOrTraitItemId)
-                              -> (ast::Name, Namespace)
+        fn name_and_namespace<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                        item: &ty::ImplOrTraitItemId)
+                                        -> (ast::Name, Namespace)
         {
             let name = tcx.impl_or_trait_item(item.def_id()).name();
             (name, match *item {
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index d5912e224bc..53ec72abac0 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -15,13 +15,13 @@ use rustc::ty::TyCtxt;
 use rustc::hir::intravisit;
 use rustc::hir;
 
-pub fn check(tcx: TyCtxt) {
+pub fn check<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut orphan = UnsafetyChecker { tcx: tcx };
     tcx.map.krate().visit_all_items(&mut orphan);
 }
 
 struct UnsafetyChecker<'cx, 'tcx:'cx> {
-    tcx: TyCtxt<'cx, 'tcx>
+    tcx: TyCtxt<'cx, 'tcx, 'tcx>
 }
 
 impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index 4b1be8b9a5e..25ae23cd531 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -295,8 +295,8 @@ impl<'a,'tcx> ItemCtxt<'a,'tcx> {
     }
 }
 
-impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
-    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx> { self.ccx.tcx }
+impl<'a, 'tcx> AstConv<'tcx, 'tcx> for ItemCtxt<'a, 'tcx> {
+    fn tcx<'b>(&'b self) -> TyCtxt<'b, 'tcx, 'tcx> { self.ccx.tcx }
 
     fn get_item_type_scheme(&self, span: Span, id: DefId)
                             -> Result<ty::TypeScheme<'tcx>, ErrorReported>
@@ -353,16 +353,37 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
         }
     }
 
-        fn ty_infer(&self,
-                    _ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
-                    _substs: Option<&mut Substs<'tcx>>,
-                    _space: Option<ParamSpace>,
-                    span: Span) -> Ty<'tcx> {
+    fn get_free_substs(&self) -> Option<&Substs<'tcx>> {
+        None
+    }
+
+    fn ty_infer(&self,
+                _ty_param_def: Option<ty::TypeParameterDef<'tcx>>,
+                _substs: Option<&mut Substs<'tcx>>,
+                _space: Option<ParamSpace>,
+                span: Span) -> Ty<'tcx> {
         span_err!(self.tcx().sess, span, E0121,
                   "the type placeholder `_` is not allowed within types on item signatures");
         self.tcx().types.err
     }
 
+    fn projected_ty_from_poly_trait_ref(&self,
+                                        span: Span,
+                                        poly_trait_ref: ty::PolyTraitRef<'tcx>,
+                                        item_name: ast::Name)
+                                        -> Ty<'tcx>
+    {
+        if let Some(trait_ref) = self.tcx().no_late_bound_regions(&poly_trait_ref) {
+            self.projected_ty(span, trait_ref, item_name)
+        } else {
+            // no late-bound regions, we can just ignore the binder
+            span_err!(self.tcx().sess, span, E0212,
+                "cannot extract an associated type from a higher-ranked trait bound \
+                 in this context");
+            self.tcx().types.err
+        }
+    }
+
     fn projected_ty(&self,
                     _span: Span,
                     trait_ref: ty::TraitRef<'tcx>,
@@ -381,7 +402,7 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
 /// an `ItemCtxt`. This allows us to use multiple kinds of sources.
 trait GetTypeParameterBounds<'tcx> {
     fn get_type_parameter_bounds(&self,
-                                 astconv: &AstConv<'tcx>,
+                                 astconv: &AstConv<'tcx, 'tcx>,
                                  span: Span,
                                  node_id: ast::NodeId)
                                  -> Vec<ty::Predicate<'tcx>>;
@@ -392,7 +413,7 @@ impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
     where A : GetTypeParameterBounds<'tcx>, B : GetTypeParameterBounds<'tcx>
 {
     fn get_type_parameter_bounds(&self,
-                                 astconv: &AstConv<'tcx>,
+                                 astconv: &AstConv<'tcx, 'tcx>,
                                  span: Span,
                                  node_id: ast::NodeId)
                                  -> Vec<ty::Predicate<'tcx>>
@@ -406,7 +427,7 @@ impl<'a,'b,'tcx,A,B> GetTypeParameterBounds<'tcx> for (&'a A,&'b B)
 /// Empty set of bounds.
 impl<'tcx> GetTypeParameterBounds<'tcx> for () {
     fn get_type_parameter_bounds(&self,
-                                 _astconv: &AstConv<'tcx>,
+                                 _astconv: &AstConv<'tcx, 'tcx>,
                                  _span: Span,
                                  _node_id: ast::NodeId)
                                  -> Vec<ty::Predicate<'tcx>>
@@ -420,7 +441,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for () {
 /// from the trait/impl have been fully converted.
 impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
     fn get_type_parameter_bounds(&self,
-                                 astconv: &AstConv<'tcx>,
+                                 astconv: &AstConv<'tcx, 'tcx>,
                                  _span: Span,
                                  node_id: ast::NodeId)
                                  -> Vec<ty::Predicate<'tcx>>
@@ -459,7 +480,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ty::GenericPredicates<'tcx> {
 /// bounds for a type parameter `X` if `X::Foo` is used.
 impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
     fn get_type_parameter_bounds(&self,
-                                 astconv: &AstConv<'tcx>,
+                                 astconv: &AstConv<'tcx, 'tcx>,
                                  _: Span,
                                  node_id: ast::NodeId)
                                  -> Vec<ty::Predicate<'tcx>>
@@ -498,7 +519,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for hir::Generics {
 /// parameter with id `param_id`. We use this so as to avoid running
 /// `ast_ty_to_ty`, because we want to avoid triggering an all-out
 /// conversion of the type to avoid inducing unnecessary cycles.
-fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx>,
+fn is_param<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
                       ast_ty: &hir::Ty,
                       param_id: ast::NodeId)
                       -> bool
@@ -1664,7 +1685,7 @@ fn ty_generic_predicates_for_fn<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 }
 
 // Add the Sized bound, unless the type parameter is marked as `?Sized`.
-fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
+fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                            bounds: &mut ty::BuiltinBounds,
                            ast_bounds: &[hir::TyParamBound],
                            span: Span)
@@ -2008,7 +2029,7 @@ enum SizedByDefault { Yes, No, }
 /// Translate the AST's notion of ty param bounds (which are an enum consisting of a newtyped Ty or
 /// a region) to ty's notion of ty param bounds, which can either be user-defined traits, or the
 /// built-in trait (formerly known as kind): Send.
-fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
+fn compute_bounds<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                         param_ty: ty::Ty<'tcx>,
                         ast_bounds: &[hir::TyParamBound],
                         sized_by_default: SizedByDefault,
@@ -2038,7 +2059,7 @@ fn compute_bounds<'tcx>(astconv: &AstConv<'tcx>,
 /// because this can be anywhere from 0 predicates (`T:?Sized` adds no
 /// predicates) to 1 (`T:Foo`) to many (`T:Bar<X=i32>` adds `T:Bar`
 /// and `<T as Bar>::X == i32`).
-fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
+fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                                param_ty: Ty<'tcx>,
                                bound: &hir::TyParamBound)
                                -> Vec<ty::Predicate<'tcx>>
@@ -2063,7 +2084,7 @@ fn predicates_from_bound<'tcx>(astconv: &AstConv<'tcx>,
     }
 }
 
-fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
+fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                              param_ty: Ty<'tcx>,
                              trait_ref: &hir::PolyTraitRef,
                              projections: &mut Vec<ty::PolyProjectionPredicate<'tcx>>)
@@ -2076,7 +2097,7 @@ fn conv_poly_trait_ref<'tcx>(astconv: &AstConv<'tcx>,
                                         projections)
 }
 
-fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx>,
+fn conv_param_bounds<'a,'tcx>(astconv: &AstConv<'tcx, 'tcx>,
                               span: Span,
                               param_ty: ty::Ty<'tcx>,
                               ast_bounds: &[hir::TyParamBound])
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index a86595bbc4e..0fb751f3700 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -149,7 +149,7 @@ pub struct CrateCtxt<'a, 'tcx: 'a> {
     /// Note that these cycles can cross multiple items.
     pub stack: RefCell<Vec<collect::AstConvRequest>>,
 
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
 }
 
 // Functions that write types into the node type table
@@ -193,7 +193,7 @@ fn require_c_abi_if_variadic(tcx: TyCtxt,
 }
 
 fn require_same_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
-                                maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx>>,
+                                maybe_infcx: Option<&infer::InferCtxt<'a, 'tcx, 'tcx>>,
                                 span: Span,
                                 t1: Ty<'tcx>,
                                 t2: Ty<'tcx>,
@@ -329,7 +329,9 @@ fn check_for_entry_fn(ccx: &CrateCtxt) {
     }
 }
 
-pub fn check_crate(tcx: TyCtxt, trait_map: hir::TraitMap) -> CompileResult {
+pub fn check_crate<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             trait_map: hir::TraitMap)
+                             -> CompileResult {
     let time_passes = tcx.sess.time_passes();
     let ccx = CrateCtxt {
         trait_map: trait_map,
diff --git a/src/librustc_typeck/variance/constraints.rs b/src/librustc_typeck/variance/constraints.rs
index 7ee56e7cb00..d4d16a60789 100644
--- a/src/librustc_typeck/variance/constraints.rs
+++ b/src/librustc_typeck/variance/constraints.rs
@@ -127,7 +127,7 @@ fn is_lifetime(map: &hir_map::Map, param_id: ast::NodeId) -> bool {
 }
 
 impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
-    fn tcx(&self) -> TyCtxt<'a, 'tcx> {
+    fn tcx(&self) -> TyCtxt<'a, 'tcx, 'tcx> {
         self.terms_cx.tcx
     }
 
diff --git a/src/librustc_typeck/variance/mod.rs b/src/librustc_typeck/variance/mod.rs
index 08d61d19fe6..13ed6cf7641 100644
--- a/src/librustc_typeck/variance/mod.rs
+++ b/src/librustc_typeck/variance/mod.rs
@@ -27,7 +27,7 @@ mod solve;
 /// Code for transforming variances.
 mod xform;
 
-pub fn infer_variance(tcx: TyCtxt) {
+pub fn infer_variance<'a, 'tcx>(tcx: TyCtxt<'a, 'tcx, 'tcx>) {
     let mut arena = arena::TypedArena::new();
     let terms_cx = terms::determine_parameters_to_be_inferred(tcx, &mut arena);
     let constraints_cx = constraints::add_constraints_from_crate(terms_cx);
diff --git a/src/librustc_typeck/variance/terms.rs b/src/librustc_typeck/variance/terms.rs
index 270f79e7ed7..d9e7e8cbf7d 100644
--- a/src/librustc_typeck/variance/terms.rs
+++ b/src/librustc_typeck/variance/terms.rs
@@ -59,7 +59,7 @@ impl<'a> fmt::Debug for VarianceTerm<'a> {
 // The first pass over the crate simply builds up the set of inferreds.
 
 pub struct TermsContext<'a, 'tcx: 'a> {
-    pub tcx: TyCtxt<'a, 'tcx>,
+    pub tcx: TyCtxt<'a, 'tcx, 'tcx>,
     pub arena: &'a TypedArena<VarianceTerm<'a>>,
 
     pub empty_variances: Rc<ty::ItemVariances>,
@@ -98,7 +98,7 @@ pub struct InferredInfo<'a> {
 }
 
 pub fn determine_parameters_to_be_inferred<'a, 'tcx>(
-    tcx: TyCtxt<'a, 'tcx>,
+    tcx: TyCtxt<'a, 'tcx, 'tcx>,
     arena: &'a mut TypedArena<VarianceTerm<'a>>)
     -> TermsContext<'a, 'tcx>
 {
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index b592d94fff3..c9df54dfef2 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -68,8 +68,8 @@ pub fn try_inline(cx: &DocContext, id: ast::NodeId, into: Option<ast::Name>)
     })
 }
 
-fn try_inline_def(cx: &DocContext, tcx: TyCtxt,
-                  def: Def) -> Option<Vec<clean::Item>> {
+fn try_inline_def<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            def: Def) -> Option<Vec<clean::Item>> {
     let mut ret = Vec::new();
     let did = def.def_id();
     let inner = match def {
@@ -130,8 +130,8 @@ fn try_inline_def(cx: &DocContext, tcx: TyCtxt,
     Some(ret)
 }
 
-pub fn load_attrs(cx: &DocContext, tcx: TyCtxt,
-                  did: DefId) -> Vec<clean::Attribute> {
+pub fn load_attrs<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            did: DefId) -> Vec<clean::Attribute> {
     tcx.get_attrs(did).iter().map(|a| a.clean(cx)).collect()
 }
 
@@ -150,8 +150,8 @@ pub fn record_extern_fqn(cx: &DocContext, did: DefId, kind: clean::TypeKind) {
     }
 }
 
-pub fn build_external_trait(cx: &DocContext, tcx: TyCtxt,
-                            did: DefId) -> clean::Trait {
+pub fn build_external_trait<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                      did: DefId) -> clean::Trait {
     let def = tcx.lookup_trait_def(did);
     let trait_items = tcx.trait_items(did).clean(cx);
     let predicates = tcx.lookup_predicates(did);
@@ -166,7 +166,8 @@ pub fn build_external_trait(cx: &DocContext, tcx: TyCtxt,
     }
 }
 
-fn build_external_function(cx: &DocContext, tcx: TyCtxt, did: DefId) -> clean::Function {
+fn build_external_function<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                     did: DefId) -> clean::Function {
     let t = tcx.lookup_item_type(did);
     let (decl, style, abi) = match t.ty.sty {
         ty::TyFnDef(_, _, ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi),
@@ -189,7 +190,8 @@ fn build_external_function(cx: &DocContext, tcx: TyCtxt, did: DefId) -> clean::F
     }
 }
 
-fn build_struct(cx: &DocContext, tcx: TyCtxt, did: DefId) -> clean::Struct {
+fn build_struct<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          did: DefId) -> clean::Struct {
     let t = tcx.lookup_item_type(did);
     let predicates = tcx.lookup_predicates(did);
     let variant = tcx.lookup_adt_def(did).struct_variant();
@@ -207,7 +209,8 @@ fn build_struct(cx: &DocContext, tcx: TyCtxt, did: DefId) -> clean::Struct {
     }
 }
 
-fn build_type(cx: &DocContext, tcx: TyCtxt, did: DefId) -> clean::ItemEnum {
+fn build_type<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                        did: DefId) -> clean::ItemEnum {
     let t = tcx.lookup_item_type(did);
     let predicates = tcx.lookup_predicates(did);
     match t.ty.sty {
@@ -227,9 +230,9 @@ fn build_type(cx: &DocContext, tcx: TyCtxt, did: DefId) -> clean::ItemEnum {
     }, false)
 }
 
-pub fn build_impls(cx: &DocContext,
-                   tcx: TyCtxt,
-                   did: DefId) -> Vec<clean::Item> {
+pub fn build_impls<'a, 'tcx>(cx: &DocContext,
+                             tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                             did: DefId) -> Vec<clean::Item> {
     tcx.populate_inherent_implementations_for_type_if_necessary(did);
     let mut impls = Vec::new();
 
@@ -252,9 +255,9 @@ pub fn build_impls(cx: &DocContext,
             populate_impls(cx, tcx, item.def, &mut impls);
         }
 
-        fn populate_impls(cx: &DocContext, tcx: TyCtxt,
-                          def: cstore::DefLike,
-                          impls: &mut Vec<clean::Item>) {
+        fn populate_impls<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                                    def: cstore::DefLike,
+                                    impls: &mut Vec<clean::Item>) {
             match def {
                 cstore::DlImpl(did) => build_impl(cx, tcx, did, impls),
                 cstore::DlDef(Def::Mod(did)) => {
@@ -270,10 +273,10 @@ pub fn build_impls(cx: &DocContext,
     impls
 }
 
-pub fn build_impl(cx: &DocContext,
-                  tcx: TyCtxt,
-                  did: DefId,
-                  ret: &mut Vec<clean::Item>) {
+pub fn build_impl<'a, 'tcx>(cx: &DocContext,
+                            tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                            did: DefId,
+                            ret: &mut Vec<clean::Item>) {
     if !cx.renderinfo.borrow_mut().inlined.insert(did) {
         return
     }
@@ -441,8 +444,8 @@ pub fn build_impl(cx: &DocContext,
     });
 }
 
-fn build_module(cx: &DocContext, tcx: TyCtxt,
-                did: DefId) -> clean::Module {
+fn build_module<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          did: DefId) -> clean::Module {
     let mut items = Vec::new();
     fill_in(cx, tcx, did, &mut items);
     return clean::Module {
@@ -450,8 +453,8 @@ fn build_module(cx: &DocContext, tcx: TyCtxt,
         is_crate: false,
     };
 
-    fn fill_in(cx: &DocContext, tcx: TyCtxt, did: DefId,
-               items: &mut Vec<clean::Item>) {
+    fn fill_in<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         did: DefId, items: &mut Vec<clean::Item>) {
         // If we're reexporting a reexport it may actually reexport something in
         // two namespaces, so the target may be listed twice. Make sure we only
         // visit each node at most once.
@@ -476,8 +479,8 @@ fn build_module(cx: &DocContext, tcx: TyCtxt,
     }
 }
 
-fn build_const(cx: &DocContext, tcx: TyCtxt,
-               did: DefId) -> clean::Constant {
+fn build_const<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                         did: DefId) -> clean::Constant {
     let (expr, ty) = lookup_const_by_id(tcx, did, None).unwrap_or_else(|| {
         panic!("expected lookup_const_by_id to succeed for {:?}", did);
     });
@@ -491,9 +494,9 @@ fn build_const(cx: &DocContext, tcx: TyCtxt,
     }
 }
 
-fn build_static(cx: &DocContext, tcx: TyCtxt,
-                did: DefId,
-                mutable: bool) -> clean::Static {
+fn build_static<'a, 'tcx>(cx: &DocContext, tcx: TyCtxt<'a, 'tcx, 'tcx>,
+                          did: DefId,
+                          mutable: bool) -> clean::Static {
     clean::Static {
         type_: tcx.lookup_item_type(did).ty.clean(cx),
         mutability: if mutable {clean::Mutable} else {clean::Immutable},
diff --git a/src/librustdoc/core.rs b/src/librustdoc/core.rs
index 245ebcdfe4f..895c0bb8490 100644
--- a/src/librustdoc/core.rs
+++ b/src/librustdoc/core.rs
@@ -42,7 +42,7 @@ pub use rustc::session::search_paths::SearchPaths;
 
 /// Are we generating documentation (`Typed`) or tests (`NotTyped`)?
 pub enum MaybeTyped<'a, 'tcx: 'a> {
-    Typed(TyCtxt<'a, 'tcx>),
+    Typed(TyCtxt<'a, 'tcx, 'tcx>),
     NotTyped(&'a session::Session)
 }
 
@@ -74,14 +74,14 @@ impl<'b, 'tcx> DocContext<'b, 'tcx> {
         }
     }
 
-    pub fn tcx_opt<'a>(&'a self) -> Option<TyCtxt<'a, 'tcx>> {
+    pub fn tcx_opt<'a>(&'a self) -> Option<TyCtxt<'a, 'tcx, 'tcx>> {
         match self.maybe_typed {
             Typed(tcx) => Some(tcx),
             NotTyped(_) => None
         }
     }
 
-    pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx> {
+    pub fn tcx<'a>(&'a self) -> TyCtxt<'a, 'tcx, 'tcx> {
         let tcx_opt = self.tcx_opt();
         tcx_opt.expect("tcx not present")
     }
diff --git a/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs b/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs
index 79226515ce3..0abf71ba444 100644
--- a/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs
+++ b/src/test/run-pass-fulldeps/auxiliary/dummy_mir_pass.rs
@@ -30,7 +30,8 @@ struct Pass;
 
 impl transform::Pass for Pass {}
 impl<'tcx> MirPass<'tcx> for Pass {
-    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx>, _: MirSource, mir: &mut Mir<'tcx>) {
+    fn run_pass<'a>(&mut self, _: TyCtxt<'a, 'tcx, 'tcx>,
+                    _: MirSource, mir: &mut Mir<'tcx>) {
         Visitor.visit_mir(mir)
     }
 }