]> git.lizzy.rs Git - rust.git/blobdiff - src/librustc/middle/typeck/check/mod.rs
auto merge of #18984 : sheroze1123/rust/fix17574, r=bstrie
[rust.git] / src / librustc / middle / typeck / check / mod.rs
index 0d1ebac54c1530122407c41a6f192cb8bb8a8005..85d2f573615b7029bc94cc83efe499793e2d2c39 100644 (file)
 
 */
 
+pub use self::LvaluePreference::*;
+pub use self::DerefArgs::*;
+pub use self::Expectation::*;
+use self::IsBinopAssignment::*;
+use self::TupleArgumentsFlag::*;
 
-use driver::session::Session;
+use session::Session;
 use middle::const_eval;
 use middle::def;
 use middle::lang_items::IteratorItem;
 use middle::mem_categorization;
 use middle::pat_util::pat_id_map;
 use middle::pat_util;
+use middle::region::CodeExtent;
 use middle::subst;
 use middle::subst::{Subst, Substs, VecPerParamSpace, ParamSpace};
 use middle::traits;
 use middle::ty::{FnSig, VariantInfo};
 use middle::ty::{Polytype};
 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
-use middle::ty;
+use middle::ty::{mod, Ty};
+use middle::ty::liberate_late_bound_regions;
 use middle::ty_fold::TypeFolder;
 use middle::typeck::astconv::AstConv;
 use middle::typeck::astconv::{ast_region_to_region, ast_ty_to_ty};
 use middle::typeck::astconv;
 use middle::typeck::check::_match::pat_ctxt;
-use middle::typeck::check::method::{AutoderefReceiver};
-use middle::typeck::check::method::{CheckTraitsAndInherentMethods};
-use middle::typeck::check::regionmanip::replace_late_bound_regions;
 use middle::typeck::CrateCtxt;
 use middle::typeck::infer;
 use middle::typeck::rscope::RegionScope;
 pub mod demand;
 pub mod method;
 pub mod wf;
+mod closure;
 
 /// Fields that are part of a `FnCtxt` which are inherited by
 /// closures defined within the function.  For example:
 /// share the inherited fields.
 pub struct Inherited<'a, 'tcx: 'a> {
     infcx: infer::InferCtxt<'a, 'tcx>,
-    locals: RefCell<NodeMap<ty::t>>,
-    param_env: ty::ParameterEnvironment,
+    locals: RefCell<NodeMap<Ty<'tcx>>>,
+    param_env: ty::ParameterEnvironment<'tcx>,
 
     // Temporary tables:
-    node_types: RefCell<NodeMap<ty::t>>,
-    item_substs: RefCell<NodeMap<ty::ItemSubsts>>,
-    adjustments: RefCell<NodeMap<ty::AutoAdjustment>>,
-    method_map: MethodMap,
+    node_types: RefCell<NodeMap<Ty<'tcx>>>,
+    item_substs: RefCell<NodeMap<ty::ItemSubsts<'tcx>>>,
+    adjustments: RefCell<NodeMap<ty::AutoAdjustment<'tcx>>>,
+    method_map: MethodMap<'tcx>,
     upvar_borrow_map: RefCell<ty::UpvarBorrowMap>,
-    unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure>>,
-    object_cast_map: ObjectCastMap,
+    unboxed_closures: RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>>,
+    object_cast_map: ObjectCastMap<'tcx>,
 
     // A mapping from each fn's id to its signature, with all bound
     // regions replaced with free ones. Unlike the other tables, this
     // one is never copied into the tcx: it is only used by regionck.
-    fn_sig_map: RefCell<NodeMap<Vec<ty::t>>>,
+    fn_sig_map: RefCell<NodeMap<Vec<Ty<'tcx>>>>,
 
     // A set of constraints that regionck must validate. Each
     // constraint has the form `T:'a`, meaning "some type `T` must
@@ -198,29 +203,29 @@ pub struct Inherited<'a, 'tcx: 'a> {
     // regionck to be sure that it has found *all* the region
     // obligations (otherwise, it's easy to fail to walk to a
     // particular node-id).
-    region_obligations: RefCell<NodeMap<Vec<RegionObligation>>>,
+    region_obligations: RefCell<NodeMap<Vec<RegionObligation<'tcx>>>>,
 
     // Tracks trait obligations incurred during this function body.
-    fulfillment_cx: RefCell<traits::FulfillmentContext>,
+    fulfillment_cx: RefCell<traits::FulfillmentContext<'tcx>>,
 }
 
-struct RegionObligation {
+struct RegionObligation<'tcx> {
     sub_region: ty::Region,
-    sup_type: ty::t,
-    origin: infer::SubregionOrigin,
+    sup_type: Ty<'tcx>,
+    origin: infer::SubregionOrigin<'tcx>,
 }
 
 /// When type-checking an expression, we propagate downward
 /// whatever type hint we are able in the form of an `Expectation`.
-enum Expectation {
+enum Expectation<'tcx> {
     /// We know nothing about what type this expression should have.
     NoExpectation,
 
     /// This expression should have the type given (or some subtype)
-    ExpectHasType(ty::t),
+    ExpectHasType(Ty<'tcx>),
 
-    /// This expression will be cast to the `ty::t`
-    ExpectCastableToType(ty::t),
+    /// This expression will be cast to the `Ty`
+    ExpectCastableToType(Ty<'tcx>),
 }
 
 #[deriving(Clone)]
@@ -279,7 +284,7 @@ pub struct FnCtxt<'a, 'tcx: 'a> {
     // expects the types within the function to be consistent.
     err_count_on_creation: uint,
 
-    ret_ty: ty::FnOutput,
+    ret_ty: ty::FnOutput<'tcx>,
 
     ps: RefCell<FnStyleState>,
 
@@ -292,37 +297,38 @@ impl<'a, 'tcx> mem_categorization::Typer<'tcx> for FnCtxt<'a, 'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> {
         self.ccx.tcx
     }
-    fn node_ty(&self, id: ast::NodeId) -> McResult<ty::t> {
+    fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
         Ok(self.node_ty(id))
     }
     fn node_method_ty(&self, method_call: typeck::MethodCall)
-                      -> Option<ty::t> {
+                      -> Option<Ty<'tcx>> {
         self.inh.method_map.borrow().get(&method_call).map(|m| m.ty)
     }
-    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment>> {
+    fn adjustments<'a>(&'a self) -> &'a RefCell<NodeMap<ty::AutoAdjustment<'tcx>>> {
         &self.inh.adjustments
     }
     fn is_method_call(&self, id: ast::NodeId) -> bool {
         self.inh.method_map.borrow().contains_key(&typeck::MethodCall::expr(id))
     }
-    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<ast::NodeId> {
+    fn temporary_scope(&self, rvalue_id: ast::NodeId) -> Option<CodeExtent> {
         self.tcx().temporary_scope(rvalue_id)
     }
     fn upvar_borrow(&self, upvar_id: ty::UpvarId) -> ty::UpvarBorrow {
-        self.inh.upvar_borrow_map.borrow().get_copy(&upvar_id)
+        self.inh.upvar_borrow_map.borrow()[upvar_id].clone()
     }
     fn capture_mode(&self, closure_expr_id: ast::NodeId)
                     -> ast::CaptureClause {
         self.ccx.tcx.capture_mode(closure_expr_id)
     }
-    fn unboxed_closures<'a>(&'a self) -> &'a RefCell<DefIdMap<ty::UnboxedClosure>> {
+    fn unboxed_closures<'a>(&'a self)
+                        -> &'a RefCell<DefIdMap<ty::UnboxedClosure<'tcx>>> {
         &self.inh.unboxed_closures
     }
 }
 
 impl<'a, 'tcx> Inherited<'a, 'tcx> {
     fn new(tcx: &'a ty::ctxt<'tcx>,
-           param_env: ty::ParameterEnvironment)
+           param_env: ty::ParameterEnvironment<'tcx>)
            -> Inherited<'a, 'tcx> {
         Inherited {
             infcx: infer::new_infer_ctxt(tcx),
@@ -345,7 +351,7 @@ fn new(tcx: &'a ty::ctxt<'tcx>,
 // Used by check_const and check_enum_variants
 pub fn blank_fn_ctxt<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
                                inh: &'a Inherited<'a, 'tcx>,
-                               rty: ty::FnOutput,
+                               rty: ty::FnOutput<'tcx>,
                                body_id: ast::NodeId)
                                -> FnCtxt<'a, 'tcx> {
     FnCtxt {
@@ -391,17 +397,17 @@ pub fn check_item_types(ccx: &CrateCtxt) {
     ccx.tcx.sess.abort_if_errors();
 }
 
-fn check_bare_fn(ccx: &CrateCtxt,
-                 decl: &ast::FnDecl,
-                 body: &ast::Block,
-                 id: ast::NodeId,
-                 fty: ty::t,
-                 param_env: ty::ParameterEnvironment) {
+fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                           decl: &ast::FnDecl,
+                           body: &ast::Block,
+                           id: ast::NodeId,
+                           fty: Ty<'tcx>,
+                           param_env: ty::ParameterEnvironment<'tcx>) {
     // Compute the fty from point of view of inside fn
     // (replace any type-scheme with a type)
     let fty = fty.subst(ccx.tcx, &param_env.free_substs);
 
-    match ty::get(fty).sty {
+    match fty.sty {
         ty::ty_bare_fn(ref fn_ty) => {
             let inh = Inherited::new(ccx.tcx, param_env);
             let fcx = check_fn(ccx, fn_ty.fn_style, id, &fn_ty.sig,
@@ -422,7 +428,7 @@ struct GatherLocalsVisitor<'a, 'tcx: 'a> {
 }
 
 impl<'a, 'tcx> GatherLocalsVisitor<'a, 'tcx> {
-    fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<ty::t>) -> ty::t {
+    fn assign(&mut self, _span: Span, nid: ast::NodeId, ty_opt: Option<Ty<'tcx>>) -> Ty<'tcx> {
         match ty_opt {
             None => {
                 // infer the variable's type
@@ -450,7 +456,7 @@ fn visit_local(&mut self, local: &ast::Local) {
         debug!("Local variable {} is assigned type {}",
                self.fcx.pat_to_string(&*local.pat),
                self.fcx.infcx().ty_to_string(
-                   self.fcx.inh.locals.borrow().get_copy(&local.id)));
+                   self.fcx.inh.locals.borrow()[local.id].clone()));
         visit::walk_local(self, local);
     }
 
@@ -467,7 +473,7 @@ fn visit_pat(&mut self, p: &ast::Pat) {
                     debug!("Pattern binding {} is assigned to {} with type {}",
                            token::get_ident(path1.node),
                            self.fcx.infcx().ty_to_string(
-                               self.fcx.inh.locals.borrow().get_copy(&p.id)),
+                               self.fcx.inh.locals.borrow()[p.id].clone()),
                            var_ty.repr(self.fcx.tcx()));
                 }
             _ => {}
@@ -504,7 +510,7 @@ fn visit_item(&mut self, _: &ast::Item) { }
 fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
                       fn_style: ast::FnStyle,
                       fn_style_id: ast::NodeId,
-                      fn_sig: &ty::FnSig,
+                      fn_sig: &ty::FnSig<'tcx>,
                       decl: &ast::FnDecl,
                       fn_id: ast::NodeId,
                       body: &ast::Block,
@@ -525,9 +531,7 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
 
     // First, we have to replace any bound regions in the fn type with free ones.
     // The free region references will be bound the node_id of the body block.
-    let (_, fn_sig) = replace_late_bound_regions(tcx, fn_sig.binder_id, fn_sig, |br| {
-        ty::ReFree(ty::FreeRegion {scope_id: body.id, bound_region: br})
-    });
+    let fn_sig = liberate_late_bound_regions(tcx, CodeExtent::from_node_id(body.id), fn_sig);
 
     let arg_tys = fn_sig.inputs.as_slice();
     let ret_ty = fn_sig.output;
@@ -550,13 +554,13 @@ fn check_fn<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>,
     };
 
     // Remember return type so that regionck can access it later.
-    let mut fn_sig_tys: Vec<ty::t> =
+    let mut fn_sig_tys: Vec<Ty> =
         arg_tys.iter()
         .map(|&ty| ty)
         .collect();
 
     if let ty::FnConverging(ret_ty) = ret_ty {
-        fcx.require_type_is_sized(ret_ty, decl.output.span, traits::ReturnType);
+        fcx.require_type_is_sized(ret_ty, decl.output.span(), traits::ReturnType);
         fn_sig_tys.push(ret_ty);
     }
 
@@ -718,9 +722,9 @@ pub fn check_item(ccx: &CrateCtxt, it: &ast::Item) {
     }
 }
 
-fn check_method_body(ccx: &CrateCtxt,
-                     item_generics: &ty::Generics,
-                     method: &ast::Method) {
+fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                               item_generics: &ty::Generics<'tcx>,
+                               method: &ast::Method) {
     /*!
      * Type checks a method body.
      *
@@ -737,6 +741,12 @@ fn check_method_body(ccx: &CrateCtxt,
     let param_env = ParameterEnvironment::for_item(ccx.tcx, method.id);
 
     let fty = ty::node_id_to_type(ccx.tcx, method.id);
+    debug!("fty (raw): {}", fty.repr(ccx.tcx));
+
+    let body_id = method.pe_body().id;
+    let fty = liberate_late_bound_regions(
+        ccx.tcx, CodeExtent::from_node_id(body_id), &ty::bind(fty)).value;
+    debug!("fty (liberated): {}", fty.repr(ccx.tcx));
 
     check_bare_fn(ccx,
                   &*method.pe_fn_decl(),
@@ -746,11 +756,11 @@ fn check_method_body(ccx: &CrateCtxt,
                   param_env);
 }
 
-fn check_impl_items_against_trait(ccx: &CrateCtxt,
-                                  impl_span: Span,
-                                  ast_trait_ref: &ast::TraitRef,
-                                  impl_trait_ref: &ty::TraitRef,
-                                  impl_items: &[ast::ImplItem]) {
+fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                            impl_span: Span,
+                                            ast_trait_ref: &ast::TraitRef,
+                                            impl_trait_ref: &ty::TraitRef<'tcx>,
+                                            impl_items: &[ast::ImplItem]) {
     // Locate trait methods
     let tcx = ccx.tcx;
     let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
@@ -781,7 +791,7 @@ fn check_impl_items_against_trait(ccx: &CrateCtxt,
                                                     impl_method.span,
                                                     impl_method.pe_body().id,
                                                     &**trait_method_ty,
-                                                    &impl_trait_ref.substs);
+                                                    impl_trait_ref);
                             }
                             _ => {
                                 // This is span_bug as it should have already been
@@ -921,16 +931,43 @@ trait `{}`",
  * - trait_m: the method in the trait
  * - trait_to_impl_substs: the substitutions used on the type of the trait
  */
-fn compare_impl_method(tcx: &ty::ctxt,
-                       impl_m: &ty::Method,
-                       impl_m_span: Span,
-                       impl_m_body_id: ast::NodeId,
-                       trait_m: &ty::Method,
-                       trait_to_impl_substs: &subst::Substs) {
-    debug!("compare_impl_method(trait_to_impl_substs={})",
-           trait_to_impl_substs.repr(tcx));
+fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                             impl_m: &ty::Method<'tcx>,
+                             impl_m_span: Span,
+                             impl_m_body_id: ast::NodeId,
+                             trait_m: &ty::Method<'tcx>,
+                             impl_trait_ref: &ty::TraitRef<'tcx>) {
+    debug!("compare_impl_method(impl_trait_ref={})",
+           impl_trait_ref.repr(tcx));
+
+    let impl_m_body_scope = CodeExtent::from_node_id(impl_m_body_id);
+
+    // The impl's trait ref may bind late-bound regions from the impl.
+    // Liberate them and assign them the scope of the method body.
+    //
+    // An example would be:
+    //
+    //     impl<'a> Foo<&'a T> for &'a U { ... }
+    //
+    // Here, the region parameter `'a` is late-bound, so the
+    // trait reference associated with the impl will be
+    //
+    //     for<'a> Foo<&'a T>
+    //
+    // liberating will convert this into:
+    //
+    //     Foo<&'A T>
+    //
+    // where `'A` is the `ReFree` version of `'a`.
+    let impl_trait_ref = liberate_late_bound_regions(tcx, impl_m_body_scope, impl_trait_ref);
+
+    debug!("impl_trait_ref (liberated) = {}",
+           impl_trait_ref.repr(tcx));
+
     let infcx = infer::new_infer_ctxt(tcx);
 
+    let trait_to_impl_substs = &impl_trait_ref.substs;
+
     // Try to give more informative error messages about self typing
     // mismatches.  Note that any mismatch will also be detected
     // below, where we construct a canonical function type that
@@ -994,22 +1031,23 @@ fn compare_impl_method(tcx: &ty::ctxt,
 
     // This code is best explained by example. Consider a trait:
     //
-    //     trait Trait<T> {
-    //          fn method<'a,M>(t: T, m: &'a M) -> Self;
+    //     trait Trait<'t,T> {
+    //          fn method<'a,M>(t: &'t T, m: &'a M) -> Self;
     //     }
     //
     // And an impl:
     //
-    //     impl<'i, U> Trait<&'i U> for Foo {
-    //          fn method<'b,N>(t: &'i U, m: &'b N) -> Foo;
+    //     impl<'i, 'j, U> Trait<'j, &'i U> for Foo {
+    //          fn method<'b,N>(t: &'j &'i U, m: &'b N) -> Foo;
     //     }
     //
     // We wish to decide if those two method types are compatible.
     //
-    // We start out with trait_to_impl_substs, that maps the trait type
-    // parameters to impl type parameters:
+    // We start out with trait_to_impl_substs, that maps the trait
+    // type parameters to impl type parameters. This is taken from the
+    // impl trait reference:
     //
-    //     trait_to_impl_substs = {T => &'i U, Self => Foo}
+    //     trait_to_impl_substs = {'t => 'j, T => &'i U, Self => Foo}
     //
     // We create a mapping `dummy_substs` that maps from the impl type
     // parameters to fresh types and regions. For type parameters,
@@ -1064,6 +1102,7 @@ fn compare_impl_method(tcx: &ty::ctxt,
     if !check_region_bounds_on_impl_method(tcx,
                                            impl_m_span,
                                            impl_m,
+                                           impl_m_body_scope,
                                            &trait_m.generics,
                                            &impl_m.generics,
                                            &trait_to_skol_substs,
@@ -1071,15 +1110,50 @@ fn compare_impl_method(tcx: &ty::ctxt,
         return;
     }
 
-    // Check bounds.
-    let it = trait_m.generics.types.get_slice(subst::FnSpace).iter()
-        .zip(impl_m.generics.types.get_slice(subst::FnSpace).iter());
-    for (i, (trait_param_def, impl_param_def)) in it.enumerate() {
+    // Check bounds. Note that the bounds from the impl may reference
+    // late-bound regions declared on the impl, so liberate those.
+    // This requires two artificial binding scopes -- one for the impl,
+    // and one for the method.
+    //
+    // An example would be:
+    //
+    //     trait Foo<T> { fn method<U:Bound<T>>() { ... } }
+    //
+    //     impl<'a> Foo<&'a T> for &'a U {
+    //         fn method<U:Bound<&'a T>>() { ... }
+    //     }
+    //
+    // Here, the region parameter `'a` is late-bound, so in the bound
+    // `Bound<&'a T>`, the lifetime `'a` will be late-bound with a
+    // depth of 3 (it is nested within 3 binders: the impl, method,
+    // and trait-ref itself). So when we do the liberation, we have
+    // two introduce two `ty::bind` scopes, one for the impl and one
+    // the method.
+    //
+    // The only late-bounded regions that can possibly appear here are
+    // from the impl, not the method. This is because region
+    // parameters declared on the method which appear in a type bound
+    // would be early bound. On the trait side, there can be no
+    // late-bound lifetimes because trait definitions do not introduce
+    // a late region binder.
+    let trait_bounds =
+        trait_m.generics.types.get_slice(subst::FnSpace).iter()
+        .map(|trait_param_def| &trait_param_def.bounds);
+    let impl_bounds =
+        impl_m.generics.types.get_slice(subst::FnSpace).iter()
+        .map(|impl_param_def|
+             liberate_late_bound_regions(
+                 tcx,
+                 impl_m_body_scope,
+                 &ty::bind(ty::bind(impl_param_def.bounds.clone()))).value.value);
+    for (i, (trait_param_bounds, impl_param_bounds)) in
+        trait_bounds.zip(impl_bounds).enumerate()
+    {
         // Check that the impl does not require any builtin-bounds
         // that the trait does not guarantee:
         let extra_bounds =
-            impl_param_def.bounds.builtin_bounds -
-            trait_param_def.bounds.builtin_bounds;
+            impl_param_bounds.builtin_bounds -
+            trait_param_bounds.builtin_bounds;
         if !extra_bounds.is_empty() {
             span_err!(tcx.sess, impl_m_span, E0051,
                 "in method `{}`, type parameter {} requires `{}`, \
@@ -1096,31 +1170,32 @@ fn compare_impl_method(tcx: &ty::ctxt,
         //
         // FIXME(pcwalton): We could be laxer here regarding sub- and super-
         // traits, but I doubt that'll be wanted often, so meh.
-        for impl_trait_bound in impl_param_def.bounds.trait_bounds.iter() {
+        for impl_trait_bound in impl_param_bounds.trait_bounds.iter() {
             debug!("compare_impl_method(): impl-trait-bound subst");
             let impl_trait_bound =
                 impl_trait_bound.subst(tcx, &impl_to_skol_substs);
 
-            let mut ok = false;
-            for trait_bound in trait_param_def.bounds.trait_bounds.iter() {
-                debug!("compare_impl_method(): trait-bound subst");
-                let trait_bound =
-                    trait_bound.subst(tcx, &trait_to_skol_substs);
-                let infcx = infer::new_infer_ctxt(tcx);
-                match infer::mk_sub_trait_refs(&infcx,
-                                               true,
-                                               infer::Misc(impl_m_span),
-                                               trait_bound,
-                                               impl_trait_bound.clone()) {
-                    Ok(_) => {
-                        ok = true;
-                        break
-                    }
-                    Err(_) => continue,
-                }
-            }
+            // There may be late-bound regions from the impl in the
+            // impl's bound, so "liberate" those. Note that the
+            // trait_to_skol_substs is derived from the impl's
+            // trait-ref, and the late-bound regions appearing there
+            // have already been liberated, so the result should match
+            // up.
+
+            let found_match_in_trait =
+                trait_param_bounds.trait_bounds.iter().any(|trait_bound| {
+                    debug!("compare_impl_method(): trait-bound subst");
+                    let trait_bound =
+                        trait_bound.subst(tcx, &trait_to_skol_substs);
+                    let infcx = infer::new_infer_ctxt(tcx);
+                    infer::mk_sub_trait_refs(&infcx,
+                                             true,
+                                             infer::Misc(impl_m_span),
+                                             trait_bound,
+                                             impl_trait_bound.clone()).is_ok()
+                });
 
-            if !ok {
+            if !found_match_in_trait {
                 span_err!(tcx.sess, impl_m_span, E0052,
                     "in method `{}`, type parameter {} requires bound `{}`, which is not \
                      required by the corresponding type parameter in the trait declaration",
@@ -1131,9 +1206,12 @@ fn compare_impl_method(tcx: &ty::ctxt,
         }
     }
 
-    // Compute skolemized form of impl and trait method tys.
+    // Compute skolemized form of impl and trait method tys. Note
+    // that we must liberate the late-bound regions from the impl.
     let impl_fty = ty::mk_bare_fn(tcx, impl_m.fty.clone());
     let impl_fty = impl_fty.subst(tcx, &impl_to_skol_substs);
+    let impl_fty = liberate_late_bound_regions(
+        tcx, impl_m_body_scope, &ty::bind(impl_fty)).value;
     let trait_fty = ty::mk_bare_fn(tcx, trait_m.fty.clone());
     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
 
@@ -1165,14 +1243,15 @@ fn compare_impl_method(tcx: &ty::ctxt,
     // parameters.
     infcx.resolve_regions_and_report_errors();
 
-    fn check_region_bounds_on_impl_method(tcx: &ty::ctxt,
-                                          span: Span,
-                                          impl_m: &ty::Method,
-                                          trait_generics: &ty::Generics,
-                                          impl_generics: &ty::Generics,
-                                          trait_to_skol_substs: &Substs,
-                                          impl_to_skol_substs: &Substs)
-                                          -> bool
+    fn check_region_bounds_on_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                                span: Span,
+                                                impl_m: &ty::Method<'tcx>,
+                                                impl_m_body_scope: CodeExtent,
+                                                trait_generics: &ty::Generics<'tcx>,
+                                                impl_generics: &ty::Generics<'tcx>,
+                                                trait_to_skol_substs: &Substs<'tcx>,
+                                                impl_to_skol_substs: &Substs<'tcx>)
+                                                -> bool
     {
         /*!
 
@@ -1213,9 +1292,13 @@ fn method2<'b>() { .. case 2, could be ok .. }
 
         debug!("check_region_bounds_on_impl_method: \
                trait_generics={} \
-               impl_generics={}",
+               impl_generics={} \
+               trait_to_skol_substs={} \
+               impl_to_skol_substs={}",
                trait_generics.repr(tcx),
-               impl_generics.repr(tcx));
+               impl_generics.repr(tcx),
+               trait_to_skol_substs.repr(tcx),
+               impl_to_skol_substs.repr(tcx));
 
         // Must have same number of early-bound lifetime parameters.
         // Unfortunately, if the user screws up the bounds, then this
@@ -1246,6 +1329,16 @@ fn method2<'b>() { .. case 2, could be ok .. }
             let impl_bounds =
                 impl_param.bounds.subst(tcx, impl_to_skol_substs);
 
+            // The bounds may reference late-bound regions from the
+            // impl declaration. In that case, we want to replace
+            // those with the liberated variety so as to match the
+            // versions appearing in the `trait_to_skol_substs`.
+            // There are two-levels of binder to be aware of: the
+            // impl, and the method.
+            let impl_bounds =
+                ty::liberate_late_bound_regions(
+                    tcx, impl_m_body_scope, &ty::bind(ty::bind(impl_bounds))).value.value;
+
             debug!("check_region_bounds_on_impl_method: \
                    trait_param={} \
                    impl_param={} \
@@ -1347,7 +1440,7 @@ fn check_cast(fcx: &FnCtxt,
         fcx.type_error_message(span, |actual| {
             format!("cast to unsized type: `{}` as `{}`", actual, tstr)
         }, t_e, None);
-        match ty::get(t_e).sty {
+        match t_e.sty {
             ty::ty_rptr(_, ty::mt { mutbl: mt, .. }) => {
                 let mtstr = match mt {
                     ast::MutMutable => "mut ",
@@ -1416,19 +1509,19 @@ fn check_cast(fcx: &FnCtxt,
         // casts from C-like enums are allowed
     } else if t_1_is_char {
         let t_e = fcx.infcx().shallow_resolve(t_e);
-        if ty::get(t_e).sty != ty::ty_uint(ast::TyU8) {
+        if t_e.sty != ty::ty_uint(ast::TyU8) {
             fcx.type_error_message(span, |actual| {
                 format!("only `u8` can be cast as \
                          `char`, not `{}`", actual)
             }, t_e, None);
         }
-    } else if ty::get(t_1).sty == ty::ty_bool {
+    } else if t_1.sty == ty::ty_bool {
         span_err!(fcx.tcx().sess, span, E0054,
             "cannot cast as `bool`, compare with zero instead");
     } else if ty::type_is_region_ptr(t_e) && ty::type_is_unsafe_ptr(t_1) {
-        fn types_compatible(fcx: &FnCtxt, sp: Span,
-                            t1: ty::t, t2: ty::t) -> bool {
-            match ty::get(t1).sty {
+        fn types_compatible<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
+                                      t1: Ty<'tcx>, t2: Ty<'tcx>) -> bool {
+            match t1.sty {
                 ty::ty_vec(_, Some(_)) => {}
                 _ => return false
             }
@@ -1456,7 +1549,7 @@ fn types_compatible(fcx: &FnCtxt, sp: Span,
 
         /* this cast is only allowed from &[T, ..n] to *T or
         &T to *T. */
-        match (&ty::get(t_e).sty, &ty::get(t_1).sty) {
+        match (&t_e.sty, &t_1.sty) {
             (&ty::ty_rptr(_, ty::mt { ty: mt1, mutbl: ast::MutImmutable }),
              &ty::ty_ptr(ty::mt { ty: mt2, mutbl: ast::MutImmutable }))
             if types_compatible(fcx, e.span, mt1, mt2) => {
@@ -1492,29 +1585,29 @@ fn types_compatible(fcx: &FnCtxt, sp: Span,
 impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     fn tcx<'a>(&'a self) -> &'a ty::ctxt<'tcx> { self.ccx.tcx }
 
-    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype {
+    fn get_item_ty(&self, id: ast::DefId) -> ty::Polytype<'tcx> {
         ty::lookup_item_type(self.tcx(), id)
     }
 
-    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef> {
+    fn get_trait_def(&self, id: ast::DefId) -> Rc<ty::TraitDef<'tcx>> {
         ty::lookup_trait_def(self.tcx(), id)
     }
 
-    fn ty_infer(&self, _span: Span) -> ty::t {
+    fn ty_infer(&self, _span: Span) -> Ty<'tcx> {
         self.infcx().next_ty_var()
     }
 
-    fn associated_types_of_trait_are_valid(&self, _: ty::t, _: ast::DefId)
+    fn associated_types_of_trait_are_valid(&self, _: Ty, _: ast::DefId)
                                            -> bool {
         false
     }
 
     fn associated_type_binding(&self,
                                span: Span,
-                               _: Option<ty::t>,
+                               _: Option<Ty<'tcx>>,
                                _: ast::DefId,
                                _: ast::DefId)
-                               -> ty::t {
+                               -> Ty<'tcx> {
         self.tcx().sess.span_err(span, "unsupported associated type binding");
         ty::mk_err()
     }
@@ -1554,7 +1647,7 @@ pub fn tag(&self) -> String {
         format!("{}", self as *const FnCtxt)
     }
 
-    pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
+    pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> Ty<'tcx> {
         match self.inh.locals.borrow().get(&nid) {
             Some(&t) => t,
             None => {
@@ -1569,13 +1662,13 @@ pub fn local_ty(&self, span: Span, nid: ast::NodeId) -> ty::t {
     pub fn default_diverging_type_variables_to_nil(&self) {
         for (_, &ref ty) in self.inh.node_types.borrow_mut().iter_mut() {
             if self.infcx().type_var_diverges(self.infcx().resolve_type_vars_if_possible(*ty)) {
-                demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil());
+                demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
             }
         }
     }
 
     #[inline]
-    pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
+    pub fn write_ty(&self, node_id: ast::NodeId, ty: Ty<'tcx>) {
         debug!("write_ty({}, {}) in fcx {}",
                node_id, ppaux::ty_to_string(self.tcx(), ty), self.tag());
         self.inh.node_types.borrow_mut().insert(node_id, ty);
@@ -1583,13 +1676,13 @@ pub fn write_ty(&self, node_id: ast::NodeId, ty: ty::t) {
 
     pub fn write_object_cast(&self,
                              key: ast::NodeId,
-                             trait_ref: Rc<ty::TraitRef>) {
+                             trait_ref: Rc<ty::TraitRef<'tcx>>) {
         debug!("write_object_cast key={} trait_ref={}",
                key, trait_ref.repr(self.tcx()));
         self.inh.object_cast_map.borrow_mut().insert(key, trait_ref);
     }
 
-    pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
+    pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts<'tcx>) {
         if !substs.substs.is_noop() {
             debug!("write_substs({}, {}) in fcx {}",
                    node_id,
@@ -1600,15 +1693,6 @@ pub fn write_substs(&self, node_id: ast::NodeId, substs: ty::ItemSubsts) {
         }
     }
 
-    pub fn write_ty_substs(&self,
-                           node_id: ast::NodeId,
-                           ty: ty::t,
-                           substs: ty::ItemSubsts) {
-        let ty = ty.subst(self.tcx(), &substs.substs);
-        self.write_ty(node_id, ty);
-        self.write_substs(node_id, substs);
-    }
-
     pub fn write_autoderef_adjustment(&self,
                                       node_id: ast::NodeId,
                                       span: Span,
@@ -1626,8 +1710,8 @@ pub fn write_autoderef_adjustment(&self,
     pub fn write_adjustment(&self,
                             node_id: ast::NodeId,
                             span: Span,
-                            adj: ty::AutoAdjustment) {
-        debug!("write_adjustment(node_id={}, adj={})", node_id, adj);
+                            adj: ty::AutoAdjustment<'tcx>) {
+        debug!("write_adjustment(node_id={}, adj={})", node_id, adj.repr(self.tcx()));
 
         if adj.is_identity() {
             return;
@@ -1645,7 +1729,7 @@ pub fn write_adjustment(&self,
 
     fn register_adjustment_obligations(&self,
                                        span: Span,
-                                       adj: &ty::AutoAdjustment) {
+                                       adj: &ty::AutoAdjustment<'tcx>) {
         match *adj {
             ty::AdjustAddEnv(..) => { }
             ty::AdjustDerefRef(ref d_r) => {
@@ -1661,7 +1745,7 @@ fn register_adjustment_obligations(&self,
 
     fn register_autoref_obligations(&self,
                                     span: Span,
-                                    autoref: &ty::AutoRef) {
+                                    autoref: &ty::AutoRef<'tcx>) {
         match *autoref {
             ty::AutoUnsize(ref unsize) => {
                 self.register_unsize_obligations(span, unsize);
@@ -1681,7 +1765,7 @@ fn register_autoref_obligations(&self,
 
     fn register_unsize_obligations(&self,
                                    span: Span,
-                                   unsize: &ty::UnsizeKind) {
+                                   unsize: &ty::UnsizeKind<'tcx>) {
         debug!("register_unsize_obligations: unsize={}", unsize);
 
         match *unsize {
@@ -1691,12 +1775,13 @@ fn register_unsize_obligations(&self,
             }
             ty::UnsizeVtable(ref ty_trait, self_ty) => {
                 vtable::check_object_safety(self.tcx(), ty_trait, span);
+
                 // If the type is `Foo+'a`, ensures that the type
                 // being cast to `Foo+'a` implements `Foo`:
                 vtable::register_object_cast_obligations(self,
-                                                          span,
-                                                          ty_trait,
-                                                          self_ty);
+                                                         span,
+                                                         ty_trait,
+                                                         self_ty);
 
                 // If the type is `Foo+'a`, ensures that the type
                 // being cast to `Foo+'a` outlives `'a`:
@@ -1706,17 +1791,21 @@ fn register_unsize_obligations(&self,
         }
     }
 
-    pub fn instantiate_item_type(&self,
-                                 span: Span,
-                                 def_id: ast::DefId)
-                                 -> TypeAndSubsts
+    pub fn instantiate_type(&self,
+                            span: Span,
+                            def_id: ast::DefId)
+                            -> TypeAndSubsts<'tcx>
     {
         /*!
          * Returns the type of `def_id` with all generics replaced by
          * by fresh type/region variables. Also returns the
          * substitution from the type parameters on `def_id` to the
-         * fresh variables.  Registers any trait obligations specified
+         * fresh variables. Registers any trait obligations specified
          * on `def_id` at the same time.
+         *
+         * Note that function is only intended to be used with types
+         * (notably, not impls). This is because it doesn't do any
+         * instantiation of late-bound regions.
          */
 
         let polytype =
@@ -1725,12 +1814,14 @@ pub fn instantiate_item_type(&self,
             self.infcx().fresh_substs_for_generics(
                 span,
                 &polytype.generics);
+        let bounds =
+            polytype.generics.to_bounds(self.tcx(), &substs);
         self.add_obligations_for_parameters(
             traits::ObligationCause::new(
                 span,
                 traits::ItemObligation(def_id)),
             &substs,
-            &polytype.generics);
+            &bounds);
         let monotype =
             polytype.ty.subst(self.tcx(), &substs);
 
@@ -1741,16 +1832,16 @@ pub fn instantiate_item_type(&self,
     }
 
     pub fn write_nil(&self, node_id: ast::NodeId) {
-        self.write_ty(node_id, ty::mk_nil());
+        self.write_ty(node_id, ty::mk_nil(self.tcx()));
     }
     pub fn write_error(&self, node_id: ast::NodeId) {
         self.write_ty(node_id, ty::mk_err());
     }
 
     pub fn require_type_meets(&self,
-                              ty: ty::t,
+                              ty: Ty<'tcx>,
                               span: Span,
-                              code: traits::ObligationCauseCode,
+                              code: traits::ObligationCauseCode<'tcx>,
                               bound: ty::BuiltinBound)
     {
         let obligation = traits::obligation_for_builtin_bound(
@@ -1765,22 +1856,22 @@ pub fn require_type_meets(&self,
     }
 
     pub fn require_type_is_sized(&self,
-                                 ty: ty::t,
+                                 ty: Ty<'tcx>,
                                  span: Span,
-                                 code: traits::ObligationCauseCode)
+                                 code: traits::ObligationCauseCode<'tcx>)
     {
         self.require_type_meets(ty, span, code, ty::BoundSized);
     }
 
     pub fn require_expr_have_sized_type(&self,
                                         expr: &ast::Expr,
-                                        code: traits::ObligationCauseCode)
+                                        code: traits::ObligationCauseCode<'tcx>)
     {
         self.require_type_is_sized(self.expr_ty(expr), expr.span, code);
     }
 
     pub fn register_obligation(&self,
-                               obligation: traits::Obligation)
+                               obligation: traits::Obligation<'tcx>)
     {
         debug!("register_obligation({})",
                obligation.repr(self.tcx()));
@@ -1790,12 +1881,12 @@ pub fn register_obligation(&self,
             .register_obligation(self.tcx(), obligation);
     }
 
-    pub fn to_ty(&self, ast_t: &ast::Ty) -> ty::t {
+    pub fn to_ty(&self, ast_t: &ast::Ty) -> Ty<'tcx> {
         let t = ast_ty_to_ty(self, self.infcx(), ast_t);
 
         let mut bounds_checker = wf::BoundsChecker::new(self,
                                                         ast_t.span,
-                                                        self.body_id,
+                                                        CodeExtent::from_node_id(self.body_id),
                                                         None);
         bounds_checker.check_ty(t);
 
@@ -1806,7 +1897,7 @@ pub fn pat_to_string(&self, pat: &ast::Pat) -> String {
         pat.repr(self.tcx())
     }
 
-    pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
+    pub fn expr_ty(&self, ex: &ast::Expr) -> Ty<'tcx> {
         match self.inh.node_types.borrow().get(&ex.id) {
             Some(&t) => t,
             None => {
@@ -1816,7 +1907,7 @@ pub fn expr_ty(&self, ex: &ast::Expr) -> ty::t {
         }
     }
 
-    pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> ty::t {
+    pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
         /*!
          * Fetch type of `expr` after applying adjustments that
          * have been recorded in the fcx.
@@ -1829,8 +1920,8 @@ pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> ty::t {
 
     pub fn adjust_expr_ty(&self,
                           expr: &ast::Expr,
-                          adjustment: Option<&ty::AutoAdjustment>)
-                          -> ty::t
+                          adjustment: Option<&ty::AutoAdjustment<'tcx>>)
+                          -> Ty<'tcx>
     {
         /*!
          * Apply `adjustment` to the type of `expr`
@@ -1848,7 +1939,7 @@ pub fn adjust_expr_ty(&self,
                                                        .map(|method| method.ty))
     }
 
-    pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
+    pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
         match self.inh.node_types.borrow().get(&id) {
             Some(&t) => t,
             None => {
@@ -1860,13 +1951,13 @@ pub fn node_ty(&self, id: ast::NodeId) -> ty::t {
         }
     }
 
-    pub fn item_substs<'a>(&'a self) -> Ref<'a, NodeMap<ty::ItemSubsts>> {
+    pub fn item_substs<'a>(&'a self) -> Ref<'a, NodeMap<ty::ItemSubsts<'tcx>>> {
         self.inh.item_substs.borrow()
     }
 
     pub fn opt_node_ty_substs(&self,
                               id: ast::NodeId,
-                              f: |&ty::ItemSubsts|) {
+                              f: |&ty::ItemSubsts<'tcx>|) {
         match self.inh.item_substs.borrow().get(&id) {
             Some(s) => { f(s) }
             None => { }
@@ -1876,27 +1967,27 @@ pub fn opt_node_ty_substs(&self,
     pub fn mk_subty(&self,
                     a_is_expected: bool,
                     origin: infer::TypeOrigin,
-                    sub: ty::t,
-                    sup: ty::t)
-                    -> Result<(), ty::type_err> {
+                    sub: Ty<'tcx>,
+                    sup: Ty<'tcx>)
+                    -> Result<(), ty::type_err<'tcx>> {
         infer::mk_subty(self.infcx(), a_is_expected, origin, sub, sup)
     }
 
-    pub fn can_mk_subty(&self, sub: ty::t, sup: ty::t)
-                        -> Result<(), ty::type_err> {
+    pub fn can_mk_subty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>)
+                        -> Result<(), ty::type_err<'tcx>> {
         infer::can_mk_subty(self.infcx(), sub, sup)
     }
 
-    pub fn can_mk_eqty(&self, sub: ty::t, sup: ty::t)
-                       -> Result<(), ty::type_err> {
+    pub fn can_mk_eqty(&self, sub: Ty<'tcx>, sup: Ty<'tcx>)
+                       -> Result<(), ty::type_err<'tcx>> {
         infer::can_mk_eqty(self.infcx(), sub, sup)
     }
 
     pub fn mk_assignty(&self,
                        expr: &ast::Expr,
-                       sub: ty::t,
-                       sup: ty::t)
-                       -> Result<(), ty::type_err> {
+                       sub: Ty<'tcx>,
+                       sup: Ty<'tcx>)
+                       -> Result<(), ty::type_err<'tcx>> {
         match infer::mk_coercety(self.infcx(),
                                  false,
                                  infer::ExprAssignable(expr.span),
@@ -1914,14 +2005,14 @@ pub fn mk_assignty(&self,
     pub fn mk_eqty(&self,
                    a_is_expected: bool,
                    origin: infer::TypeOrigin,
-                   sub: ty::t,
-                   sup: ty::t)
-                   -> Result<(), ty::type_err> {
+                   sub: Ty<'tcx>,
+                   sup: Ty<'tcx>)
+                   -> Result<(), ty::type_err<'tcx>> {
         infer::mk_eqty(self.infcx(), a_is_expected, origin, sub, sup)
     }
 
     pub fn mk_subr(&self,
-                   origin: infer::SubregionOrigin,
+                   origin: infer::SubregionOrigin<'tcx>,
                    sub: ty::Region,
                    sup: ty::Region) {
         infer::mk_subr(self.infcx(), origin, sub, sup)
@@ -1930,22 +2021,22 @@ pub fn mk_subr(&self,
     pub fn type_error_message(&self,
                               sp: Span,
                               mk_msg: |String| -> String,
-                              actual_ty: ty::t,
-                              err: Option<&ty::type_err>) {
+                              actual_ty: Ty<'tcx>,
+                              err: Option<&ty::type_err<'tcx>>) {
         self.infcx().type_error_message(sp, mk_msg, actual_ty, err);
     }
 
     pub fn report_mismatched_types(&self,
                                    sp: Span,
-                                   e: ty::t,
-                                   a: ty::t,
-                                   err: &ty::type_err) {
+                                   e: Ty<'tcx>,
+                                   a: Ty<'tcx>,
+                                   err: &ty::type_err<'tcx>) {
         self.infcx().report_mismatched_types(sp, e, a, err)
     }
 
     pub fn register_region_obligation(&self,
-                                      origin: infer::SubregionOrigin,
-                                      ty: ty::t,
+                                      origin: infer::SubregionOrigin<'tcx>,
+                                      ty: Ty<'tcx>,
                                       r: ty::Region)
     {
         /*!
@@ -1955,8 +2046,8 @@ pub fn register_region_obligation(&self,
 
         let mut region_obligations = self.inh.region_obligations.borrow_mut();
         let region_obligation = RegionObligation { sub_region: r,
-                                  sup_type: ty,
-                                  origin: origin };
+                                                   sup_type: ty,
+                                                   origin: origin };
 
         match region_obligations.entry(self.body_id) {
             Vacant(entry) => { entry.set(vec![region_obligation]); },
@@ -1964,15 +2055,27 @@ pub fn register_region_obligation(&self,
         }
     }
 
+    pub fn add_default_region_param_bounds(&self,
+                                           substs: &Substs<'tcx>,
+                                           expr: &ast::Expr)
+    {
+        for &ty in substs.types.iter() {
+            let default_bound = ty::ReScope(CodeExtent::from_node_id(expr.id));
+            let origin = infer::RelateDefaultParamBound(expr.span, ty);
+            self.register_region_obligation(origin, ty, default_bound);
+        }
+    }
+
     pub fn add_obligations_for_parameters(&self,
-                                          cause: traits::ObligationCause,
-                                          substs: &Substs,
-                                          generics: &ty::Generics)
+                                          cause: traits::ObligationCause<'tcx>,
+                                          substs: &Substs<'tcx>,
+                                          generic_bounds: &ty::GenericBounds<'tcx>)
     {
         /*!
-         * Given a set of generic parameter definitions (`generics`)
-         * and the values provided for each of them (`substs`),
-         * creates and registers suitable region obligations.
+         * Given a fully substituted set of bounds (`generic_bounds`),
+         * and the values with which each type/region parameter was
+         * instantiated (`substs`), creates and registers suitable
+         * trait/region obligations.
          *
          * For example, if there is a function:
          *
@@ -1988,62 +2091,62 @@ pub fn add_obligations_for_parameters(&self,
          * locally.
          */
 
-        debug!("add_obligations_for_parameters(substs={}, generics={})",
+        assert!(!generic_bounds.has_escaping_regions());
+
+        debug!("add_obligations_for_parameters(substs={}, generic_bounds={})",
                substs.repr(self.tcx()),
-               generics.repr(self.tcx()));
+               generic_bounds.repr(self.tcx()));
 
-        self.add_trait_obligations_for_generics(cause, substs, generics);
-        self.add_region_obligations_for_generics(cause, substs, generics);
+        self.add_trait_obligations_for_generics(cause, substs, generic_bounds);
+        self.add_region_obligations_for_generics(cause, substs, generic_bounds);
     }
 
     fn add_trait_obligations_for_generics(&self,
-                                          cause: traits::ObligationCause,
-                                          substs: &Substs,
-                                          generics: &ty::Generics) {
+                                          cause: traits::ObligationCause<'tcx>,
+                                          substs: &Substs<'tcx>,
+                                          generic_bounds: &ty::GenericBounds<'tcx>) {
+        assert!(!generic_bounds.has_escaping_regions());
+        assert!(!substs.has_regions_escaping_depth(0));
+
         let obligations =
             traits::obligations_for_generics(self.tcx(),
                                              cause,
-                                             generics,
-                                             substs);
+                                             generic_bounds,
+                                             &substs.types);
         obligations.map_move(|o| self.register_obligation(o));
     }
 
     fn add_region_obligations_for_generics(&self,
-                                           cause: traits::ObligationCause,
-                                           substs: &Substs,
-                                           generics: &ty::Generics)
+                                           cause: traits::ObligationCause<'tcx>,
+                                           substs: &Substs<'tcx>,
+                                           generic_bounds: &ty::GenericBounds<'tcx>)
     {
-        assert_eq!(generics.types.iter().len(),
-                   substs.types.iter().len());
-        for (type_def, &type_param) in
-            generics.types.iter().zip(
+        assert!(!generic_bounds.has_escaping_regions());
+        assert_eq!(generic_bounds.types.iter().len(), substs.types.iter().len());
+
+        for (type_bounds, &type_param) in
+            generic_bounds.types.iter().zip(
                 substs.types.iter())
         {
-            let param_ty = ty::ParamTy { space: type_def.space,
-                                         idx: type_def.index,
-                                         def_id: type_def.def_id };
-            let bounds = type_def.bounds.subst(self.tcx(), substs);
             self.add_region_obligations_for_type_parameter(
-                cause.span, param_ty, &bounds, type_param);
+                cause.span, type_bounds, type_param);
         }
 
-        assert_eq!(generics.regions.iter().len(),
+        assert_eq!(generic_bounds.regions.iter().len(),
                    substs.regions().iter().len());
-        for (region_def, &region_param) in
-            generics.regions.iter().zip(
+        for (region_bounds, &region_param) in
+            generic_bounds.regions.iter().zip(
                 substs.regions().iter())
         {
-            let bounds = region_def.bounds.subst(self.tcx(), substs);
             self.add_region_obligations_for_region_parameter(
-                cause.span, bounds.as_slice(), region_param);
+                cause.span, region_bounds.as_slice(), region_param);
         }
     }
 
     fn add_region_obligations_for_type_parameter(&self,
                                                  span: Span,
-                                                 param_ty: ty::ParamTy,
-                                                 param_bound: &ty::ParamBounds,
-                                                 ty: ty::t)
+                                                 param_bound: &ty::ParamBounds<'tcx>,
+                                                 ty: Ty<'tcx>)
     {
         // For each declared region bound `T:r`, `T` must outlive `r`.
         let region_bounds =
@@ -2053,7 +2156,7 @@ fn add_region_obligations_for_type_parameter(&self,
                 param_bound.builtin_bounds,
                 param_bound.trait_bounds.as_slice());
         for &r in region_bounds.iter() {
-            let origin = infer::RelateParamBound(span, param_ty, ty);
+            let origin = infer::RelateParamBound(span, ty);
             self.register_region_obligation(origin, ty, r);
         }
     }
@@ -2078,11 +2181,12 @@ pub enum LvaluePreference {
     NoPreference
 }
 
-pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
-                    expr_id: Option<ast::NodeId>,
-                    mut lvalue_pref: LvaluePreference,
-                    should_stop: |ty::t, uint| -> Option<T>)
-                    -> (ty::t, uint, Option<T>) {
+pub fn autoderef<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
+                              base_ty: Ty<'tcx>,
+                              expr_id: Option<ast::NodeId>,
+                              mut lvalue_pref: LvaluePreference,
+                              should_stop: |Ty<'tcx>, uint| -> Option<T>)
+                              -> (Ty<'tcx>, uint, Option<T>) {
     /*!
      * Executes an autoderef loop for the type `t`. At each step, invokes
      * `should_stop` to decide whether to terminate the loop. Returns
@@ -2133,12 +2237,12 @@ pub fn autoderef<T>(fcx: &FnCtxt, sp: Span, base_ty: ty::t,
 }
 
 /// Attempts to resolve a call expression as an overloaded call.
-fn try_overloaded_call<'a>(fcx: &FnCtxt,
-                           call_expression: &ast::Expr,
-                           callee: &ast::Expr,
-                           callee_type: ty::t,
-                           args: &[&'a P<ast::Expr>])
-                           -> bool {
+fn try_overloaded_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                 call_expression: &ast::Expr,
+                                 callee: &ast::Expr,
+                                 callee_type: Ty<'tcx>,
+                                 args: &[&P<ast::Expr>])
+                                 -> bool {
     // Bail out if the callee is a bare function or a closure. We check those
     // manually.
     match *structure_of(fcx, callee.span, callee_type) {
@@ -2178,11 +2282,11 @@ fn try_overloaded_call<'a>(fcx: &FnCtxt,
         fcx.inh.method_map.borrow_mut().insert(method_call, method_callee);
         write_call(fcx, call_expression, output_type);
 
-        if !fcx.tcx().sess.features.borrow().overloaded_calls {
+        if !fcx.tcx().sess.features.borrow().unboxed_closures {
             span_err!(fcx.tcx().sess, call_expression.span, E0056,
                 "overloaded calls are experimental");
             span_help!(fcx.tcx().sess, call_expression.span,
-                "add `#![feature(overloaded_calls)]` to \
+                "add `#![feature(unboxed_closures)]` to \
                 the crate attributes to enable");
         }
 
@@ -2192,13 +2296,13 @@ fn try_overloaded_call<'a>(fcx: &FnCtxt,
     false
 }
 
-fn try_overloaded_deref(fcx: &FnCtxt,
-                        span: Span,
-                        method_call: Option<MethodCall>,
-                        base_expr: Option<&ast::Expr>,
-                        base_ty: ty::t,
-                        lvalue_pref: LvaluePreference)
-                        -> Option<ty::mt>
+fn try_overloaded_deref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                  span: Span,
+                                  method_call: Option<MethodCall>,
+                                  base_expr: Option<&ast::Expr>,
+                                  base_ty: Ty<'tcx>,
+                                  lvalue_pref: LvaluePreference)
+                                  -> Option<ty::mt<'tcx>>
 {
     // Try DerefMut first, if preferred.
     let method = match (lvalue_pref, fcx.tcx().lang_items.deref_mut_trait()) {
@@ -2223,10 +2327,10 @@ fn try_overloaded_deref(fcx: &FnCtxt,
     make_overloaded_lvalue_return_type(fcx, method_call, method)
 }
 
-fn make_overloaded_lvalue_return_type(fcx: &FnCtxt,
-                                      method_call: Option<MethodCall>,
-                                      method: Option<MethodCallee>)
-                                      -> Option<ty::mt>
+fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                                method_call: Option<MethodCall>,
+                                                method: Option<MethodCallee<'tcx>>)
+                                                -> Option<ty::mt<'tcx>>
 {
     /*!
      * For the overloaded lvalue expressions (`*x`, `x[3]`), the trait
@@ -2259,13 +2363,17 @@ fn make_overloaded_lvalue_return_type(fcx: &FnCtxt,
     }
 }
 
-fn autoderef_for_index<T>(fcx: &FnCtxt,
-                          base_expr: &ast::Expr,
-                          base_ty: ty::t,
-                          lvalue_pref: LvaluePreference,
-                          step: |ty::t, ty::AutoDerefRef| -> Option<T>)
-                          -> Option<T>
+fn autoderef_for_index<'a, 'tcx, T>(fcx: &FnCtxt<'a, 'tcx>,
+                                    base_expr: &ast::Expr,
+                                    base_ty: Ty<'tcx>,
+                                    lvalue_pref: LvaluePreference,
+                                    step: |Ty<'tcx>, ty::AutoDerefRef<'tcx>| -> Option<T>)
+                                    -> Option<T>
 {
+    // FIXME(#18741) -- this is almost but not quite the same as the
+    // autoderef that normal method probing does. They could likely be
+    // consolidated.
+
     let (ty, autoderefs, final_mt) =
         autoderef(fcx, base_expr.span, base_ty, Some(base_expr.id), lvalue_pref, |adj_ty, idx| {
             let autoderefref = ty::AutoDerefRef { autoderefs: idx, autoref: None };
@@ -2278,7 +2386,7 @@ fn autoderef_for_index<T>(fcx: &FnCtxt,
 
     // After we have fully autoderef'd, if the resulting type is [T, ..n], then
     // do a final unsized coercion to yield [T].
-    match ty::get(ty).sty {
+    match ty.sty {
         ty::ty_vec(element_ty, Some(n)) => {
             let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
             let autoderefref = ty::AutoDerefRef {
@@ -2293,15 +2401,15 @@ fn autoderef_for_index<T>(fcx: &FnCtxt,
     }
 }
 
-fn try_overloaded_slice(fcx: &FnCtxt,
-                        method_call: MethodCall,
-                        expr: &ast::Expr,
-                        base_expr: &ast::Expr,
-                        base_ty: ty::t,
-                        start_expr: &Option<P<ast::Expr>>,
-                        end_expr: &Option<P<ast::Expr>>,
-                        mutbl: ast::Mutability)
-                        -> Option<ty::t> // return type is result of slice
+fn try_overloaded_slice<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                  method_call: MethodCall,
+                                  expr: &ast::Expr,
+                                  base_expr: &ast::Expr,
+                                  base_ty: Ty<'tcx>,
+                                  start_expr: &Option<P<ast::Expr>>,
+                                  end_expr: &Option<P<ast::Expr>>,
+                                  mutbl: ast::Mutability)
+                                  -> Option<Ty<'tcx>> // return type is result of slice
 {
     /*!
      * Autoderefs `base_expr`, looking for a `Slice` impl. If it
@@ -2349,16 +2457,17 @@ fn try_overloaded_slice(fcx: &FnCtxt,
     })
 }
 
-fn try_overloaded_slice_step(fcx: &FnCtxt,
-                             method_call: MethodCall,
-                             expr: &ast::Expr,
-                             base_expr: &ast::Expr,
-                             base_ty: ty::t, // autoderef'd type
-                             autoderefref: ty::AutoDerefRef,
-                             mutbl: ast::Mutability,
-                             start_expr: &Option<P<ast::Expr>>,
-                             end_expr: &Option<P<ast::Expr>>)
-                             -> Option<ty::t> // result type is type of method being called
+fn try_overloaded_slice_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                       method_call: MethodCall,
+                                       expr: &ast::Expr,
+                                       base_expr: &ast::Expr,
+                                       base_ty: Ty<'tcx>, // autoderef'd type
+                                       autoderefref: ty::AutoDerefRef<'tcx>,
+                                       mutbl: ast::Mutability,
+                                       start_expr: &Option<P<ast::Expr>>,
+                                       end_expr: &Option<P<ast::Expr>>)
+                                       // result type is type of method being called
+                                       -> Option<Ty<'tcx>>
 {
     /*!
      * Checks for a `Slice` (or `SliceMut`) impl at the relevant level
@@ -2422,14 +2531,14 @@ fn try_overloaded_slice_step(fcx: &FnCtxt,
     })
 }
 
-fn try_index_step(fcx: &FnCtxt,
-                  method_call: MethodCall,
-                  expr: &ast::Expr,
-                  base_expr: &ast::Expr,
-                  adjusted_ty: ty::t,
-                  adjustment: ty::AutoDerefRef,
-                  lvalue_pref: LvaluePreference)
-                  -> Option<(/*index type*/ ty::t, /*element type*/ ty::t)>
+fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                            method_call: MethodCall,
+                            expr: &ast::Expr,
+                            base_expr: &ast::Expr,
+                            adjusted_ty: Ty<'tcx>,
+                            adjustment: ty::AutoDerefRef<'tcx>,
+                            lvalue_pref: LvaluePreference)
+                            -> Option<(/*index type*/ Ty<'tcx>, /*element type*/ Ty<'tcx>)>
 {
     /*!
      * To type-check `base_expr[index_expr]`, we progressively autoderef (and otherwise adjust)
@@ -2497,14 +2606,14 @@ fn try_index_step(fcx: &FnCtxt,
 }
 
 /// Given the head of a `for` expression, looks up the `next` method in the
-/// `Iterator` trait. Fails if the expression does not implement `next`.
+/// `Iterator` trait. Panics if the expression does not implement `next`.
 ///
 /// The return type of this function represents the concrete element type
 /// `A` in the type `Iterator<A>` that the method returns.
-fn lookup_method_for_for_loop(fcx: &FnCtxt,
-                              iterator_expr: &ast::Expr,
-                              loop_id: ast::NodeId)
-                              -> ty::t {
+fn lookup_method_for_for_loop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                        iterator_expr: &ast::Expr,
+                                        loop_id: ast::NodeId)
+                                        -> Ty<'tcx> {
     let trait_did = match fcx.tcx().lang_items.require(IteratorItem) {
         Ok(trait_did) => trait_did,
         Err(ref err_string) => {
@@ -2561,7 +2670,7 @@ fn lookup_method_for_for_loop(fcx: &FnCtxt,
                     structurally_resolved_type(fcx, iterator_expr.span, return_type),
                 ty::FnDiverging => ty::mk_err()
             };
-            match ty::get(return_type).sty {
+            match return_type.sty {
                 ty::ty_enum(_, ref substs)
                         if !substs.types.is_empty_in(subst::TypeSpace) => {
                     *substs.types.get(subst::TypeSpace, 0)
@@ -2583,14 +2692,14 @@ trait has an unexpected type `{}`",
     }
 }
 
-fn check_method_argument_types<'a>(fcx: &FnCtxt,
-                                   sp: Span,
-                                   method_fn_ty: ty::t,
-                                   callee_expr: &ast::Expr,
-                                   args_no_rcvr: &[&'a P<ast::Expr>],
-                                   deref_args: DerefArgs,
-                                   tuple_arguments: TupleArgumentsFlag)
-                                   -> ty::FnOutput {
+fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                         sp: Span,
+                                         method_fn_ty: Ty<'tcx>,
+                                         callee_expr: &ast::Expr,
+                                         args_no_rcvr: &[&P<ast::Expr>],
+                                         deref_args: DerefArgs,
+                                         tuple_arguments: TupleArgumentsFlag)
+                                         -> ty::FnOutput<'tcx> {
     if ty::type_is_error(method_fn_ty) {
        let err_inputs = err_args(args_no_rcvr.len());
         check_argument_types(fcx,
@@ -2603,7 +2712,7 @@ fn check_method_argument_types<'a>(fcx: &FnCtxt,
                              tuple_arguments);
         ty::FnConverging(ty::mk_err())
     } else {
-        match ty::get(method_fn_ty).sty {
+        match method_fn_ty.sty {
             ty::ty_bare_fn(ref fty) => {
                 // HACK(eddyb) ignore self in the definition (see above).
                 check_argument_types(fcx,
@@ -2624,14 +2733,14 @@ fn check_method_argument_types<'a>(fcx: &FnCtxt,
     }
 }
 
-fn check_argument_types<'a>(fcx: &FnCtxt,
-                            sp: Span,
-                            fn_inputs: &[ty::t],
-                            _callee_expr: &ast::Expr,
-                            args: &[&'a P<ast::Expr>],
-                            deref_args: DerefArgs,
-                            variadic: bool,
-                            tuple_arguments: TupleArgumentsFlag) {
+fn check_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                  sp: Span,
+                                  fn_inputs: &[Ty<'tcx>],
+                                  _callee_expr: &ast::Expr,
+                                  args: &[&P<ast::Expr>],
+                                  deref_args: DerefArgs,
+                                  variadic: bool,
+                                  tuple_arguments: TupleArgumentsFlag) {
     /*!
      *
      * Generic function that factors out common logic from
@@ -2651,7 +2760,7 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
     let expected_arg_count = fn_inputs.len();
     let formal_tys = if tuple_arguments == TupleArguments {
         let tuple_type = structurally_resolved_type(fcx, sp, fn_inputs[0]);
-        match ty::get(tuple_type).sty {
+        match tuple_type.sty {
             ty::ty_tup(ref arg_types) => {
                 if arg_types.len() != args.len() {
                     span_err!(tcx.sess, sp, E0057,
@@ -2665,17 +2774,6 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
                     (*arg_types).clone()
                 }
             }
-            ty::ty_nil => {
-                if args.len() != 0 {
-                    span_err!(tcx.sess, sp, E0058,
-                        "this function takes 0 parameters but {} parameter{} supplied",
-                        args.len(),
-                        if args.len() == 1 {" was"} else {"s were"});
-                    err_args(args.len())
-                } else {
-                    vec![]
-                }
-            }
             _ => {
                 span_err!(tcx.sess, sp, E0059,
                     "cannot use call notation; the first type parameter \
@@ -2741,9 +2839,7 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
         };
         for (i, arg) in args.iter().take(t).enumerate() {
             let is_block = match arg.node {
-                ast::ExprFnBlock(..) |
-                ast::ExprProc(..) |
-                ast::ExprUnboxedFn(..) => true,
+                ast::ExprClosure(..) | ast::ExprProc(..) => true,
                 _ => false
             };
 
@@ -2753,7 +2849,7 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
 
                 match deref_args {
                     DoDerefArgs => {
-                        match ty::get(formal_ty).sty {
+                        match formal_ty.sty {
                             ty::ty_rptr(_, mt) => formal_ty = mt.ty,
                             ty::ty_err => (),
                             _ => {
@@ -2785,7 +2881,7 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
             // in C but we just error out instead and require explicit casts.
             let arg_ty = structurally_resolved_type(fcx, arg.span,
                                                     fcx.expr_ty(&***arg));
-            match ty::get(arg_ty).sty {
+            match arg_ty.sty {
                 ty::ty_float(ast::TyF32) => {
                     fcx.type_error_message(arg.span,
                                            |t| {
@@ -2813,11 +2909,14 @@ fn check_argument_types<'a>(fcx: &FnCtxt,
     }
 }
 
-fn err_args(len: uint) -> Vec<ty::t> {
+// FIXME(#17596) Ty<'tcx> is incorrectly invariant w.r.t 'tcx.
+fn err_args<'tcx>(len: uint) -> Vec<Ty<'tcx>> {
     Vec::from_fn(len, |_| ty::mk_err())
 }
 
-fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::FnOutput) {
+fn write_call<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                        call_expr: &ast::Expr,
+                        output: ty::FnOutput<'tcx>) {
     fcx.write_ty(call_expr.id, match output {
         ty::FnConverging(output_ty) => output_ty,
         ty::FnDiverging => fcx.infcx().next_diverging_ty_var()
@@ -2825,10 +2924,10 @@ fn write_call(fcx: &FnCtxt, call_expr: &ast::Expr, output: ty::FnOutput) {
 }
 
 // AST fragment checking
-fn check_lit(fcx: &FnCtxt,
-             lit: &ast::Lit,
-             expected: Expectation)
-             -> ty::t
+fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                       lit: &ast::Lit,
+                       expected: Expectation<'tcx>)
+                       -> Ty<'tcx>
 {
     let tcx = fcx.ccx.tcx;
 
@@ -2866,7 +2965,6 @@ fn check_lit(fcx: &FnCtxt,
             opt_ty.unwrap_or_else(
                 || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
         }
-        ast::LitNil => ty::mk_nil(),
         ast::LitBool(_) => ty::mk_bool()
     }
 }
@@ -2881,40 +2979,41 @@ pub fn valid_range_bounds(ccx: &CrateCtxt,
     }
 }
 
-pub fn check_expr_has_type(fcx: &FnCtxt,
-                           expr: &ast::Expr,
-                           expected: ty::t) {
+pub fn check_expr_has_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                     expr: &ast::Expr,
+                                     expected: Ty<'tcx>) {
     check_expr_with_unifier(
         fcx, expr, ExpectHasType(expected), NoPreference,
         || demand::suptype(fcx, expr.span, expected, fcx.expr_ty(expr)));
 }
 
-fn check_expr_coercable_to_type(fcx: &FnCtxt,
-                                expr: &ast::Expr,
-                                expected: ty::t) {
+fn check_expr_coercable_to_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                          expr: &ast::Expr,
+                                          expected: Ty<'tcx>) {
     check_expr_with_unifier(
         fcx, expr, ExpectHasType(expected), NoPreference,
         || demand::coerce(fcx, expr.span, expected, expr));
 }
 
-fn check_expr_with_hint(fcx: &FnCtxt, expr: &ast::Expr, expected: ty::t) {
+fn check_expr_with_hint<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, expr: &ast::Expr,
+                                  expected: Ty<'tcx>) {
     check_expr_with_unifier(
         fcx, expr, ExpectHasType(expected), NoPreference,
         || ())
 }
 
-fn check_expr_with_expectation(fcx: &FnCtxt,
-                               expr: &ast::Expr,
-                               expected: Expectation) {
+fn check_expr_with_expectation<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                         expr: &ast::Expr,
+                                         expected: Expectation<'tcx>) {
     check_expr_with_unifier(
         fcx, expr, expected, NoPreference,
         || ())
 }
 
-fn check_expr_with_expectation_and_lvalue_pref(fcx: &FnCtxt,
-                                            expr: &ast::Expr,
-                                            expected: Expectation,
-                                            lvalue_pref: LvaluePreference)
+fn check_expr_with_expectation_and_lvalue_pref<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                                         expr: &ast::Expr,
+                                                         expected: Expectation<'tcx>,
+                                                         lvalue_pref: LvaluePreference)
 {
     check_expr_with_unifier(fcx, expr, expected, lvalue_pref, || ())
 }
@@ -2932,10 +3031,10 @@ fn check_expr_with_lvalue_pref(fcx: &FnCtxt, expr: &ast::Expr,
 // declared on the impl declaration e.g., `impl<A,B> for ~[(A,B)]`
 // would return ($0, $1) where $0 and $1 are freshly instantiated type
 // variables.
-pub fn impl_self_ty(fcx: &FnCtxt,
-                    span: Span, // (potential) receiver for this impl
-                    did: ast::DefId)
-                    -> TypeAndSubsts {
+pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                              span: Span, // (potential) receiver for this impl
+                              did: ast::DefId)
+                              -> TypeAndSubsts<'tcx> {
     let tcx = fcx.tcx();
 
     let ity = ty::lookup_item_type(tcx, did);
@@ -2954,21 +3053,23 @@ pub fn impl_self_ty(fcx: &FnCtxt,
 
 // Only for fields! Returns <none> for methods>
 // Indifferent to privacy flags
-pub fn lookup_field_ty(tcx: &ty::ctxt,
-                       class_id: ast::DefId,
-                       items: &[ty::field_ty],
-                       fieldname: ast::Name,
-                       substs: &subst::Substs) -> Option<ty::t> {
+pub fn lookup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
+                             class_id: ast::DefId,
+                             items: &[ty::field_ty],
+                             fieldname: ast::Name,
+                             substs: &subst::Substs<'tcx>)
+                             -> Option<Ty<'tcx>> {
 
     let o_field = items.iter().find(|f| f.name == fieldname);
     o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
 }
 
-pub fn lookup_tup_field_ty(tcx: &ty::ctxt,
-                           class_id: ast::DefId,
-                           items: &[ty::field_ty],
-                           idx: uint,
-                           substs: &subst::Substs) -> Option<ty::t> {
+pub fn lookup_tup_field_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                 class_id: ast::DefId,
+                                 items: &[ty::field_ty],
+                                 idx: uint,
+                                 substs: &subst::Substs<'tcx>)
+                                 -> Option<Ty<'tcx>> {
 
     let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
     o_field.map(|f| ty::lookup_field_type(tcx, class_id, f.id, substs))
@@ -3013,20 +3114,20 @@ enum TupleArgumentsFlag {
 /// Note that inspecting a type's structure *directly* may expose the fact
 /// that there are actually multiple representations for `ty_err`, so avoid
 /// that when err needs to be handled differently.
-fn check_expr_with_unifier(fcx: &FnCtxt,
-                           expr: &ast::Expr,
-                           expected: Expectation,
-                           lvalue_pref: LvaluePreference,
-                           unifier: ||)
+fn check_expr_with_unifier<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                     expr: &ast::Expr,
+                                     expected: Expectation<'tcx>,
+                                     lvalue_pref: LvaluePreference,
+                                     unifier: ||)
 {
     debug!(">> typechecking: expr={} expected={}",
            expr.repr(fcx.tcx()), expected.repr(fcx.tcx()));
 
     // A generic function for doing all of the checking for call expressions
-    fn check_call<'a>(fcx: &FnCtxt,
-                      call_expr: &ast::Expr,
-                      f: &ast::Expr,
-                      args: &[&'a P<ast::Expr>]) {
+    fn check_call(fcx: &FnCtxt,
+                  call_expr: &ast::Expr,
+                  f: &ast::Expr,
+                  args: &[&P<ast::Expr>]) {
         // Store the type of `f` as the type of the callee
         let fn_ty = fcx.expr_ty(f);
 
@@ -3037,7 +3138,6 @@ fn check_call<'a>(fcx: &FnCtxt,
         // In that case, we check each argument against "error" in order to
         // set up all the node type bindings.
         let error_fn_sig = FnSig {
-            binder_id: ast::CRATE_NODE_ID,
             inputs: err_args(args.len()),
             output: ty::FnConverging(ty::mk_err()),
             variadic: false
@@ -3056,9 +3156,10 @@ fn check_call<'a>(fcx: &FnCtxt,
 
         // Replace any bound regions that appear in the function
         // signature with region variables
-        let (_, fn_sig) = replace_late_bound_regions(fcx.tcx(), fn_sig.binder_id, fn_sig, |br| {
-            fcx.infcx().next_region_var(infer::LateBoundRegion(call_expr.span, br))
-        });
+        let fn_sig =
+            fcx.infcx().replace_late_bound_regions_with_fresh_var(call_expr.span,
+                                                                  infer::FnCall,
+                                                                  fn_sig).0;
 
         // Call the generic checker.
         check_argument_types(fcx,
@@ -3090,14 +3191,12 @@ fn check_method_call(fcx: &FnCtxt,
 
         let tps = tps.iter().map(|ast_ty| fcx.to_ty(&**ast_ty)).collect::<Vec<_>>();
         let fn_ty = match method::lookup(fcx,
-                                         expr,
-                                         &*rcvr,
+                                         method_name.span,
                                          method_name.node.name,
                                          expr_t,
-                                         tps.as_slice(),
-                                         DontDerefArgs,
-                                         CheckTraitsAndInherentMethods,
-                                         AutoderefReceiver) {
+                                         tps,
+                                         expr,
+                                         rcvr) {
             Ok(method) => {
                 let method_ty = method.ty;
                 let method_call = MethodCall::expr(expr.id);
@@ -3126,13 +3225,13 @@ fn check_method_call(fcx: &FnCtxt,
 
     // A generic function for checking the then and else in an if
     // or if-check
-    fn check_then_else(fcx: &FnCtxt,
-                       cond_expr: &ast::Expr,
-                       then_blk: &ast::Block,
-                       opt_else_expr: Option<&ast::Expr>,
-                       id: ast::NodeId,
-                       sp: Span,
-                       expected: Expectation) {
+    fn check_then_else<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                 cond_expr: &ast::Expr,
+                                 then_blk: &ast::Block,
+                                 opt_else_expr: Option<&ast::Expr>,
+                                 id: ast::NodeId,
+                                 sp: Span,
+                                 expected: Expectation<'tcx>) {
         check_expr_has_type(fcx, cond_expr, ty::mk_bool());
 
         // Disregard "castable to" expectations because they
@@ -3180,7 +3279,7 @@ fn check_then_else(fcx: &FnCtxt,
                                         infer::IfExpressionWithNoElse(sp),
                                         false,
                                         then_ty,
-                                        ty::mk_nil())
+                                        ty::mk_nil(fcx.tcx()))
             }
         };
 
@@ -3196,12 +3295,12 @@ fn check_then_else(fcx: &FnCtxt,
 
     fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
                                   op_ex: &ast::Expr,
-                                  lhs_ty: ty::t,
+                                  lhs_ty: Ty<'tcx>,
                                   opname: ast::Name,
                                   trait_did: Option<ast::DefId>,
                                   lhs: &'a ast::Expr,
                                   rhs: Option<&P<ast::Expr>>,
-                                  unbound_method: ||) -> ty::t {
+                                  unbound_method: ||) -> Ty<'tcx> {
         let method = match trait_did {
             Some(trait_did) => {
                 // We do eager coercions to make using operators
@@ -3214,7 +3313,7 @@ fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
                 //   could also solve this with variance or different
                 //   traits that don't force left and right to have same
                 //   type.
-                let (adj_ty, adjustment) = match ty::get(lhs_ty).sty {
+                let (adj_ty, adjustment) = match lhs_ty.sty {
                     ty::ty_rptr(r_in, mt) => {
                         let r_adj = fcx.infcx().next_region_var(infer::Autoref(lhs.span));
                         fcx.mk_subr(infer::Reborrow(lhs.span), r_adj, r_in);
@@ -3379,12 +3478,12 @@ fn check_binop(fcx: &FnCtxt,
         }
     }
 
-    fn check_user_binop(fcx: &FnCtxt,
-                        ex: &ast::Expr,
-                        lhs_expr: &ast::Expr,
-                        lhs_resolved_t: ty::t,
-                        op: ast::BinOp,
-                        rhs: &P<ast::Expr>) -> ty::t {
+    fn check_user_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                  ex: &ast::Expr,
+                                  lhs_expr: &ast::Expr,
+                                  lhs_resolved_t: Ty<'tcx>,
+                                  op: ast::BinOp,
+                                  rhs: &P<ast::Expr>) -> Ty<'tcx> {
         let tcx = fcx.ccx.tcx;
         let lang = &tcx.lang_items;
         let (name, trait_did) = match op {
@@ -3419,13 +3518,13 @@ fn check_user_binop(fcx: &FnCtxt,
         })
     }
 
-    fn check_user_unop(fcx: &FnCtxt,
-                       op_str: &str,
-                       mname: &str,
-                       trait_did: Option<ast::DefId>,
-                       ex: &ast::Expr,
-                       rhs_expr: &ast::Expr,
-                       rhs_t: ty::t) -> ty::t {
+    fn check_user_unop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                 op_str: &str,
+                                 mname: &str,
+                                 trait_did: Option<ast::DefId>,
+                                 ex: &ast::Expr,
+                                 rhs_expr: &ast::Expr,
+                                 rhs_t: Ty<'tcx>) -> Ty<'tcx> {
        lookup_op_method(fcx, ex, rhs_t, token::intern(mname),
                         trait_did, rhs_expr, None, || {
             fcx.type_error_message(ex.span, |actual| {
@@ -3435,178 +3534,12 @@ fn check_user_unop(fcx: &FnCtxt,
         })
     }
 
-    fn check_unboxed_closure(fcx: &FnCtxt,
-                             expr: &ast::Expr,
-                             kind: ast::UnboxedClosureKind,
-                             decl: &ast::FnDecl,
-                             body: &ast::Block) {
-        let mut fn_ty = astconv::ty_of_closure(
-            fcx,
-            expr.id,
-            ast::NormalFn,
-            ast::Many,
-
-            // The `RegionTraitStore` and region_existential_bounds
-            // are lies, but we ignore them so it doesn't matter.
-            //
-            // FIXME(pcwalton): Refactor this API.
-            ty::region_existential_bound(ty::ReStatic),
-            ty::RegionTraitStore(ty::ReStatic, ast::MutImmutable),
-
-            decl,
-            abi::RustCall,
-            None);
-
-        let region = match fcx.infcx().anon_regions(expr.span, 1) {
-            Err(_) => {
-                fcx.ccx.tcx.sess.span_bug(expr.span,
-                                          "can't make anon regions here?!")
-            }
-            Ok(regions) => regions[0],
-        };
-        let closure_type = ty::mk_unboxed_closure(fcx.ccx.tcx,
-                                                  local_def(expr.id),
-                                                  region,
-                                                  fcx.inh.param_env.free_substs.clone());
-        fcx.write_ty(expr.id, closure_type);
-
-        check_fn(fcx.ccx,
-                 ast::NormalFn,
-                 expr.id,
-                 &fn_ty.sig,
-                 decl,
-                 expr.id,
-                 &*body,
-                 fcx.inh);
-
-        // Tuple up the arguments and insert the resulting function type into
-        // the `unboxed_closures` table.
-        fn_ty.sig.inputs = vec![ty::mk_tup_or_nil(fcx.tcx(), fn_ty.sig.inputs)];
-
-        let kind = match kind {
-            ast::FnUnboxedClosureKind => ty::FnUnboxedClosureKind,
-            ast::FnMutUnboxedClosureKind => ty::FnMutUnboxedClosureKind,
-            ast::FnOnceUnboxedClosureKind => ty::FnOnceUnboxedClosureKind,
-        };
-
-        debug!("unboxed_closure for {} --> sig={} kind={}",
-               local_def(expr.id).repr(fcx.tcx()),
-               fn_ty.sig.repr(fcx.tcx()),
-               kind);
-
-        let unboxed_closure = ty::UnboxedClosure {
-            closure_type: fn_ty,
-            kind: kind,
-        };
-
-        fcx.inh
-           .unboxed_closures
-           .borrow_mut()
-           .insert(local_def(expr.id), unboxed_closure);
-    }
-
-    fn check_expr_fn(fcx: &FnCtxt,
-                     expr: &ast::Expr,
-                     store: ty::TraitStore,
-                     decl: &ast::FnDecl,
-                     body: &ast::Block,
-                     expected: Expectation) {
-        let tcx = fcx.ccx.tcx;
-
-        // Find the expected input/output types (if any). Substitute
-        // fresh bound regions for any bound regions we find in the
-        // expected types so as to avoid capture.
-        let expected_sty = expected.map_to_option(fcx, |x| Some((*x).clone()));
-        let (expected_sig,
-             expected_onceness,
-             expected_bounds) = {
-            match expected_sty {
-                Some(ty::ty_closure(ref cenv)) => {
-                    let (_, sig) =
-                        replace_late_bound_regions(
-                            tcx, cenv.sig.binder_id, &cenv.sig,
-                            |_| fcx.inh.infcx.fresh_bound_region(expr.id));
-                    let onceness = match (&store, &cenv.store) {
-                        // As the closure type and onceness go, only three
-                        // combinations are legit:
-                        //      once closure
-                        //      many closure
-                        //      once proc
-                        // If the actual and expected closure type disagree with
-                        // each other, set expected onceness to be always Once or
-                        // Many according to the actual type. Otherwise, it will
-                        // yield either an illegal "many proc" or a less known
-                        // "once closure" in the error message.
-                        (&ty::UniqTraitStore, &ty::UniqTraitStore) |
-                        (&ty::RegionTraitStore(..), &ty::RegionTraitStore(..)) =>
-                            cenv.onceness,
-                        (&ty::UniqTraitStore, _) => ast::Once,
-                        (&ty::RegionTraitStore(..), _) => ast::Many,
-                    };
-                    (Some(sig), onceness, cenv.bounds)
-                }
-                _ => {
-                    // Not an error! Means we're inferring the closure type
-                    let (bounds, onceness) = match expr.node {
-                        ast::ExprProc(..) => {
-                            let mut bounds = ty::region_existential_bound(ty::ReStatic);
-                            bounds.builtin_bounds.insert(ty::BoundSend); // FIXME
-                            (bounds, ast::Once)
-                        }
-                        _ => {
-                            let region = fcx.infcx().next_region_var(
-                                infer::AddrOfRegion(expr.span));
-                            (ty::region_existential_bound(region), ast::Many)
-                        }
-                    };
-                    (None, onceness, bounds)
-                }
-            }
-        };
-
-        // construct the function type
-        let fn_ty = astconv::ty_of_closure(fcx,
-                                           expr.id,
-                                           ast::NormalFn,
-                                           expected_onceness,
-                                           expected_bounds,
-                                           store,
-                                           decl,
-                                           abi::Rust,
-                                           expected_sig);
-        let fty_sig = fn_ty.sig.clone();
-        let fty = ty::mk_closure(tcx, fn_ty);
-        debug!("check_expr_fn fty={}", fcx.infcx().ty_to_string(fty));
-
-        fcx.write_ty(expr.id, fty);
-
-        // If the closure is a stack closure and hasn't had some non-standard
-        // style inferred for it, then check it under its parent's style.
-        // Otherwise, use its own
-        let (inherited_style, inherited_style_id) = match store {
-            ty::RegionTraitStore(..) => (fcx.ps.borrow().fn_style,
-                                         fcx.ps.borrow().def),
-            ty::UniqTraitStore => (ast::NormalFn, expr.id)
-        };
-
-        check_fn(fcx.ccx,
-                 inherited_style,
-                 inherited_style_id,
-                 &fty_sig,
-                 &*decl,
-                 expr.id,
-                 &*body,
-                 fcx.inh);
-    }
-
-
     // Check field access expressions
     fn check_field(fcx: &FnCtxt,
                    expr: &ast::Expr,
                    lvalue_pref: LvaluePreference,
                    base: &ast::Expr,
-                   field: &ast::SpannedIdent,
-                   tys: &[P<ast::Ty>]) {
+                   field: &ast::SpannedIdent) {
         let tcx = fcx.ccx.tcx;
         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
         let expr_t = structurally_resolved_type(fcx, expr.span,
@@ -3614,7 +3547,7 @@ fn check_field(fcx: &FnCtxt,
         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
         let (_, autoderefs, field_ty) =
             autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
-                match ty::get(base_t).sty {
+                match base_t.sty {
                     ty::ty_struct(base_id, ref substs) => {
                         debug!("struct named {}", ppaux::ty_to_string(tcx, base_t));
                         let fields = ty::lookup_struct_fields(tcx, base_id);
@@ -3633,42 +3566,29 @@ fn check_field(fcx: &FnCtxt,
             None => {}
         }
 
-        let tps: Vec<ty::t> = tys.iter().map(|ty| fcx.to_ty(&**ty)).collect();
-        match method::lookup(fcx,
-                             expr,
-                             base,
-                             field.node.name,
-                             expr_t,
-                             tps.as_slice(),
-                             DontDerefArgs,
-                             CheckTraitsAndInherentMethods,
-                             AutoderefReceiver) {
-            Ok(_) => {
-                fcx.type_error_message(
-                    field.span,
-                    |actual| {
-                        format!("attempted to take value of method `{}` on type \
-                                 `{}`", token::get_ident(field.node), actual)
-                    },
-                    expr_t, None);
-
-                tcx.sess.span_help(field.span,
-                    "maybe a `()` to call it is missing? \
-                     If not, try an anonymous function");
-            }
+        if method::exists(fcx, field.span, field.node.name, expr_t, expr.id) {
+            fcx.type_error_message(
+                field.span,
+                |actual| {
+                    format!("attempted to take value of method `{}` on type \
+                            `{}`", token::get_ident(field.node), actual)
+                },
+                expr_t, None);
 
-            Err(_) => {
-                fcx.type_error_message(
-                    expr.span,
-                    |actual| {
-                        format!("attempted access of field `{}` on \
-                                        type `{}`, but no field with that \
-                                        name was found",
-                                       token::get_ident(field.node),
-                                       actual)
-                    },
-                    expr_t, None);
-            }
+            tcx.sess.span_help(field.span,
+                               "maybe a `()` to call it is missing? \
+                               If not, try an anonymous function");
+        } else {
+            fcx.type_error_message(
+                expr.span,
+                |actual| {
+                    format!("attempted access of field `{}` on \
+                            type `{}`, but no field with that \
+                            name was found",
+                            token::get_ident(field.node),
+                            actual)
+                },
+                expr_t, None);
         }
 
         fcx.write_error(expr.id);
@@ -3679,8 +3599,7 @@ fn check_tup_field(fcx: &FnCtxt,
                        expr: &ast::Expr,
                        lvalue_pref: LvaluePreference,
                        base: &ast::Expr,
-                       idx: codemap::Spanned<uint>,
-                       _tys: &[P<ast::Ty>]) {
+                       idx: codemap::Spanned<uint>) {
         let tcx = fcx.ccx.tcx;
         check_expr_with_lvalue_pref(fcx, base, lvalue_pref);
         let expr_t = structurally_resolved_type(fcx, expr.span,
@@ -3689,7 +3608,7 @@ fn check_tup_field(fcx: &FnCtxt,
         // FIXME(eddyb) #12808 Integrate privacy into this auto-deref loop.
         let (_, autoderefs, field_ty) =
             autoderef(fcx, expr.span, expr_t, Some(base.id), lvalue_pref, |base_t, _| {
-                match ty::get(base_t).sty {
+                match base_t.sty {
                     ty::ty_struct(base_id, ref substs) => {
                         tuple_like = ty::is_tuple_struct(tcx, base_id);
                         if tuple_like {
@@ -3736,15 +3655,15 @@ fn check_tup_field(fcx: &FnCtxt,
         fcx.write_error(expr.id);
     }
 
-    fn check_struct_or_variant_fields(fcx: &FnCtxt,
-                                      struct_ty: ty::t,
-                                      span: Span,
-                                      class_id: ast::DefId,
-                                      node_id: ast::NodeId,
-                                      substitutions: subst::Substs,
-                                      field_types: &[ty::field_ty],
-                                      ast_fields: &[ast::Field],
-                                      check_completeness: bool)  {
+    fn check_struct_or_variant_fields<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                                struct_ty: Ty<'tcx>,
+                                                span: Span,
+                                                class_id: ast::DefId,
+                                                node_id: ast::NodeId,
+                                                substitutions: subst::Substs<'tcx>,
+                                                field_types: &[ty::field_ty],
+                                                ast_fields: &[ast::Field],
+                                                check_completeness: bool)  {
         let tcx = fcx.ccx.tcx;
 
         let mut class_field_map = FnvHashMap::new();
@@ -3838,7 +3757,7 @@ fn check_struct_constructor(fcx: &FnCtxt,
         let TypeAndSubsts {
             ty: mut struct_type,
             substs: struct_substs
-        } = fcx.instantiate_item_type(span, class_id);
+        } = fcx.instantiate_type(span, class_id);
 
         // Look up and check the fields.
         let class_fields = ty::lookup_struct_fields(tcx, class_id);
@@ -3880,7 +3799,7 @@ fn check_struct_enum_variant(fcx: &FnCtxt,
         let TypeAndSubsts {
             ty: enum_type,
             substs: substitutions
-        } = fcx.instantiate_item_type(span, enum_id);
+        } = fcx.instantiate_type(span, enum_id);
 
         // Look up and check the enum variant fields.
         let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
@@ -3912,7 +3831,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
         }
     }
 
-    type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, ty::t);
+    type ExprCheckerWithTy = fn(&FnCtxt, &ast::Expr, Ty);
 
     let tcx = fcx.ccx.tcx;
     let id = expr.id;
@@ -4020,7 +3939,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
                                                            Some(&**oprnd), oprnd_t, lvalue_pref) {
                             Some(mt) => mt.ty,
                             None => {
-                                let is_newtype = match ty::get(oprnd_t).sty {
+                                let is_newtype = match oprnd_t.sty {
                                     ty::ty_struct(did, ref substs) => {
                                         let fields = ty::struct_fields(fcx.tcx(), did, substs);
                                         fields.len() == 1
@@ -4049,7 +3968,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
                                                          oprnd_t);
                     if !(ty::type_is_integral(oprnd_t) ||
-                         ty::get(oprnd_t).sty == ty::ty_bool) {
+                         oprnd_t.sty == ty::ty_bool) {
                         oprnd_t = check_user_unop(fcx, "!", "not",
                                                   tcx.lang_items.not_trait(),
                                                   expr, &**oprnd, oprnd_t);
@@ -4149,7 +4068,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
                 match *expr_opt {
                     None =>
                         if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
-                                                    result_type, ty::mk_nil()) {
+                                                    result_type, ty::mk_nil(fcx.tcx())) {
                             span_err!(tcx.sess, expr.span, E0069,
                                 "`return;` in function returning non-nil");
                         },
@@ -4243,32 +4162,16 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
       ast::ExprMatch(ref discrim, ref arms, _) => {
         _match::check_match(fcx, expr, &**discrim, arms.as_slice());
       }
-      ast::ExprFnBlock(_, ref decl, ref body) => {
-        let region = astconv::opt_ast_region_to_region(fcx,
-                                                       fcx.infcx(),
-                                                       expr.span,
-                                                       &None);
-        check_expr_fn(fcx,
-                      expr,
-                      ty::RegionTraitStore(region, ast::MutMutable),
-                      &**decl,
-                      &**body,
-                      expected);
-      }
-      ast::ExprUnboxedFn(_, kind, ref decl, ref body) => {
-        check_unboxed_closure(fcx,
-                              expr,
-                              kind,
-                              &**decl,
-                              &**body);
+      ast::ExprClosure(_, opt_kind, ref decl, ref body) => {
+          closure::check_expr_closure(fcx, expr, opt_kind, &**decl, &**body, expected);
       }
       ast::ExprProc(ref decl, ref body) => {
-        check_expr_fn(fcx,
-                      expr,
-                      ty::UniqTraitStore,
-                      &**decl,
-                      &**body,
-                      expected);
+          closure::check_boxed_closure(fcx,
+                                       expr,
+                                       ty::UniqTraitStore,
+                                       &**decl,
+                                       &**body,
+                                       expected);
       }
       ast::ExprBlock(ref b) => {
         check_block_with_expected(fcx, &**b, expected);
@@ -4315,7 +4218,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
       ast::ExprVec(ref args) => {
         let uty = match expected {
             ExpectHasType(uty) => {
-                match ty::get(uty).sty {
+                match uty.sty {
                         ty::ty_vec(ty, _) => Some(ty),
                         _ => None
                 }
@@ -4331,7 +4234,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
                 uty
             }
             None => {
-                let t: ty::t = fcx.infcx().next_ty_var();
+                let t: Ty = fcx.infcx().next_ty_var();
                 for e in args.iter() {
                     check_expr_has_type(fcx, &**e, t);
                 }
@@ -4347,7 +4250,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
 
         let uty = match expected {
             ExpectHasType(uty) => {
-                match ty::get(uty).sty {
+                match uty.sty {
                         ty::ty_vec(ty, _) => Some(ty),
                         _ => None
                 }
@@ -4361,7 +4264,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
                 (uty, uty)
             }
             None => {
-                let t: ty::t = fcx.infcx().next_ty_var();
+                let t: Ty = fcx.infcx().next_ty_var();
                 check_expr_has_type(fcx, &**element, t);
                 (fcx.expr_ty(&**element), t)
             }
@@ -4438,7 +4341,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
             Some(def) => {
                 // Verify that this was actually a struct.
                 let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
-                match ty::get(typ.ty).sty {
+                match typ.ty.sty {
                     ty::ty_struct(struct_did, _) => {
                         check_struct_constructor(fcx,
                                                  id,
@@ -4474,8 +4377,7 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
             let type_and_substs = astconv::ast_path_to_ty_relaxed(fcx,
                                                                   fcx.infcx(),
                                                                   struct_id,
-                                                                  path,
-                                                                  expr.id);
+                                                                  path);
             match fcx.mk_subty(false,
                                infer::Misc(path.span),
                                actual_structure_type,
@@ -4503,11 +4405,11 @@ fn check_struct_fields_on_error(fcx: &FnCtxt,
 
         fcx.require_expr_have_sized_type(expr, traits::StructInitializerSized);
       }
-      ast::ExprField(ref base, ref field, ref tys) => {
-        check_field(fcx, expr, lvalue_pref, &**base, field, tys.as_slice());
+      ast::ExprField(ref base, ref field, _) => {
+        check_field(fcx, expr, lvalue_pref, &**base, field);
       }
-      ast::ExprTupField(ref base, idx, ref tys) => {
-        check_tup_field(fcx, expr, lvalue_pref, &**base, idx, tys.as_slice());
+      ast::ExprTupField(ref base, idx, _) => {
+        check_tup_field(fcx, expr, lvalue_pref, &**base, idx);
       }
       ast::ExprIndex(ref base, ref idx) => {
           check_expr_with_lvalue_pref(fcx, &**base, lvalue_pref);
@@ -4622,16 +4524,12 @@ fn constrain_path_type_parameters(fcx: &FnCtxt,
                                   expr: &ast::Expr)
 {
     fcx.opt_node_ty_substs(expr.id, |item_substs| {
-        for &ty in item_substs.substs.types.iter() {
-            let default_bound = ty::ReScope(expr.id);
-            let origin = infer::RelateDefaultParamBound(expr.span, ty);
-            fcx.register_region_obligation(origin, ty, default_bound);
-        }
+        fcx.add_default_region_param_bounds(&item_substs.substs, expr);
     });
 }
 
-impl Expectation {
-    fn only_has_type(self) -> Expectation {
+impl<'tcx> Expectation<'tcx> {
+    fn only_has_type(self) -> Expectation<'tcx> {
         match self {
             NoExpectation | ExpectCastableToType(..) => NoExpectation,
             ExpectHasType(t) => ExpectHasType(t)
@@ -4641,7 +4539,7 @@ fn only_has_type(self) -> Expectation {
     // 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) -> Expectation {
+    fn resolve<'a>(self, fcx: &FnCtxt<'a, 'tcx>) -> Expectation<'tcx> {
         match self {
             NoExpectation => {
                 NoExpectation
@@ -4657,27 +4555,29 @@ fn resolve(self, fcx: &FnCtxt) -> Expectation {
         }
     }
 
-    fn map(self, fcx: &FnCtxt, unpack: |&ty::sty| -> Expectation) -> Expectation {
+    fn map<'a>(self, fcx: &FnCtxt<'a, 'tcx>,
+               unpack: |&ty::sty<'tcx>| -> Expectation<'tcx>)
+               -> Expectation<'tcx> {
         match self.resolve(fcx) {
             NoExpectation => NoExpectation,
-            ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
+            ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
         }
     }
 
-    fn map_to_option<O>(self,
-                        fcx: &FnCtxt,
-                        unpack: |&ty::sty| -> Option<O>)
-                        -> Option<O>
+    fn map_to_option<'a, O>(self,
+                            fcx: &FnCtxt<'a, 'tcx>,
+                            unpack: |&ty::sty<'tcx>| -> Option<O>)
+                            -> Option<O>
     {
         match self.resolve(fcx) {
             NoExpectation => None,
-            ExpectCastableToType(t) | ExpectHasType(t) => unpack(&ty::get(t).sty),
+            ExpectCastableToType(t) | ExpectHasType(t) => unpack(&t.sty),
         }
     }
 }
 
-impl Repr for Expectation {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
+impl<'tcx> Repr<'tcx> for Expectation<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         match *self {
             NoExpectation => format!("NoExpectation"),
             ExpectHasType(t) => format!("ExpectHasType({})",
@@ -4744,7 +4644,7 @@ pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
       ast::StmtExpr(ref expr, id) => {
         node_id = id;
         // Check with expected type of ()
-        check_expr_has_type(fcx, &**expr, ty::mk_nil());
+        check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
         let expr_ty = fcx.expr_ty(&**expr);
         saw_bot = saw_bot || fcx.infcx().type_var_diverges(expr_ty);
         saw_err = saw_err || ty::type_is_error(expr_ty);
@@ -4770,19 +4670,19 @@ pub fn check_stmt(fcx: &FnCtxt, stmt: &ast::Stmt)  {
 }
 
 pub fn check_block_no_value(fcx: &FnCtxt, blk: &ast::Block)  {
-    check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil()));
+    check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
     let blkty = fcx.node_ty(blk.id);
     if ty::type_is_error(blkty) {
         fcx.write_error(blk.id);
     } else {
-        let nilty = ty::mk_nil();
+        let nilty = ty::mk_nil(fcx.tcx());
         demand::suptype(fcx, blk.span, nilty, blkty);
     }
 }
 
-fn check_block_with_expected(fcx: &FnCtxt,
-                             blk: &ast::Block,
-                             expected: Expectation) {
+fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                       blk: &ast::Block,
+                                       expected: Expectation<'tcx>) {
     let prev = {
         let mut fcx_ps = fcx.ps.borrow_mut();
         let fn_style_state = fcx_ps.recurse(blk);
@@ -4863,9 +4763,9 @@ fn check_block_with_expected(fcx: &FnCtxt,
 /// Checks a constant appearing in a type. At the moment this is just the
 /// length expression in a fixed-length vector, but someday it might be
 /// extended to type-level numeric literals.
-pub fn check_const_in_type(tcx: &ty::ctxt,
-                           expr: &ast::Expr,
-                           expected_type: ty::t) {
+pub fn check_const_in_type<'tcx>(tcx: &ty::ctxt<'tcx>,
+                                 expr: &ast::Expr,
+                                 expected_type: Ty<'tcx>) {
     // Synthesize a crate context. The trait map is not needed here (though I
     // imagine it will be if we have associated statics --pcwalton), so we
     // leave it blank.
@@ -4889,10 +4789,10 @@ pub fn check_const(ccx: &CrateCtxt,
     check_const_with_ty(&fcx, sp, e, declty);
 }
 
-pub fn check_const_with_ty(fcx: &FnCtxt,
-                           _: Span,
-                           e: &ast::Expr,
-                           declty: ty::t) {
+pub fn check_const_with_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                     _: Span,
+                                     e: &ast::Expr,
+                                     declty: Ty<'tcx>) {
     // Gather locals in statics (because of block expressions).
     // This is technically unnecessary because locals in static items are forbidden,
     // but prevents type checking from blowing up before const checking can properly
@@ -4969,7 +4869,7 @@ pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
         span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
         return;
     }
-    match ty::get(t).sty {
+    match t.sty {
         ty::ty_struct(did, ref substs) => {
             let fields = ty::lookup_struct_fields(tcx, did);
             if fields.is_empty() {
@@ -5024,11 +4924,11 @@ fn int_in_range(ccx: &CrateCtxt, ty: ast::IntTy, disr: ty::Disr) -> bool {
         }
     }
 
-    fn do_check(ccx: &CrateCtxt,
-                vs: &[P<ast::Variant>],
-                id: ast::NodeId,
-                hint: attr::ReprAttr)
-                -> Vec<Rc<ty::VariantInfo>> {
+    fn do_check<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                          vs: &[P<ast::Variant>],
+                          id: ast::NodeId,
+                          hint: attr::ReprAttr)
+                          -> Vec<Rc<ty::VariantInfo<'tcx>>> {
 
         let rty = ty::node_id_to_type(ccx.tcx, id);
         let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
@@ -5149,10 +5049,10 @@ pub fn lookup_def(fcx: &FnCtxt, sp: Span, id: ast::NodeId) -> def::Def {
 }
 
 // Returns the type parameter count and the type for the given definition.
-pub fn polytype_for_def(fcx: &FnCtxt,
-                        sp: Span,
-                        defn: def::Def)
-                        -> Polytype {
+pub fn polytype_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                  sp: Span,
+                                  defn: def::Def)
+                                  -> Polytype<'tcx> {
     match defn {
       def::DefLocal(nid) | def::DefUpvar(nid, _, _) => {
           let typ = fcx.local_ty(sp, nid);
@@ -5193,12 +5093,12 @@ pub fn polytype_for_def(fcx: &FnCtxt,
 
 // Instantiates the given path, which must refer to an item with the given
 // number of type parameters and type.
-pub fn instantiate_path(fcx: &FnCtxt,
-                        path: &ast::Path,
-                        polytype: Polytype,
-                        def: def::Def,
-                        span: Span,
-                        node_id: ast::NodeId) {
+pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
+                                  path: &ast::Path,
+                                  polytype: Polytype<'tcx>,
+                                  def: def::Def,
+                                  span: Span,
+                                  node_id: ast::NodeId) {
     debug!("instantiate_path(path={}, def={}, node_id={}, polytype={})",
            path.repr(fcx.tcx()),
            def.repr(fcx.tcx()),
@@ -5359,14 +5259,39 @@ pub fn instantiate_path(fcx: &FnCtxt,
         assert_eq!(substs.regions().len(space), region_defs.len(space));
     }
 
+    // The things we are substituting into the type should not contain
+    // escaping late-bound regions.
+    assert!(!substs.has_regions_escaping_depth(0));
+
+    // In the case of static items taken from impls, there may be
+    // late-bound regions associated with the impl (not declared on
+    // the fn itself). Those should be replaced with fresh variables
+    // now. These can appear either on the type being referenced, or
+    // on the associated bounds.
+    let bounds = polytype.generics.to_bounds(fcx.tcx(), &substs);
+    let (ty_late_bound, bounds) =
+        fcx.infcx().replace_late_bound_regions_with_fresh_var(
+            span,
+            infer::FnCall,
+            &ty::bind((polytype.ty, bounds))).0.value;
+
+    debug!("after late-bounds have been replaced: ty_late_bound={}", ty_late_bound.repr(fcx.tcx()));
+    debug!("after late-bounds have been replaced: bounds={}", bounds.repr(fcx.tcx()));
+
     fcx.add_obligations_for_parameters(
         traits::ObligationCause::new(span, traits::ItemObligation(def.def_id())),
         &substs,
-        &polytype.generics);
+        &bounds);
 
-    fcx.write_ty_substs(node_id, polytype.ty, ty::ItemSubsts {
-        substs: substs,
-    });
+    // Substitute the values for the type parameters into the type of
+    // the referenced item.
+    let ty_substituted = ty_late_bound.subst(fcx.tcx(), &substs);
+
+    debug!("ty_substituted: ty_substituted={}", ty_substituted.repr(fcx.tcx()));
+
+    fcx.write_ty(node_id, ty_substituted);
+    fcx.write_substs(node_id, ty::ItemSubsts { substs: substs });
+    return;
 
     fn report_error_if_segment_contains_type_parameters(
         fcx: &FnCtxt,
@@ -5385,14 +5310,14 @@ fn report_error_if_segment_contains_type_parameters(
         }
     }
 
-    fn push_explicit_parameters_from_segment_to_substs(
-        fcx: &FnCtxt,
+    fn push_explicit_parameters_from_segment_to_substs<'a, 'tcx>(
+        fcx: &FnCtxt<'a, 'tcx>,
         space: subst::ParamSpace,
         span: Span,
-        type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
+        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
         segment: &ast::PathSegment,
-        substs: &mut Substs)
+        substs: &mut Substs<'tcx>)
     {
         /*!
          * Finds the parameters that the user provided and adds them
@@ -5424,13 +5349,13 @@ fn push_explicit_parameters_from_segment_to_substs(
         }
     }
 
-    fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(
-        fcx: &FnCtxt,
+    fn push_explicit_angle_bracketed_parameters_from_segment_to_substs<'a, 'tcx>(
+        fcx: &FnCtxt<'a, 'tcx>,
         space: subst::ParamSpace,
-        type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
+        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
         region_defs: &VecPerParamSpace<ty::RegionParameterDef>,
         data: &ast::AngleBracketedParameterData,
-        substs: &mut Substs)
+        substs: &mut Substs<'tcx>)
     {
         {
             let type_count = type_defs.len(space);
@@ -5469,13 +5394,13 @@ fn push_explicit_angle_bracketed_parameters_from_segment_to_substs(
         }
     }
 
-    fn push_explicit_parenthesized_parameters_from_segment_to_substs(
-        fcx: &FnCtxt,
+    fn push_explicit_parenthesized_parameters_from_segment_to_substs<'a, 'tcx>(
+        fcx: &FnCtxt<'a, 'tcx>,
         space: subst::ParamSpace,
         span: Span,
-        type_defs: &VecPerParamSpace<ty::TypeParameterDef>,
+        type_defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
         data: &ast::ParenthesizedParameterData,
-        substs: &mut Substs)
+        substs: &mut Substs<'tcx>)
     {
         /*!
          * As with
@@ -5494,33 +5419,33 @@ fn push_explicit_parenthesized_parameters_from_segment_to_substs(
                       type_count);
         }
 
-        let input_tys: Vec<ty::t> =
+        let input_tys: Vec<Ty> =
             data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
 
         let tuple_ty =
-            ty::mk_tup_or_nil(fcx.tcx(), input_tys);
+            ty::mk_tup(fcx.tcx(), input_tys);
 
         if type_count >= 1 {
             substs.types.push(space, tuple_ty);
         }
 
-        let output_ty: Option<ty::t> =
+        let output_ty: Option<Ty> =
             data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
 
         let output_ty =
-            output_ty.unwrap_or(ty::mk_nil());
+            output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
 
         if type_count >= 2 {
             substs.types.push(space, output_ty);
         }
     }
 
-    fn adjust_type_parameters(
-        fcx: &FnCtxt,
+    fn adjust_type_parameters<'a, 'tcx>(
+        fcx: &FnCtxt<'a, 'tcx>,
         span: Span,
         space: ParamSpace,
-        defs: &VecPerParamSpace<ty::TypeParameterDef>,
-        substs: &mut Substs)
+        defs: &VecPerParamSpace<ty::TypeParameterDef<'tcx>>,
+        substs: &mut Substs<'tcx>)
     {
         let provided_len = substs.types.len(space);
         let desired = defs.get_slice(space);
@@ -5620,7 +5545,8 @@ fn adjust_region_parameters(
 
 // Resolves `typ` by a single level if `typ` is a type variable.  If no
 // resolution is possible, then an error is reported.
-pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, mut ty: ty::t) -> ty::t {
+pub fn structurally_resolved_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span,
+                                            mut ty: Ty<'tcx>) -> Ty<'tcx> {
     // If `ty` is a type variable, see whether we already know what it is.
     ty = fcx.infcx().shallow_resolve(ty);
 
@@ -5649,9 +5575,9 @@ pub fn structurally_resolved_type(fcx: &FnCtxt, sp: Span, mut ty: ty::t) -> ty::
 }
 
 // Returns the one-level-deep structure of the given type.
-pub fn structure_of<'a>(fcx: &FnCtxt, sp: Span, typ: ty::t)
-                        -> &'a ty::sty {
-    &ty::get(structurally_resolved_type(fcx, sp, typ)).sty
+pub fn structure_of<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>, sp: Span, typ: Ty<'tcx>)
+                        -> &'tcx ty::sty<'tcx> {
+    &structurally_resolved_type(fcx, sp, typ).sty
 }
 
 // Returns true if b contains a break that can exit from b
@@ -5678,10 +5604,10 @@ pub fn may_break(cx: &ty::ctxt, id: ast::NodeId, b: &ast::Block) -> bool {
         }}))
 }
 
-pub fn check_bounds_are_used(ccx: &CrateCtxt,
-                             span: Span,
-                             tps: &OwnedSlice<ast::TyParam>,
-                             ty: ty::t) {
+pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
+                                       span: Span,
+                                       tps: &OwnedSlice<ast::TyParam>,
+                                       ty: Ty<'tcx>) {
     debug!("check_bounds_are_used(n_tps={}, ty={})",
            tps.len(), ppaux::ty_to_string(ccx.tcx, ty));
 
@@ -5690,7 +5616,7 @@ pub fn check_bounds_are_used(ccx: &CrateCtxt,
     let mut tps_used = Vec::from_elem(tps.len(), false);
 
     ty::walk_ty(ty, |t| {
-            match ty::get(t).sty {
+            match t.sty {
                 ty::ty_param(ParamTy {idx, ..}) => {
                     debug!("Found use of ty param num {}", idx);
                     tps_used[idx] = true;
@@ -5709,7 +5635,7 @@ pub fn check_bounds_are_used(ccx: &CrateCtxt,
 }
 
 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
-    fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
+    fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: uint) -> Ty<'tcx> {
         ty::mk_param(ccx.tcx, subst::FnSpace, n, local_def(0))
     }
 
@@ -5728,7 +5654,7 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
             "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
                        param(ccx, 0)),
             "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
-                        ty::mk_nil()),
+                        ty::mk_nil(tcx)),
 
             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
             "min"  | "umax" | "umin" => {
@@ -5736,7 +5662,7 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
                  param(ccx, 0))
             }
             "fence" => {
-                (0, Vec::new(), ty::mk_nil())
+                (0, Vec::new(), ty::mk_nil(tcx))
             }
             op => {
                 span_err!(tcx.sess, it.span, E0092,
@@ -5749,20 +5675,21 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
         (0, Vec::new(), ty::FnDiverging)
     } else {
         let (n_tps, inputs, output) = match name.get() {
-            "breakpoint" => (0, Vec::new(), ty::mk_nil()),
+            "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
             "size_of" |
             "pref_align_of" | "min_align_of" => (1u, Vec::new(), ty::mk_uint()),
             "init" => (1u, Vec::new(), param(ccx, 0u)),
             "uninit" => (1u, Vec::new(), param(ccx, 0u)),
-            "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil()),
+            "forget" => (1u, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
             "move_val_init" => {
                 (1u,
                  vec!(
-                    ty::mk_mut_rptr(tcx, ty::ReLateBound(it.id, ty::BrAnon(0)), param(ccx, 0)),
+                    ty::mk_mut_rptr(tcx, ty::ReLateBound(ty::DebruijnIndex::new(1), ty::BrAnon(0)),
+                                    param(ccx, 0)),
                     param(ccx, 0u)
                   ),
-               ty::mk_nil())
+               ty::mk_nil(tcx))
             }
             "needs_drop" => (1u, Vec::new(), ty::mk_bool()),
             "owns_managed" => (1u, Vec::new(), ty::mk_bool()),
@@ -5818,7 +5745,7 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
                   }),
                   ty::mk_uint()
                ),
-               ty::mk_nil())
+               ty::mk_nil(tcx))
             }
             "set_memory" | "volatile_set_memory" => {
               (1,
@@ -5830,7 +5757,7 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
                   ty::mk_u8(),
                   ty::mk_uint()
                ),
-               ty::mk_nil())
+               ty::mk_nil(tcx))
             }
             "sqrtf32" => (0, vec!( ty::mk_f32() ), ty::mk_f32()),
             "sqrtf64" => (0, vec!( ty::mk_f64() ), ty::mk_f64()),
@@ -5913,7 +5840,7 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
             "volatile_load" =>
                 (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
             "volatile_store" =>
-                (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil()),
+                (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
 
             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
                 (0, vec!(ty::mk_i8(), ty::mk_i8()),
@@ -5949,7 +5876,7 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
 
             "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, ty::mk_u8())),
 
-            "assume" => (0, vec![ty::mk_bool()], ty::mk_nil()),
+            "assume" => (0, vec![ty::mk_bool()], ty::mk_nil(tcx)),
 
             ref other => {
                 span_err!(tcx.sess, it.span, E0093,
@@ -5963,7 +5890,6 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
         fn_style: ast::UnsafeFn,
         abi: abi::RustIntrinsic,
         sig: FnSig {
-            binder_id: it.id,
             inputs: inputs,
             output: output,
             variadic: false,
@@ -5990,8 +5916,8 @@ fn param(ccx: &CrateCtxt, n: uint) -> ty::t {
     }
 }
 
-impl Repr for RegionObligation {
-    fn repr(&self, tcx: &ty::ctxt) -> String {
+impl<'tcx> Repr<'tcx> for RegionObligation<'tcx> {
+    fn repr(&self, tcx: &ty::ctxt<'tcx>) -> String {
         format!("RegionObligation(sub_region={}, sup_type={}, origin={})",
                 self.sub_region.repr(tcx),
                 self.sup_type.repr(tcx),