about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--src/librustc/metadata/encoder.rs51
-rw-r--r--src/librustc/metadata/tydecode.rs38
-rw-r--r--src/librustc/middle/astconv_util.rs8
-rw-r--r--src/librustc/middle/cast.rs4
-rw-r--r--src/librustc/middle/cfg/construct.rs8
-rw-r--r--src/librustc/middle/check_const.rs24
-rw-r--r--src/librustc/middle/check_match.rs40
-rw-r--r--src/librustc/middle/check_rvalues.rs2
-rw-r--r--src/librustc/middle/const_eval.rs18
-rw-r--r--src/librustc/middle/dead.rs23
-rw-r--r--src/librustc/middle/effect.rs8
-rw-r--r--src/librustc/middle/expr_use_visitor.rs39
-rw-r--r--src/librustc/middle/implicator.rs22
-rw-r--r--src/librustc/middle/infer/bivariate.rs4
-rw-r--r--src/librustc/middle/infer/combine.rs6
-rw-r--r--src/librustc/middle/infer/error_reporting.rs358
-rw-r--r--src/librustc/middle/infer/freshen.rs6
-rw-r--r--src/librustc/middle/infer/higher_ranked/mod.rs2
-rw-r--r--src/librustc/middle/infer/mod.rs29
-rw-r--r--src/librustc/middle/infer/region_inference/mod.rs2
-rw-r--r--src/librustc/middle/infer/resolve.rs6
-rw-r--r--src/librustc/middle/infer/unify_key.rs6
-rw-r--r--src/librustc/middle/intrinsicck.rs20
-rw-r--r--src/librustc/middle/liveness.rs22
-rw-r--r--src/librustc/middle/mem_categorization.rs30
-rw-r--r--src/librustc/middle/pat_util.rs2
-rw-r--r--src/librustc/middle/stability.rs28
-rw-r--r--src/librustc/middle/subst.rs21
-rw-r--r--src/librustc/middle/traits/coherence.rs14
-rw-r--r--src/librustc/middle/traits/error_reporting.rs20
-rw-r--r--src/librustc/middle/traits/fulfill.rs4
-rw-r--r--src/librustc/middle/traits/mod.rs4
-rw-r--r--src/librustc/middle/traits/object_safety.rs18
-rw-r--r--src/librustc/middle/traits/project.rs23
-rw-r--r--src/librustc/middle/traits/select.rs56
-rw-r--r--src/librustc/middle/traits/util.rs24
-rw-r--r--src/librustc/middle/ty.rs6521
-rw-r--r--src/librustc/middle/ty_fold.rs8
-rw-r--r--src/librustc/middle/ty_relate/mod.rs26
-rw-r--r--src/librustc/util/ppaux.rs19
-rw-r--r--src/librustc_borrowck/borrowck/check_loans.rs2
-rw-r--r--src/librustc_borrowck/borrowck/fragments.rs8
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs4
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/mod.rs2
-rw-r--r--src/librustc_borrowck/borrowck/gather_loans/move_error.rs2
-rw-r--r--src/librustc_borrowck/borrowck/mod.rs32
-rw-r--r--src/librustc_driver/driver.rs20
-rw-r--r--src/librustc_driver/pretty.rs2
-rw-r--r--src/librustc_driver/test.rs102
-rw-r--r--src/librustc_lint/builtin.rs82
-rw-r--r--src/librustc_privacy/lib.rs34
-rw-r--r--src/librustc_trans/save/dump_csv.rs46
-rw-r--r--src/librustc_trans/save/mod.rs8
-rw-r--r--src/librustc_trans/trans/_match.rs49
-rw-r--r--src/librustc_trans/trans/adt.rs33
-rw-r--r--src/librustc_trans/trans/attributes.rs8
-rw-r--r--src/librustc_trans/trans/base.rs72
-rw-r--r--src/librustc_trans/trans/callee.rs71
-rw-r--r--src/librustc_trans/trans/closure.rs16
-rw-r--r--src/librustc_trans/trans/common.rs53
-rw-r--r--src/librustc_trans/trans/consts.rs58
-rw-r--r--src/librustc_trans/trans/context.rs8
-rw-r--r--src/librustc_trans/trans/datum.rs10
-rw-r--r--src/librustc_trans/trans/debuginfo/metadata.rs20
-rw-r--r--src/librustc_trans/trans/debuginfo/mod.rs8
-rw-r--r--src/librustc_trans/trans/debuginfo/namespace.rs4
-rw-r--r--src/librustc_trans/trans/debuginfo/type_names.rs8
-rw-r--r--src/librustc_trans/trans/declare.rs2
-rw-r--r--src/librustc_trans/trans/expr.rs76
-rw-r--r--src/librustc_trans/trans/foreign.rs26
-rw-r--r--src/librustc_trans/trans/glue.rs31
-rw-r--r--src/librustc_trans/trans/inline.rs11
-rw-r--r--src/librustc_trans/trans/intrinsic.rs14
-rw-r--r--src/librustc_trans/trans/meth.rs36
-rw-r--r--src/librustc_trans/trans/monomorphize.rs18
-rw-r--r--src/librustc_trans/trans/tvec.rs10
-rw-r--r--src/librustc_trans/trans/type_of.rs26
-rw-r--r--src/librustc_typeck/astconv.rs57
-rw-r--r--src/librustc_typeck/check/_match.rs68
-rw-r--r--src/librustc_typeck/check/assoc.rs4
-rw-r--r--src/librustc_typeck/check/callee.rs7
-rw-r--r--src/librustc_typeck/check/cast.rs9
-rw-r--r--src/librustc_typeck/check/closure.rs14
-rw-r--r--src/librustc_typeck/check/coercion.rs10
-rw-r--r--src/librustc_typeck/check/compare_method.rs28
-rw-r--r--src/librustc_typeck/check/dropck.rs36
-rw-r--r--src/librustc_typeck/check/method/confirm.rs16
-rw-r--r--src/librustc_typeck/check/method/mod.rs8
-rw-r--r--src/librustc_typeck/check/method/probe.rs41
-rw-r--r--src/librustc_typeck/check/method/suggest.rs25
-rw-r--r--src/librustc_typeck/check/mod.rs407
-rw-r--r--src/librustc_typeck/check/op.rs69
-rw-r--r--src/librustc_typeck/check/regionck.rs40
-rw-r--r--src/librustc_typeck/check/upvar.rs2
-rw-r--r--src/librustc_typeck/check/wf.rs61
-rw-r--r--src/librustc_typeck/check/writeback.rs12
-rw-r--r--src/librustc_typeck/coherence/mod.rs59
-rw-r--r--src/librustc_typeck/coherence/orphan.rs14
-rw-r--r--src/librustc_typeck/coherence/overlap.rs14
-rw-r--r--src/librustc_typeck/coherence/unsafety.rs4
-rw-r--r--src/librustc_typeck/collect.rs103
-rw-r--r--src/librustc_typeck/constrained_type_params.rs2
-rw-r--r--src/librustc_typeck/lib.rs20
-rw-r--r--src/librustc_typeck/variance.rs22
-rw-r--r--src/librustdoc/clean/inline.rs36
-rw-r--r--src/librustdoc/clean/mod.rs8
-rw-r--r--src/librustdoc/clean/simplify.rs5
107 files changed, 4634 insertions, 5143 deletions
diff --git a/src/librustc/metadata/encoder.rs b/src/librustc/metadata/encoder.rs
index b217eabec6e..b844717e613 100644
--- a/src/librustc/metadata/encoder.rs
+++ b/src/librustc/metadata/encoder.rs
@@ -23,7 +23,6 @@ use metadata::cstore;
 use metadata::decoder;
 use metadata::tyencode;
 use middle::def;
-use middle::ty::lookup_item_type;
 use middle::ty::{self, Ty};
 use middle::stability;
 use util::nodemap::{FnvHashMap, NodeMap, NodeSet};
@@ -133,7 +132,7 @@ pub fn def_to_string(did: DefId) -> String {
 fn encode_item_variances(rbml_w: &mut Encoder,
                          ecx: &EncodeContext,
                          id: NodeId) {
-    let v = ty::item_variances(ecx.tcx, ast_util::local_def(id));
+    let v = ecx.tcx.item_variances(ast_util::local_def(id));
     rbml_w.start_tag(tag_item_variances);
     v.encode(rbml_w);
     rbml_w.end_tag();
@@ -144,8 +143,8 @@ fn encode_bounds_and_type_for_item<'a, 'tcx>(rbml_w: &mut Encoder,
                                              id: ast::NodeId) {
     encode_bounds_and_type(rbml_w,
                            ecx,
-                           &ty::lookup_item_type(ecx.tcx, local_def(id)),
-                           &ty::lookup_predicates(ecx.tcx, local_def(id)));
+                           &ecx.tcx.lookup_item_type(local_def(id)),
+                           &ecx.tcx.lookup_predicates(local_def(id)));
 }
 
 fn encode_bounds_and_type<'a, 'tcx>(rbml_w: &mut Encoder,
@@ -293,8 +292,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
 
     let mut disr_val = 0;
     let mut i = 0;
-    let vi = ty::enum_variants(ecx.tcx,
-                               DefId { krate: ast::LOCAL_CRATE, node: id });
+    let vi = ecx.tcx.enum_variants(local_def(id));
     for variant in variants {
         let def_id = local_def(variant.node.id);
         index.push(entry {
@@ -319,7 +317,7 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
         match variant.node.kind {
             ast::TupleVariantKind(_) => {},
             ast::StructVariantKind(_) => {
-                let fields = ty::lookup_struct_fields(ecx.tcx, def_id);
+                let fields = ecx.tcx.lookup_struct_fields(def_id);
                 let idx = encode_info_for_struct(ecx,
                                                  rbml_w,
                                                  &fields[..],
@@ -328,9 +326,10 @@ fn encode_enum_variant_info(ecx: &EncodeContext,
                 encode_index(rbml_w, idx, write_i64);
             }
         }
-        if (*vi)[i].disr_val != disr_val {
-            encode_disr_val(ecx, rbml_w, (*vi)[i].disr_val);
-            disr_val = (*vi)[i].disr_val;
+        let specified_disr_val = vi[i].disr_val;
+        if specified_disr_val != disr_val {
+            encode_disr_val(ecx, rbml_w, specified_disr_val);
+            disr_val = specified_disr_val;
         }
         encode_bounds_and_type_for_item(rbml_w, ecx, def_id.local_id());
 
@@ -379,9 +378,7 @@ fn encode_reexported_static_base_methods(ecx: &EncodeContext,
         Some(implementations) => {
             for base_impl_did in implementations.iter() {
                 for &method_did in impl_items.get(base_impl_did).unwrap() {
-                    let impl_item = ty::impl_or_trait_item(
-                        ecx.tcx,
-                        method_did.def_id());
+                    let impl_item = ecx.tcx.impl_or_trait_item(method_did.def_id());
                     if let ty::MethodTraitItem(ref m) = impl_item {
                         encode_reexported_static_method(rbml_w,
                                                         exp,
@@ -875,7 +872,7 @@ fn encode_info_for_method<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
     if let Some(impl_item) = impl_item_opt {
         if let ast::MethodImplItem(ref sig, _) = impl_item.node {
             encode_attributes(rbml_w, &impl_item.attrs);
-            let scheme = ty::lookup_item_type(ecx.tcx, m.def_id);
+            let scheme = ecx.tcx.lookup_item_type(m.def_id);
             let any_types = !scheme.generics.types.is_empty();
             let needs_inline = any_types || is_default_impl ||
                                attr::requests_inline(&impl_item.attrs);
@@ -923,7 +920,7 @@ fn encode_info_for_associated_type<'a, 'tcx>(ecx: &EncodeContext<'a, 'tcx>,
         encode_attributes(rbml_w, &ii.attrs);
     } else {
         encode_predicates(rbml_w, ecx,
-                          &ty::lookup_predicates(ecx.tcx, associated_type.def_id),
+                          &ecx.tcx.lookup_predicates(associated_type.def_id),
                           tag_item_generics);
     }
 
@@ -995,7 +992,7 @@ fn encode_extension_implementations(ecx: &EncodeContext,
                                     rbml_w: &mut Encoder,
                                     trait_def_id: DefId) {
     assert!(ast_util::is_local(trait_def_id));
-    let def = ty::lookup_trait_def(ecx.tcx, trait_def_id);
+    let def = ecx.tcx.lookup_trait_def(trait_def_id);
 
     def.for_each_impl(ecx.tcx, |impl_def_id| {
         rbml_w.start_tag(tag_items_data_item_extension_impl);
@@ -1161,7 +1158,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                                  index);
       }
       ast::ItemStruct(ref struct_def, _) => {
-        let fields = ty::lookup_struct_fields(tcx, def_id);
+        let fields = tcx.lookup_struct_fields(def_id);
 
         /* First, encode the fields
            These come first because we need to write them to make
@@ -1220,7 +1217,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
           encode_name(rbml_w, item.ident.name);
           encode_unsafety(rbml_w, unsafety);
 
-          let trait_ref = ty::impl_trait_ref(tcx, local_def(item.id)).unwrap();
+          let trait_ref = tcx.impl_trait_ref(local_def(item.id)).unwrap();
           encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
           rbml_w.end_tag();
       }
@@ -1274,7 +1271,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             }
             rbml_w.end_tag();
         }
-        if let Some(trait_ref) = ty::impl_trait_ref(tcx, local_def(item.id)) {
+        if let Some(trait_ref) = tcx.impl_trait_ref(local_def(item.id)) {
             encode_trait_ref(rbml_w, ecx, trait_ref, tag_item_trait_ref);
         }
         encode_path(rbml_w, path.clone());
@@ -1298,7 +1295,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
                 pos: rbml_w.mark_stable_position(),
             });
 
-            match ty::impl_or_trait_item(tcx, trait_item_def_id.def_id()) {
+            match tcx.impl_or_trait_item(trait_item_def_id.def_id()) {
                 ty::ConstTraitItem(ref associated_const) => {
                     encode_info_for_associated_const(ecx,
                                                      rbml_w,
@@ -1333,22 +1330,22 @@ fn encode_info_for_item(ecx: &EncodeContext,
         encode_def_id(rbml_w, def_id);
         encode_family(rbml_w, 'I');
         encode_item_variances(rbml_w, ecx, item.id);
-        let trait_def = ty::lookup_trait_def(tcx, def_id);
-        let trait_predicates = ty::lookup_predicates(tcx, def_id);
+        let trait_def = tcx.lookup_trait_def(def_id);
+        let trait_predicates = tcx.lookup_predicates(def_id);
         encode_unsafety(rbml_w, trait_def.unsafety);
         encode_paren_sugar(rbml_w, trait_def.paren_sugar);
-        encode_defaulted(rbml_w, ty::trait_has_default_impl(tcx, def_id));
+        encode_defaulted(rbml_w, tcx.trait_has_default_impl(def_id));
         encode_associated_type_names(rbml_w, &trait_def.associated_type_names);
         encode_generics(rbml_w, ecx, &trait_def.generics, &trait_predicates,
                         tag_item_generics);
-        encode_predicates(rbml_w, ecx, &ty::lookup_super_predicates(tcx, def_id),
+        encode_predicates(rbml_w, ecx, &tcx.lookup_super_predicates(def_id),
                           tag_item_super_predicates);
         encode_trait_ref(rbml_w, ecx, trait_def.trait_ref, tag_item_trait_ref);
         encode_name(rbml_w, item.ident.name);
         encode_attributes(rbml_w, &item.attrs);
         encode_visibility(rbml_w, vis);
         encode_stability(rbml_w, stab);
-        for &method_def_id in ty::trait_item_def_ids(tcx, def_id).iter() {
+        for &method_def_id in tcx.trait_item_def_ids(def_id).iter() {
             rbml_w.start_tag(tag_item_trait_item);
             match method_def_id {
                 ty::ConstTraitItemId(const_def_id) => {
@@ -1380,7 +1377,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
         rbml_w.end_tag();
 
         // Now output the trait item info for each trait item.
-        let r = ty::trait_item_def_ids(tcx, def_id);
+        let r = tcx.trait_item_def_ids(def_id);
         for (i, &item_def_id) in r.iter().enumerate() {
             assert_eq!(item_def_id.def_id().krate, ast::LOCAL_CRATE);
 
@@ -1397,7 +1394,7 @@ fn encode_info_for_item(ecx: &EncodeContext,
             encode_stability(rbml_w, stab);
 
             let trait_item_type =
-                ty::impl_or_trait_item(tcx, item_def_id.def_id());
+                tcx.impl_or_trait_item(item_def_id.def_id());
             let is_nonstatic_method;
             match trait_item_type {
                 ty::ConstTraitItem(associated_const) => {
diff --git a/src/librustc/metadata/tydecode.rs b/src/librustc/metadata/tydecode.rs
index 63afdc8b0fc..a5b9e40593a 100644
--- a/src/librustc/metadata/tydecode.rs
+++ b/src/librustc/metadata/tydecode.rs
@@ -21,7 +21,7 @@ pub use self::DefIdSource::*;
 use middle::region;
 use middle::subst;
 use middle::subst::VecPerParamSpace;
-use middle::ty::{self, ToPredicate, Ty};
+use middle::ty::{self, ToPredicate, Ty, HasTypeFlags};
 
 use std::str;
 use syntax::abi;
@@ -471,14 +471,14 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
         let def = parse_def_(st, NominalType, conv);
         let substs = parse_substs_(st, conv);
         assert_eq!(next(st), ']');
-        return ty::mk_enum(tcx, def, st.tcx.mk_substs(substs));
+        return tcx.mk_enum(def, st.tcx.mk_substs(substs));
       }
       'x' => {
         assert_eq!(next(st), '[');
         let trait_ref = ty::Binder(parse_trait_ref_(st, conv));
         let bounds = parse_existential_bounds_(st, conv);
         assert_eq!(next(st), ']');
-        return ty::mk_trait(tcx, trait_ref, bounds);
+        return tcx.mk_trait(trait_ref, bounds);
       }
       'p' => {
         assert_eq!(next(st), '[');
@@ -487,38 +487,38 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
         let space = parse_param_space(st);
         assert_eq!(next(st), '|');
         let name = token::intern(&parse_str(st, ']'));
-        return ty::mk_param(tcx, space, index, name);
+        return tcx.mk_param(space, index, name);
       }
-      '~' => return ty::mk_uniq(tcx, parse_ty_(st, conv)),
-      '*' => return ty::mk_ptr(tcx, parse_mt_(st, conv)),
+      '~' => return tcx.mk_box(parse_ty_(st, conv)),
+      '*' => return tcx.mk_ptr(parse_mt_(st, conv)),
       '&' => {
         let r = parse_region_(st, conv);
         let mt = parse_mt_(st, conv);
-        return ty::mk_rptr(tcx, tcx.mk_region(r), mt);
+        return tcx.mk_ref(tcx.mk_region(r), mt);
       }
       'V' => {
         let t = parse_ty_(st, conv);
-        let sz = parse_size(st);
-        return ty::mk_vec(tcx, t, sz);
+        return match parse_size(st) {
+            Some(n) => tcx.mk_array(t, n),
+            None => tcx.mk_slice(t)
+        };
       }
       'v' => {
-        return ty::mk_str(tcx);
+        return tcx.mk_str();
       }
       'T' => {
         assert_eq!(next(st), '[');
         let mut params = Vec::new();
         while peek(st) != ']' { params.push(parse_ty_(st, conv)); }
         st.pos = st.pos + 1;
-        return ty::mk_tup(tcx, params);
+        return tcx.mk_tup(params);
       }
       'F' => {
           let def_id = parse_def_(st, NominalType, conv);
-          return ty::mk_bare_fn(tcx, Some(def_id),
-                                tcx.mk_bare_fn(parse_bare_fn_ty_(st, conv)));
+          return tcx.mk_fn(Some(def_id), tcx.mk_bare_fn(parse_bare_fn_ty_(st, conv)));
       }
       'G' => {
-          return ty::mk_bare_fn(tcx, None,
-                                tcx.mk_bare_fn(parse_bare_fn_ty_(st, conv)));
+          return tcx.mk_fn(None, tcx.mk_bare_fn(parse_bare_fn_ty_(st, conv)));
       }
       '#' => {
         let pos = parse_hex(st);
@@ -534,7 +534,7 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
             // If there is a closure buried in the type some where, then we
             // need to re-convert any def ids (see case 'k', below). That means
             // we can't reuse the cached version.
-            if !ty::type_has_ty_closure(tt) {
+            if !tt.has_closure_types() {
                 return tt;
             }
           }
@@ -558,20 +558,20 @@ fn parse_ty_<'a, 'tcx, F>(st: &mut PState<'a, 'tcx>, conv: &mut F) -> Ty<'tcx> w
           let did = parse_def_(st, NominalType, conv);
           let substs = parse_substs_(st, conv);
           assert_eq!(next(st), ']');
-          return ty::mk_struct(st.tcx, did, st.tcx.mk_substs(substs));
+          return st.tcx.mk_struct(did, st.tcx.mk_substs(substs));
       }
       'k' => {
           assert_eq!(next(st), '[');
           let did = parse_def_(st, ClosureSource, conv);
           let substs = parse_substs_(st, conv);
           assert_eq!(next(st), ']');
-          return ty::mk_closure(st.tcx, did, st.tcx.mk_substs(substs));
+          return st.tcx.mk_closure(did, st.tcx.mk_substs(substs));
       }
       'P' => {
           assert_eq!(next(st), '[');
           let trait_ref = parse_trait_ref_(st, conv);
           let name = token::intern(&parse_str(st, ']'));
-          return ty::mk_projection(tcx, trait_ref, name);
+          return tcx.mk_projection(trait_ref, name);
       }
       'e' => {
           return tcx.types.err;
diff --git a/src/librustc/middle/astconv_util.rs b/src/librustc/middle/astconv_util.rs
index 33d37b28589..fb0131f258d 100644
--- a/src/librustc/middle/astconv_util.rs
+++ b/src/librustc/middle/astconv_util.rs
@@ -49,10 +49,10 @@ pub fn prim_ty_to_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
     match nty {
         ast::TyBool => tcx.types.bool,
         ast::TyChar => tcx.types.char,
-        ast::TyInt(it) => ty::mk_mach_int(tcx, it),
-        ast::TyUint(uit) => ty::mk_mach_uint(tcx, uit),
-        ast::TyFloat(ft) => ty::mk_mach_float(tcx, ft),
-        ast::TyStr => ty::mk_str(tcx)
+        ast::TyInt(it) => tcx.mk_mach_int(it),
+        ast::TyUint(uit) => tcx.mk_mach_uint(uit),
+        ast::TyFloat(ft) => tcx.mk_mach_float(ft),
+        ast::TyStr => tcx.mk_str()
     }
 }
 
diff --git a/src/librustc/middle/cast.rs b/src/librustc/middle/cast.rs
index 34088d5f13e..ec1fd67616b 100644
--- a/src/librustc/middle/cast.rs
+++ b/src/librustc/middle/cast.rs
@@ -66,8 +66,8 @@ impl<'tcx> CastTy<'tcx> {
             ty::TyInt(_) => Some(CastTy::Int(IntTy::I)),
             ty::TyUint(u) => Some(CastTy::Int(IntTy::U(u))),
             ty::TyFloat(_) => Some(CastTy::Float),
-            ty::TyEnum(..) if ty::type_is_c_like_enum(
-                tcx, t) => Some(CastTy::Int(IntTy::CEnum)),
+            ty::TyEnum(..) if t.is_c_like_enum(tcx) =>
+                Some(CastTy::Int(IntTy::CEnum)),
             ty::TyRawPtr(ref mt) => Some(CastTy::Ptr(mt)),
             ty::TyRef(_, ref mt) => Some(CastTy::RPtr(mt)),
             ty::TyBareFn(..) => Some(CastTy::FnPtr),
diff --git a/src/librustc/middle/cfg/construct.rs b/src/librustc/middle/cfg/construct.rs
index e782a03176d..801b3a721e4 100644
--- a/src/librustc/middle/cfg/construct.rs
+++ b/src/librustc/middle/cfg/construct.rs
@@ -411,14 +411,14 @@ impl<'a, 'tcx> CFGBuilder<'a, 'tcx> {
             func_or_rcvr: &ast::Expr,
             args: I) -> CFGIndex {
         let method_call = ty::MethodCall::expr(call_expr.id);
-        let return_ty = ty::ty_fn_ret(match self.tcx.method_map.borrow().get(&method_call) {
+        let fn_ty = match self.tcx.method_map.borrow().get(&method_call) {
             Some(method) => method.ty,
-            None => ty::expr_ty_adjusted(self.tcx, func_or_rcvr)
-        });
+            None => self.tcx.expr_ty_adjusted(func_or_rcvr)
+        };
 
         let func_or_rcvr_exit = self.expr(func_or_rcvr, pred);
         let ret = self.straightline(call_expr, func_or_rcvr_exit, args);
-        if return_ty.diverges() {
+        if fn_ty.fn_ret().diverges() {
             self.add_unreachable_node()
         } else {
             ret
diff --git a/src/librustc/middle/check_const.rs b/src/librustc/middle/check_const.rs
index 8af6946d3c3..62bf1648725 100644
--- a/src/librustc/middle/check_const.rs
+++ b/src/librustc/middle/check_const.rs
@@ -115,7 +115,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
     {
         let param_env = match item_id {
             Some(item_id) => ty::ParameterEnvironment::for_item(self.tcx, item_id),
-            None => ty::empty_parameter_environment(self.tcx)
+            None => self.tcx.empty_parameter_environment()
         };
         f(&mut euv::ExprUseVisitor::new(self, &param_env))
     }
@@ -231,7 +231,7 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
                                       fn_like.id());
             self.add_qualif(qualif);
 
-            if ty::type_contents(self.tcx, ret_ty).interior_unsafe() {
+            if ret_ty.type_contents(self.tcx).interior_unsafe() {
                 self.add_qualif(ConstQualif::MUTABLE_MEM);
             }
 
@@ -266,8 +266,8 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
     }
 
     fn check_static_mut_type(&self, e: &ast::Expr) {
-        let node_ty = ty::node_id_to_type(self.tcx, e.id);
-        let tcontents = ty::type_contents(self.tcx, node_ty);
+        let node_ty = self.tcx.node_id_to_type(e.id);
+        let tcontents = node_ty.type_contents(self.tcx);
 
         let suffix = if tcontents.has_dtor() {
             "destructors"
@@ -282,12 +282,12 @@ impl<'a, 'tcx> CheckCrateVisitor<'a, 'tcx> {
     }
 
     fn check_static_type(&self, e: &ast::Expr) {
-        let ty = ty::node_id_to_type(self.tcx, e.id);
+        let ty = self.tcx.node_id_to_type(e.id);
         let infcx = infer::new_infer_ctxt(self.tcx);
         let mut fulfill_cx = traits::FulfillmentContext::new(false);
         let cause = traits::ObligationCause::new(e.span, e.id, traits::SharedStatic);
         fulfill_cx.register_builtin_bound(&infcx, ty, ty::BoundSync, cause);
-        let env = ty::empty_parameter_environment(self.tcx);
+        let env = self.tcx.empty_parameter_environment();
         match fulfill_cx.select_all_or_error(&infcx, &env) {
             Ok(()) => { },
             Err(ref errors) => {
@@ -402,7 +402,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
         let mut outer = self.qualif;
         self.qualif = ConstQualif::empty();
 
-        let node_ty = ty::node_id_to_type(self.tcx, ex.id);
+        let node_ty = self.tcx.node_id_to_type(ex.id);
         check_expr(self, ex, node_ty);
 
         // Special-case some expressions to avoid certain flags bubbling up.
@@ -479,7 +479,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for CheckCrateVisitor<'a, 'tcx> {
                 // initializer values (very bad).
                 // If the type doesn't have interior mutability, then `ConstQualif::MUTABLE_MEM` has
                 // propagated from another error, so erroring again would be just noise.
-                let tc = ty::type_contents(self.tcx, node_ty);
+                let tc = node_ty.type_contents(self.tcx);
                 if self.qualif.intersects(ConstQualif::MUTABLE_MEM) && tc.interior_unsafe() {
                     outer = outer | ConstQualif::NOT_CONST;
                     if self.mode != Mode::Var {
@@ -529,7 +529,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
                         e: &ast::Expr, node_ty: Ty<'tcx>) {
     match node_ty.sty {
         ty::TyStruct(did, _) |
-        ty::TyEnum(did, _) if ty::has_dtor(v.tcx, did) => {
+        ty::TyEnum(did, _) if v.tcx.has_dtor(did) => {
             v.add_qualif(ConstQualif::NEEDS_DROP);
             if v.mode != Mode::Var {
                 v.tcx.sess.span_err(e.span,
@@ -560,7 +560,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             }
         }
         ast::ExprUnary(op, ref inner) => {
-            match ty::node_id_to_type(v.tcx, inner.id).sty {
+            match v.tcx.node_id_to_type(inner.id).sty {
                 ty::TyRawPtr(_) => {
                     assert!(op == ast::UnDeref);
 
@@ -574,7 +574,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
             }
         }
         ast::ExprBinary(op, ref lhs, _) => {
-            match ty::node_id_to_type(v.tcx, lhs.id).sty {
+            match v.tcx.node_id_to_type(lhs.id).sty {
                 ty::TyRawPtr(_) => {
                     assert!(op.node == ast::BiEq || op.node == ast::BiNe ||
                             op.node == ast::BiLe || op.node == ast::BiLt ||
@@ -731,7 +731,7 @@ fn check_expr<'a, 'tcx>(v: &mut CheckCrateVisitor<'a, 'tcx>,
         ast::ExprClosure(..) => {
             // Paths in constant contexts cannot refer to local variables,
             // as there are none, and thus closures can't have upvars there.
-            if ty::with_freevars(v.tcx, e.id, |fv| !fv.is_empty()) {
+            if v.tcx.with_freevars(e.id, |fv| !fv.is_empty()) {
                 assert!(v.mode == Mode::Var,
                         "global closures can't capture anything");
                 v.add_qualif(ConstQualif::NOT_CONST);
diff --git a/src/librustc/middle/check_match.rs b/src/librustc/middle/check_match.rs
index 1ec6e0d6d80..d2b3b83e4f4 100644
--- a/src/librustc/middle/check_match.rs
+++ b/src/librustc/middle/check_match.rs
@@ -20,7 +20,7 @@ use middle::expr_use_visitor::{ConsumeMode, Delegate, ExprUseVisitor, Init};
 use middle::expr_use_visitor::{JustWrite, LoanCause, MutateMode};
 use middle::expr_use_visitor::WriteAndRead;
 use middle::expr_use_visitor as euv;
-use middle::mem_categorization::cmt;
+use middle::mem_categorization::{cmt, Typer};
 use middle::pat_util::*;
 use middle::ty::*;
 use middle::ty;
@@ -149,7 +149,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for MatchCheckCtxt<'a, 'tcx> {
 pub fn check_crate(tcx: &ty::ctxt) {
     visit::walk_crate(&mut MatchCheckCtxt {
         tcx: tcx,
-        param_env: ty::empty_parameter_environment(tcx),
+        param_env: tcx.empty_parameter_environment(),
     }, tcx.map.krate());
     tcx.sess.abort_if_errors();
 }
@@ -203,9 +203,9 @@ fn check_expr(cx: &mut MatchCheckCtxt, ex: &ast::Expr) {
 
             // Finally, check if the whole match expression is exhaustive.
             // Check for empty enum, because is_useful only works on inhabited types.
-            let pat_ty = node_id_to_type(cx.tcx, scrut.id);
+            let pat_ty = cx.tcx.node_id_to_type(scrut.id);
             if inlined_arms.is_empty() {
-                if !type_is_empty(cx.tcx, pat_ty) {
+                if !pat_ty.is_empty(cx.tcx) {
                     // We know the type is inhabited, so this must be wrong
                     span_err!(cx.tcx.sess, ex.span, E0002,
                               "non-exhaustive patterns: type {} is non-empty",
@@ -231,11 +231,11 @@ fn check_for_bindings_named_the_same_as_variants(cx: &MatchCheckCtxt, pat: &Pat)
     ast_util::walk_pat(pat, |p| {
         match p.node {
             ast::PatIdent(ast::BindByValue(ast::MutImmutable), ident, None) => {
-                let pat_ty = ty::pat_ty(cx.tcx, p);
+                let pat_ty = cx.tcx.pat_ty(p);
                 if let ty::TyEnum(def_id, _) = pat_ty.sty {
                     let def = cx.tcx.def_map.borrow().get(&p.id).map(|d| d.full_def());
                     if let Some(DefLocal(_)) = def {
-                        if ty::enum_variants(cx.tcx, def_id).iter().any(|variant|
+                        if cx.tcx.enum_variants(def_id).iter().any(|variant|
                             token::get_name(variant.name) == token::get_name(ident.node.name)
                                 && variant.args.is_empty()
                         ) {
@@ -509,12 +509,12 @@ fn construct_witness(cx: &MatchCheckCtxt, ctor: &Constructor,
         ty::TyEnum(cid, _) | ty::TyStruct(cid, _)  => {
             let (vid, is_structure) = match ctor {
                 &Variant(vid) =>
-                    (vid, ty::enum_variant_with_id(cx.tcx, cid, vid).arg_names.is_some()),
+                    (vid, cx.tcx.enum_variant_with_id(cid, vid).arg_names.is_some()),
                 _ =>
-                    (cid, !ty::is_tuple_struct(cx.tcx, cid))
+                    (cid, !cx.tcx.is_tuple_struct(cid))
             };
             if is_structure {
-                let fields = ty::lookup_struct_fields(cx.tcx, vid);
+                let fields = cx.tcx.lookup_struct_fields(vid);
                 let field_pats: Vec<_> = fields.into_iter()
                     .zip(pats)
                     .filter(|&(_, ref pat)| pat.node != ast::PatWild(ast::PatWildSingle))
@@ -605,7 +605,7 @@ fn all_constructors(cx: &MatchCheckCtxt, left_ty: Ty,
         },
 
         ty::TyEnum(eid, _) =>
-            ty::enum_variants(cx.tcx, eid)
+            cx.tcx.enum_variants(eid)
                 .iter()
                 .map(|va| Variant(va.id))
                 .collect(),
@@ -651,12 +651,14 @@ fn is_useful(cx: &MatchCheckCtxt,
         None => v[0]
     };
     let left_ty = if real_pat.id == DUMMY_NODE_ID {
-        ty::mk_nil(cx.tcx)
+        cx.tcx.mk_nil()
     } else {
-        let left_ty = ty::pat_ty(cx.tcx, &*real_pat);
+        let left_ty = cx.tcx.pat_ty(&*real_pat);
 
         match real_pat.node {
-            ast::PatIdent(ast::BindByRef(..), _, _) => ty::deref(left_ty, false).unwrap().ty,
+            ast::PatIdent(ast::BindByRef(..), _, _) => {
+                left_ty.builtin_deref(false).unwrap().ty
+            }
             _ => left_ty,
         }
     };
@@ -815,11 +817,11 @@ pub fn constructor_arity(cx: &MatchCheckCtxt, ctor: &Constructor, ty: Ty) -> usi
         },
         ty::TyEnum(eid, _) => {
             match *ctor {
-                Variant(id) => enum_variant_with_id(cx.tcx, eid, id).args.len(),
+                Variant(id) => cx.tcx.enum_variant_with_id(eid, id).args.len(),
                 _ => unreachable!()
             }
         }
-        ty::TyStruct(cid, _) => ty::lookup_struct_fields(cx.tcx, cid).len(),
+        ty::TyStruct(cid, _) => cx.tcx.lookup_struct_fields(cid).len(),
         ty::TyArray(_, n) => n,
         _ => 0
     }
@@ -911,7 +913,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
                 },
                 _ => {
                     // Assume this is a struct.
-                    match ty::ty_to_def_id(node_id_to_type(cx.tcx, pat_id)) {
+                    match cx.tcx.node_id_to_type(pat_id).ty_to_def_id() {
                         None => {
                             cx.tcx.sess.span_bug(pat_span,
                                                  "struct pattern wasn't of a \
@@ -922,7 +924,7 @@ pub fn specialize<'a>(cx: &MatchCheckCtxt, r: &[&'a Pat],
                 }
             };
             class_id.map(|variant_id| {
-                let struct_fields = ty::lookup_struct_fields(cx.tcx, variant_id);
+                let struct_fields = cx.tcx.lookup_struct_fields(variant_id);
                 let args = struct_fields.iter().map(|sf| {
                     match pattern_fields.iter().find(|f| f.node.ident.name == sf.name) {
                         Some(ref f) => &*f.node.pat,
@@ -1107,8 +1109,8 @@ fn check_legality_of_move_bindings(cx: &MatchCheckCtxt,
             if pat_is_binding(def_map, &*p) {
                 match p.node {
                     ast::PatIdent(ast::BindByValue(_), _, ref sub) => {
-                        let pat_ty = ty::node_id_to_type(tcx, p.id);
-                        if ty::type_moves_by_default(&cx.param_env, pat.span, pat_ty) {
+                        let pat_ty = tcx.node_id_to_type(p.id);
+                        if cx.param_env.type_moves_by_default(pat_ty, pat.span) {
                             check_move(p, sub.as_ref().map(|p| &**p));
                         }
                     }
diff --git a/src/librustc/middle/check_rvalues.rs b/src/librustc/middle/check_rvalues.rs
index f5934751c58..1489e946fe2 100644
--- a/src/librustc/middle/check_rvalues.rs
+++ b/src/librustc/middle/check_rvalues.rs
@@ -59,7 +59,7 @@ impl<'a, 'tcx> euv::Delegate<'tcx> for RvalueContextDelegate<'a, 'tcx> {
                cmt: mc::cmt<'tcx>,
                _: euv::ConsumeMode) {
         debug!("consume; cmt: {:?}; type: {:?}", *cmt, cmt.ty);
-        if !ty::type_is_sized(Some(self.param_env), self.tcx, span, cmt.ty) {
+        if !cmt.ty.is_sized(self.param_env, span) {
             span_err!(self.tcx.sess, span, E0161,
                 "cannot move a value of type {0}: the size of {0} cannot be statically determined",
                 cmt.ty);
diff --git a/src/librustc/middle/const_eval.rs b/src/librustc/middle/const_eval.rs
index ed06ccf1ec6..1b1725dd15c 100644
--- a/src/librustc/middle/const_eval.rs
+++ b/src/librustc/middle/const_eval.rs
@@ -126,9 +126,9 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                         // `resolve_trait_associated_const` will select an impl
                         // or the default.
                         Some(ref_id) => {
-                            let trait_id = ty::trait_of_item(tcx, def_id)
+                            let trait_id = tcx.trait_of_item(def_id)
                                               .unwrap();
-                            let substs = ty::node_id_item_substs(tcx, ref_id)
+                            let substs = tcx.node_id_item_substs(ref_id)
                                             .substs;
                             resolve_trait_associated_const(tcx, ti, trait_id,
                                                            substs)
@@ -176,7 +176,7 @@ pub fn lookup_const_by_id<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
                         // a trait-associated const if the caller gives us
                         // the expression that refers to it.
                         Some(ref_id) => {
-                            let substs = ty::node_id_item_substs(tcx, ref_id)
+                            let substs = tcx.node_id_item_substs(ref_id)
                                             .substs;
                             resolve_trait_associated_const(tcx, ti, trait_id,
                                                            substs).map(|e| e.id)
@@ -714,7 +714,7 @@ pub fn eval_const_expr_partial<'tcx>(tcx: &ty::ctxt<'tcx>,
                                      e: &Expr,
                                      ty_hint: Option<Ty<'tcx>>) -> EvalResult {
     eval_const_expr_with_substs(tcx, e, ty_hint, |id| {
-        ty::node_id_item_substs(tcx, id).substs
+        tcx.node_id_item_substs(id).substs
     })
 }
 
@@ -725,7 +725,7 @@ pub fn eval_const_expr_with_substs<'tcx, S>(tcx: &ty::ctxt<'tcx>,
         where S: Fn(ast::NodeId) -> subst::Substs<'tcx> {
     fn fromb(b: bool) -> ConstVal { Int(b as i64) }
 
-    let ety = ty_hint.or_else(|| ty::expr_ty_opt(tcx, e));
+    let ety = ty_hint.or_else(|| tcx.expr_ty_opt(e));
 
     // If type of expression itself is int or uint, normalize in these
     // bindings so that isize/usize is mapped to a type with an
@@ -882,7 +882,7 @@ pub fn eval_const_expr_with_substs<'tcx, S>(tcx: &ty::ctxt<'tcx>,
         // FIXME (#23833): the type-hint can cause problems,
         // e.g. `(i8::MAX + 1_i8) as u32` feeds in `u32` as result
         // type to the sum, and thus no overflow is signaled.
-        let base_hint = ty::expr_ty_opt(tcx, &**base).unwrap_or(ety);
+        let base_hint = tcx.expr_ty_opt(&**base).unwrap_or(ety);
         let val = try!(eval_const_expr_partial(tcx, &**base, Some(base_hint)));
         match cast_const(tcx, val, ety) {
             Ok(val) => val,
@@ -1030,10 +1030,10 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
     let trait_ref = ty::Binder(ty::TraitRef { def_id: trait_id,
                                               substs: trait_substs });
 
-    ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
+    tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
     let infcx = infer::new_infer_ctxt(tcx);
 
-    let param_env = ty::empty_parameter_environment(tcx);
+    let param_env = tcx.empty_parameter_environment();
     let mut selcx = traits::SelectionContext::new(&infcx, &param_env);
     let obligation = traits::Obligation::new(traits::ObligationCause::dummy(),
                                              trait_ref.to_poly_trait_predicate());
@@ -1056,7 +1056,7 @@ fn resolve_trait_associated_const<'a, 'tcx: 'a>(tcx: &'a ty::ctxt<'tcx>,
 
     match selection {
         traits::VtableImpl(ref impl_data) => {
-            match ty::associated_consts(tcx, impl_data.impl_def_id)
+            match tcx.associated_consts(impl_data.impl_def_id)
                      .iter().find(|ic| ic.name == ti.ident.name) {
                 Some(ic) => lookup_const_by_id(tcx, ic.def_id, None),
                 None => match ti.node {
diff --git a/src/librustc/middle/dead.rs b/src/librustc/middle/dead.rs
index fd810429c86..bd8b8afbdfe 100644
--- a/src/librustc/middle/dead.rs
+++ b/src/librustc/middle/dead.rs
@@ -100,7 +100,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
             Some(method) => {
                 match method.origin {
                     ty::MethodStatic(def_id) => {
-                        match ty::provided_source(self.tcx, def_id) {
+                        match self.tcx.provided_source(def_id) {
                             Some(p_did) => self.check_def_id(p_did),
                             None => self.check_def_id(def_id)
                         }
@@ -116,9 +116,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                         method_num: index,
                         ..
                     }) => {
-                        let trait_item = ty::trait_item(self.tcx,
-                                                        trait_ref.def_id,
-                                                        index);
+                        let trait_item = self.tcx.trait_item(trait_ref.def_id, index);
                         self.check_def_id(trait_item.def_id());
                     }
                 }
@@ -132,9 +130,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
     }
 
     fn handle_field_access(&mut self, lhs: &ast::Expr, name: ast::Name) {
-        match ty::expr_ty_adjusted(self.tcx, lhs).sty {
+        match self.tcx.expr_ty_adjusted(lhs).sty {
             ty::TyStruct(id, _) => {
-                let fields = ty::lookup_struct_fields(self.tcx, id);
+                let fields = self.tcx.lookup_struct_fields(id);
                 let field_id = fields.iter()
                     .find(|field| field.name == name).unwrap().id;
                 self.live_symbols.insert(field_id.node);
@@ -144,9 +142,9 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
     }
 
     fn handle_tup_field_access(&mut self, lhs: &ast::Expr, idx: usize) {
-        match ty::expr_ty_adjusted(self.tcx, lhs).sty {
+        match self.tcx.expr_ty_adjusted(lhs).sty {
             ty::TyStruct(id, _) => {
-                let fields = ty::lookup_struct_fields(self.tcx, id);
+                let fields = self.tcx.lookup_struct_fields(id);
                 let field_id = fields[idx].id;
                 self.live_symbols.insert(field_id.node);
             },
@@ -159,8 +157,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
         let id = match self.tcx.def_map.borrow().get(&lhs.id).unwrap().full_def() {
             def::DefVariant(_, id, _) => id,
             _ => {
-                match ty::ty_to_def_id(ty::node_id_to_type(self.tcx,
-                                                           lhs.id)) {
+                match self.tcx.node_id_to_type(lhs.id).ty_to_def_id() {
                     None => {
                         self.tcx.sess.span_bug(lhs.span,
                                                "struct pattern wasn't of a \
@@ -170,7 +167,7 @@ impl<'a, 'tcx> MarkSymbolVisitor<'a, 'tcx> {
                 }
             }
         };
-        let fields = ty::lookup_struct_fields(self.tcx, id);
+        let fields = self.tcx.lookup_struct_fields(id);
         for pat in pats {
             if let ast::PatWild(ast::PatWildSingle) = pat.node.pat.node {
                 continue;
@@ -480,8 +477,8 @@ impl<'a, 'tcx> DeadVisitor<'a, 'tcx> {
 
     fn should_warn_about_field(&mut self, node: &ast::StructField_) -> bool {
         let is_named = node.ident().is_some();
-        let field_type = ty::node_id_to_type(self.tcx, node.id);
-        let is_marker_field = match ty::ty_to_def_id(field_type) {
+        let field_type = self.tcx.node_id_to_type(node.id);
+        let is_marker_field = match field_type.ty_to_def_id() {
             Some(def_id) => self.tcx.lang_items.items().any(|(_, item)| *item == Some(def_id)),
             _ => false
         };
diff --git a/src/librustc/middle/effect.rs b/src/librustc/middle/effect.rs
index bb63ec42d8c..c48d5d5da40 100644
--- a/src/librustc/middle/effect.rs
+++ b/src/librustc/middle/effect.rs
@@ -62,7 +62,7 @@ impl<'a, 'tcx> EffectCheckVisitor<'a, 'tcx> {
 
     fn check_str_index(&mut self, e: &ast::Expr) {
         let base_type = match e.node {
-            ast::ExprIndex(ref base, _) => ty::node_id_to_type(self.tcx, base.id),
+            ast::ExprIndex(ref base, _) => self.tcx.node_id_to_type(base.id),
             _ => return
         };
         debug!("effect: checking index with base type {:?}",
@@ -149,7 +149,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 }
             }
             ast::ExprCall(ref base, _) => {
-                let base_type = ty::node_id_to_type(self.tcx, base.id);
+                let base_type = self.tcx.node_id_to_type(base.id);
                 debug!("effect: call case, base type is {:?}",
                         base_type);
                 if type_is_unsafe_function(base_type) {
@@ -157,7 +157,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 }
             }
             ast::ExprUnary(ast::UnDeref, ref base) => {
-                let base_type = ty::node_id_to_type(self.tcx, base.id);
+                let base_type = self.tcx.node_id_to_type(base.id);
                 debug!("effect: unary case, base type is {:?}",
                         base_type);
                 if let ty::TyRawPtr(_) = base_type.sty {
@@ -174,7 +174,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EffectCheckVisitor<'a, 'tcx> {
                 self.require_unsafe(expr.span, "use of inline assembly");
             }
             ast::ExprPath(..) => {
-                if let def::DefStatic(_, true) = ty::resolve_expr(self.tcx, expr) {
+                if let def::DefStatic(_, true) = self.tcx.resolve_expr(expr) {
                     self.require_unsafe(expr.span, "use of mutable static");
                 }
             }
diff --git a/src/librustc/middle/expr_use_visitor.rs b/src/librustc/middle/expr_use_visitor.rs
index ab67c68be12..a15d02ea296 100644
--- a/src/librustc/middle/expr_use_visitor.rs
+++ b/src/librustc/middle/expr_use_visitor.rs
@@ -229,7 +229,7 @@ impl OverloadedCallType {
 
     fn from_method_id(tcx: &ty::ctxt, method_id: ast::DefId)
                       -> OverloadedCallType {
-        let method_descriptor = match ty::impl_or_trait_item(tcx, method_id) {
+        let method_descriptor = match tcx.impl_or_trait_item(method_id) {
             ty::MethodTraitItem(ref method_descriptor) => {
                 (*method_descriptor).clone()
             }
@@ -244,7 +244,7 @@ impl OverloadedCallType {
             }
             ty::ImplContainer(impl_id) => impl_id,
         };
-        let trait_ref = match ty::impl_trait_ref(tcx, impl_id) {
+        let trait_ref = match tcx.impl_trait_ref(impl_id) {
             None => {
                 tcx.sess.bug("statically resolved overloaded call impl \
                               didn't implement a trait?!")
@@ -502,9 +502,10 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                 // make sure that the thing we are pointing out stays valid
                 // for the lifetime `scope_r` of the resulting ptr:
                 let expr_ty = return_if_err!(self.typer.node_ty(expr.id));
-                let r = ty::ty_region(self.tcx(), expr.span, expr_ty);
-                let bk = ty::BorrowKind::from_mutbl(m);
-                self.borrow_expr(&**base, r, bk, AddrOf);
+                if let ty::TyRef(&r, _) = expr_ty.sty {
+                    let bk = ty::BorrowKind::from_mutbl(m);
+                    self.borrow_expr(&**base, r, bk, AddrOf);
+                }
             }
 
             ast::ExprInlineAsm(ref ia) => {
@@ -740,7 +741,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
         // expression that will actually be used
         let with_fields = match with_cmt.ty.sty {
             ty::TyStruct(did, substs) => {
-                ty::struct_fields(self.tcx(), did, substs)
+                self.tcx().struct_fields(did, substs)
             }
             _ => {
                 // the base expression should always evaluate to a
@@ -821,8 +822,8 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
 
                     // the method call infrastructure should have
                     // replaced all late-bound regions with variables:
-                    let self_ty = ty::ty_fn_sig(method_ty).input(0);
-                    let self_ty = ty::no_late_bound_regions(self.tcx(), &self_ty).unwrap();
+                    let self_ty = method_ty.fn_sig().input(0);
+                    let self_ty = self.tcx().no_late_bound_regions(&self_ty).unwrap();
 
                     let (m, r) = match self_ty.sty {
                         ty::TyRef(r, ref m) => (m.mutbl, r),
@@ -922,10 +923,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
         // This is always an rvalue, since we are producing a new
         // (temporary) indirection.
 
-        let adj_ty =
-            ty::adjust_ty_for_autoref(self.tcx(),
-                                      cmt_base_ty,
-                                      opt_autoref);
+        let adj_ty = cmt_base_ty.adjust_for_autoref(self.tcx(), opt_autoref);
 
         self.mc.cat_rvalue_node(expr.id, expr.span, adj_ty)
     }
@@ -1074,12 +1072,11 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
                 // It is also a borrow or copy/move of the value being matched.
                 match pat.node {
                     ast::PatIdent(ast::BindByRef(m), _, _) => {
-                        let (r, bk) = {
-                            (ty::ty_region(tcx, pat.span, pat_ty),
-                             ty::BorrowKind::from_mutbl(m))
-                        };
-                        delegate.borrow(pat.id, pat.span, cmt_pat,
-                                             r, bk, RefBinding);
+                        if let ty::TyRef(&r, _) = pat_ty.sty {
+                            let bk = ty::BorrowKind::from_mutbl(m);
+                            delegate.borrow(pat.id, pat.span, cmt_pat,
+                                            r, bk, RefBinding);
+                        }
                     }
                     ast::PatIdent(ast::BindByValue(_), _, _) => {
                         let mode = copy_or_move(typer, &cmt_pat, PatBindingMove);
@@ -1152,7 +1149,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
 
                         Some(def::DefVariant(enum_did, variant_did, _is_struct)) => {
                             let downcast_cmt =
-                                if ty::enum_is_univariant(tcx, enum_did) {
+                                if tcx.enum_is_univariant(enum_did) {
                                     cmt_pat
                                 } else {
                                     let cmt_pat_ty = cmt_pat.ty;
@@ -1238,7 +1235,7 @@ impl<'d,'t,'tcx,TYPER:mc::Typer<'tcx>> ExprUseVisitor<'d,'t,'tcx,TYPER> {
     fn walk_captures(&mut self, closure_expr: &ast::Expr) {
         debug!("walk_captures({:?})", closure_expr);
 
-        ty::with_freevars(self.tcx(), closure_expr.id, |freevars| {
+        self.tcx().with_freevars(closure_expr.id, |freevars| {
             for freevar in freevars {
                 let id_var = freevar.def.def_id().node;
                 let upvar_id = ty::UpvarId { var_id: id_var,
@@ -1283,7 +1280,7 @@ fn copy_or_move<'tcx>(typer: &mc::Typer<'tcx>,
                       move_reason: MoveReason)
                       -> ConsumeMode
 {
-    if typer.type_moves_by_default(cmt.span, cmt.ty) {
+    if typer.type_moves_by_default(cmt.ty, cmt.span) {
         Move(move_reason)
     } else {
         Copy
diff --git a/src/librustc/middle/implicator.rs b/src/librustc/middle/implicator.rs
index f87b121eb22..d5fa885b16a 100644
--- a/src/librustc/middle/implicator.rs
+++ b/src/librustc/middle/implicator.rs
@@ -112,7 +112,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
 
             ty::TyEnum(def_id, substs) |
             ty::TyStruct(def_id, substs) => {
-                let item_scheme = ty::lookup_item_type(self.tcx(), def_id);
+                let item_scheme = self.tcx().lookup_item_type(def_id);
                 self.accumulate_from_adt(ty, def_id, &item_scheme.generics, substs)
             }
 
@@ -236,7 +236,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
                            substs: &Substs<'tcx>)
     {
         let predicates =
-            ty::lookup_predicates(self.tcx(), def_id).instantiate(self.tcx(), substs);
+            self.tcx().lookup_predicates(def_id).instantiate(self.tcx(), substs);
         let predicates = match self.fully_normalize(&predicates) {
             Ok(predicates) => predicates,
             Err(ErrorReported) => { return; }
@@ -250,7 +250,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
                 ty::Predicate::Equate(..) => { }
                 ty::Predicate::Projection(..) => { }
                 ty::Predicate::RegionOutlives(ref data) => {
-                    match ty::no_late_bound_regions(self.tcx(), data) {
+                    match self.tcx().no_late_bound_regions(data) {
                         None => { }
                         Some(ty::OutlivesPredicate(r_a, r_b)) => {
                             self.push_sub_region_constraint(Some(ty), r_b, r_a);
@@ -258,7 +258,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
                     }
                 }
                 ty::Predicate::TypeOutlives(ref data) => {
-                    match ty::no_late_bound_regions(self.tcx(), data) {
+                    match self.tcx().no_late_bound_regions(data) {
                         None => { }
                         Some(ty::OutlivesPredicate(ty_a, r_b)) => {
                             self.stack.push((r_b, Some(ty)));
@@ -275,7 +275,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
                                     .map(|pred| Implication::Predicate(def_id, pred));
         self.out.extend(obligations);
 
-        let variances = ty::item_variances(self.tcx(), def_id);
+        let variances = self.tcx().item_variances(def_id);
 
         for (&region, &variance) in substs.regions().iter().zip(&variances.regions) {
             match variance {
@@ -316,7 +316,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
                data);
 
         for poly_trait_ref in traits::supertraits(self.tcx(), data.to_poly_trait_ref()) {
-            match ty::no_late_bound_regions(self.tcx(), &poly_trait_ref) {
+            match self.tcx().no_late_bound_regions(&poly_trait_ref) {
                 Some(trait_ref) => { self.accumulate_from_assoc_types(trait_ref); }
                 None => { }
             }
@@ -330,11 +330,11 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
                trait_ref);
 
         let trait_def_id = trait_ref.def_id;
-        let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
+        let trait_def = self.tcx().lookup_trait_def(trait_def_id);
         let assoc_type_projections: Vec<_> =
             trait_def.associated_type_names
                      .iter()
-                     .map(|&name| ty::mk_projection(self.tcx(), trait_ref.clone(), name))
+                     .map(|&name| self.tcx().mk_projection(trait_ref.clone(), name))
                      .collect();
         debug!("accumulate_from_assoc_types: assoc_type_projections={:?}",
                assoc_type_projections);
@@ -400,7 +400,7 @@ impl<'a, 'tcx> Implicator<'a, 'tcx> {
     }
 
     fn fully_normalize<T>(&self, value: &T) -> Result<T,ErrorReported>
-        where T : TypeFoldable<'tcx> + ty::HasProjectionTypes
+        where T : TypeFoldable<'tcx> + ty::HasTypeFlags
     {
         let value =
             traits::fully_normalize(self.infcx,
@@ -437,7 +437,7 @@ pub fn object_region_bounds<'tcx>(
     // Since we don't actually *know* the self type for an object,
     // this "open(err)" serves as a kind of dummy standin -- basically
     // a skolemized type.
-    let open_ty = ty::mk_infer(tcx, ty::FreshTy(0));
+    let open_ty = tcx.mk_infer(ty::FreshTy(0));
 
     // Note that we preserve the overall binding levels here.
     assert!(!open_ty.has_escaping_regions());
@@ -447,5 +447,5 @@ pub fn object_region_bounds<'tcx>(
     let mut predicates = others.to_predicates(tcx, open_ty);
     predicates.extend(trait_refs.iter().map(|t| t.to_predicate()));
 
-    ty::required_region_bounds(tcx, open_ty, predicates)
+    tcx.required_region_bounds(open_ty, predicates)
 }
diff --git a/src/librustc/middle/infer/bivariate.rs b/src/librustc/middle/infer/bivariate.rs
index 742ad3f29b7..d2268894b20 100644
--- a/src/librustc/middle/infer/bivariate.rs
+++ b/src/librustc/middle/infer/bivariate.rs
@@ -109,8 +109,8 @@ impl<'a, 'tcx> TypeRelation<'a, 'tcx> for Bivariate<'a, 'tcx> {
                   -> RelateResult<'tcx, ty::Binder<T>>
         where T: Relate<'a,'tcx>
     {
-        let a1 = ty::erase_late_bound_regions(self.tcx(), a);
-        let b1 = ty::erase_late_bound_regions(self.tcx(), b);
+        let a1 = self.tcx().erase_late_bound_regions(a);
+        let b1 = self.tcx().erase_late_bound_regions(b);
         let c = try!(self.relate(&a1, &b1));
         Ok(ty::Binder(c))
     }
diff --git a/src/librustc/middle/infer/combine.rs b/src/librustc/middle/infer/combine.rs
index 17d545212c2..13b2214d353 100644
--- a/src/librustc/middle/infer/combine.rs
+++ b/src/librustc/middle/infer/combine.rs
@@ -129,8 +129,8 @@ fn unify_integral_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
          .unify_var_value(vid, val)
          .map_err(|e| int_unification_error(vid_is_expected, e)));
     match val {
-        IntType(v) => Ok(ty::mk_mach_int(infcx.tcx, v)),
-        UintType(v) => Ok(ty::mk_mach_uint(infcx.tcx, v)),
+        IntType(v) => Ok(infcx.tcx.mk_mach_int(v)),
+        UintType(v) => Ok(infcx.tcx.mk_mach_uint(v)),
     }
 }
 
@@ -145,7 +145,7 @@ fn unify_float_variable<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
          .borrow_mut()
          .unify_var_value(vid, val)
          .map_err(|e| float_unification_error(vid_is_expected, e)));
-    Ok(ty::mk_mach_float(infcx.tcx, val))
+    Ok(infcx.tcx.mk_mach_float(val))
 }
 
 impl<'a, 'tcx> CombineFields<'a, 'tcx> {
diff --git a/src/librustc/middle/infer/error_reporting.rs b/src/librustc/middle/infer/error_reporting.rs
index 4ae618d45b7..17075c0cba6 100644
--- a/src/librustc/middle/infer/error_reporting.rs
+++ b/src/librustc/middle/infer/error_reporting.rs
@@ -77,7 +77,7 @@ use middle::def;
 use middle::infer;
 use middle::region;
 use middle::subst;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty::{Region, ReFree};
 
 use std::cell::{Cell, RefCell};
@@ -91,123 +91,125 @@ use syntax::parse::token;
 use syntax::print::pprust;
 use syntax::ptr::P;
 
-pub fn note_and_explain_region(tcx: &ty::ctxt,
-                               prefix: &str,
-                               region: ty::Region,
-                               suffix: &str) {
-    fn item_scope_tag(item: &ast::Item) -> &'static str {
-        match item.node {
-            ast::ItemImpl(..) => "impl",
-            ast::ItemStruct(..) => "struct",
-            ast::ItemEnum(..) => "enum",
-            ast::ItemTrait(..) => "trait",
-            ast::ItemFn(..) => "function body",
-            _ => "item"
+impl<'tcx> ty::ctxt<'tcx> {
+    pub fn note_and_explain_region(&self,
+                                   prefix: &str,
+                                   region: ty::Region,
+                                   suffix: &str) {
+        fn item_scope_tag(item: &ast::Item) -> &'static str {
+            match item.node {
+                ast::ItemImpl(..) => "impl",
+                ast::ItemStruct(..) => "struct",
+                ast::ItemEnum(..) => "enum",
+                ast::ItemTrait(..) => "trait",
+                ast::ItemFn(..) => "function body",
+                _ => "item"
+            }
         }
-    }
-
-    fn explain_span(tcx: &ty::ctxt, heading: &str, span: Span)
-                    -> (String, Option<Span>) {
-        let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
-        (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
-         Some(span))
-    }
 
-    let (description, span) = match region {
-        ty::ReScope(scope) => {
-            let new_string;
-            let unknown_scope = || {
-                format!("{}unknown scope: {:?}{}.  Please report a bug.",
-                        prefix, scope, suffix)
-            };
-            let span = match scope.span(&tcx.map) {
-                Some(s) => s,
-                None => return tcx.sess.note(&unknown_scope())
-            };
-            let tag = match tcx.map.find(scope.node_id()) {
-                Some(ast_map::NodeBlock(_)) => "block",
-                Some(ast_map::NodeExpr(expr)) => match expr.node {
-                    ast::ExprCall(..) => "call",
-                    ast::ExprMethodCall(..) => "method call",
-                    ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
-                    ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) =>  "while let",
-                    ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) =>  "for",
-                    ast::ExprMatch(..) => "match",
-                    _ => "expression",
-                },
-                Some(ast_map::NodeStmt(_)) => "statement",
-                Some(ast_map::NodeItem(it)) => item_scope_tag(&*it),
-                Some(_) | None => {
-                    return tcx.sess.span_note(span, &unknown_scope());
-                }
-            };
-            let scope_decorated_tag = match scope {
-                region::CodeExtent::Misc(_) => tag,
-                region::CodeExtent::ParameterScope { .. } => {
-                    "scope of parameters for function"
-                }
-                region::CodeExtent::DestructionScope(_) => {
-                    new_string = format!("destruction scope surrounding {}", tag);
-                    &new_string[..]
-                }
-                region::CodeExtent::Remainder(r) => {
-                    new_string = format!("block suffix following statement {}",
-                                         r.first_statement_index);
-                    &new_string[..]
-                }
-            };
-            explain_span(tcx, scope_decorated_tag, span)
+        fn explain_span(tcx: &ty::ctxt, heading: &str, span: Span)
+                        -> (String, Option<Span>) {
+            let lo = tcx.sess.codemap().lookup_char_pos_adj(span.lo);
+            (format!("the {} at {}:{}", heading, lo.line, lo.col.to_usize()),
+             Some(span))
         }
 
-        ty::ReFree(ref fr) => {
-            let prefix = match fr.bound_region {
-                ty::BrAnon(idx) => {
-                    format!("the anonymous lifetime #{} defined on", idx + 1)
-                }
-                ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
-                _ => {
-                    format!("the lifetime {} as defined on",
-                            fr.bound_region)
-                }
-            };
+        let (description, span) = match region {
+            ty::ReScope(scope) => {
+                let new_string;
+                let unknown_scope = || {
+                    format!("{}unknown scope: {:?}{}.  Please report a bug.",
+                            prefix, scope, suffix)
+                };
+                let span = match scope.span(&self.map) {
+                    Some(s) => s,
+                    None => return self.sess.note(&unknown_scope())
+                };
+                let tag = match self.map.find(scope.node_id()) {
+                    Some(ast_map::NodeBlock(_)) => "block",
+                    Some(ast_map::NodeExpr(expr)) => match expr.node {
+                        ast::ExprCall(..) => "call",
+                        ast::ExprMethodCall(..) => "method call",
+                        ast::ExprMatch(_, _, ast::MatchSource::IfLetDesugar { .. }) => "if let",
+                        ast::ExprMatch(_, _, ast::MatchSource::WhileLetDesugar) =>  "while let",
+                        ast::ExprMatch(_, _, ast::MatchSource::ForLoopDesugar) =>  "for",
+                        ast::ExprMatch(..) => "match",
+                        _ => "expression",
+                    },
+                    Some(ast_map::NodeStmt(_)) => "statement",
+                    Some(ast_map::NodeItem(it)) => item_scope_tag(&*it),
+                    Some(_) | None => {
+                        return self.sess.span_note(span, &unknown_scope());
+                    }
+                };
+                let scope_decorated_tag = match scope {
+                    region::CodeExtent::Misc(_) => tag,
+                    region::CodeExtent::ParameterScope { .. } => {
+                        "scope of parameters for function"
+                    }
+                    region::CodeExtent::DestructionScope(_) => {
+                        new_string = format!("destruction scope surrounding {}", tag);
+                        &new_string[..]
+                    }
+                    region::CodeExtent::Remainder(r) => {
+                        new_string = format!("block suffix following statement {}",
+                                             r.first_statement_index);
+                        &new_string[..]
+                    }
+                };
+                explain_span(self, scope_decorated_tag, span)
+            }
 
-            match tcx.map.find(fr.scope.node_id) {
-                Some(ast_map::NodeBlock(ref blk)) => {
-                    let (msg, opt_span) = explain_span(tcx, "block", blk.span);
-                    (format!("{} {}", prefix, msg), opt_span)
-                }
-                Some(ast_map::NodeItem(it)) => {
-                    let tag = item_scope_tag(&*it);
-                    let (msg, opt_span) = explain_span(tcx, tag, it.span);
-                    (format!("{} {}", prefix, msg), opt_span)
-                }
-                Some(_) | None => {
-                    // this really should not happen
-                    (format!("{} unknown free region bounded by scope {:?}",
-                             prefix, fr.scope), None)
+            ty::ReFree(ref fr) => {
+                let prefix = match fr.bound_region {
+                    ty::BrAnon(idx) => {
+                        format!("the anonymous lifetime #{} defined on", idx + 1)
+                    }
+                    ty::BrFresh(_) => "an anonymous lifetime defined on".to_owned(),
+                    _ => {
+                        format!("the lifetime {} as defined on",
+                                fr.bound_region)
+                    }
+                };
+
+                match self.map.find(fr.scope.node_id) {
+                    Some(ast_map::NodeBlock(ref blk)) => {
+                        let (msg, opt_span) = explain_span(self, "block", blk.span);
+                        (format!("{} {}", prefix, msg), opt_span)
+                    }
+                    Some(ast_map::NodeItem(it)) => {
+                        let tag = item_scope_tag(&*it);
+                        let (msg, opt_span) = explain_span(self, tag, it.span);
+                        (format!("{} {}", prefix, msg), opt_span)
+                    }
+                    Some(_) | None => {
+                        // this really should not happen
+                        (format!("{} unknown free region bounded by scope {:?}",
+                                 prefix, fr.scope), None)
+                    }
                 }
             }
-        }
 
-        ty::ReStatic => ("the static lifetime".to_owned(), None),
+            ty::ReStatic => ("the static lifetime".to_owned(), None),
 
-        ty::ReEmpty => ("the empty lifetime".to_owned(), None),
+            ty::ReEmpty => ("the empty lifetime".to_owned(), None),
 
-        ty::ReEarlyBound(ref data) => {
-            (format!("{}", token::get_name(data.name)), None)
-        }
+            ty::ReEarlyBound(ref data) => {
+                (format!("{}", token::get_name(data.name)), None)
+            }
 
-        // I believe these cases should not occur (except when debugging,
-        // perhaps)
-        ty::ReInfer(_) | ty::ReLateBound(..) => {
-            (format!("lifetime {:?}", region), None)
+            // I believe these cases should not occur (except when debugging,
+            // perhaps)
+            ty::ReInfer(_) | ty::ReLateBound(..) => {
+                (format!("lifetime {:?}", region), None)
+            }
+        };
+        let message = format!("{}{}{}", prefix, description, suffix);
+        if let Some(span) = span {
+            self.sess.span_note(span, &message);
+        } else {
+            self.sess.note(&message);
         }
-    };
-    let message = format!("{}{}{}", prefix, description, suffix);
-    if let Some(span) = span {
-        tcx.sess.span_note(span, &message);
-    } else {
-        tcx.sess.note(&message);
     }
 }
 
@@ -226,7 +228,7 @@ pub trait ErrorReporting<'tcx> {
 
     fn values_str(&self, values: &ValuePairs<'tcx>) -> Option<String>;
 
-    fn expected_found_str<T: fmt::Display + Resolvable<'tcx>>(
+    fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + HasTypeFlags>(
         &self,
         exp_found: &ty::expected_found<T>)
         -> Option<String>;
@@ -491,7 +493,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                      terr: &ty::type_err<'tcx>) {
         let span = trace.origin.span();
         self.report_type_error(trace, terr);
-        ty::note_and_explain_type_err(self.tcx, terr, span);
+        self.tcx.note_and_explain_type_err(terr, span);
     }
 
     /// Returns a string of the form "expected `{}`, found `{}`", or None if this is a derived
@@ -504,18 +506,18 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
         }
     }
 
-    fn expected_found_str<T: fmt::Display + Resolvable<'tcx>>(
+    fn expected_found_str<T: fmt::Display + Resolvable<'tcx> + HasTypeFlags>(
         &self,
         exp_found: &ty::expected_found<T>)
         -> Option<String>
     {
         let expected = exp_found.expected.resolve(self);
-        if expected.contains_error() {
+        if expected.references_error() {
             return None;
         }
 
         let found = exp_found.found.resolve(self);
-        if found.contains_error() {
+        if found.references_error() {
             return None;
         }
 
@@ -576,8 +578,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     &format!(
                         "consider adding an explicit lifetime bound for `{}`",
                         bound_kind));
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     &format!("{} must be valid for ", labeled_user_string),
                     sub,
                     "...");
@@ -600,13 +601,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                 span_err!(self.tcx.sess, span, E0312,
                     "lifetime of reference outlines \
                      lifetime of borrowed content...");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "...the reference is valid for ",
                     sub,
                     "...");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "...but the borrowed content is only valid for ",
                     sup,
                     "");
@@ -615,33 +614,25 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                 span_err!(self.tcx.sess, span, E0313,
                     "lifetime of borrowed pointer outlives \
                             lifetime of captured variable `{}`...",
-                            ty::local_var_name_str(self.tcx,
-                                                   upvar_id.var_id)
-                                .to_string());
-                note_and_explain_region(
-                    self.tcx,
+                            self.tcx.local_var_name_str(upvar_id.var_id));
+                self.tcx.note_and_explain_region(
                     "...the borrowed pointer is valid for ",
                     sub,
                     "...");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     &format!("...but `{}` is only valid for ",
-                            ty::local_var_name_str(self.tcx,
-                                                   upvar_id.var_id)
-                                .to_string()),
+                             self.tcx.local_var_name_str(upvar_id.var_id)),
                     sup,
                     "");
             }
             infer::InfStackClosure(span) => {
                 span_err!(self.tcx.sess, span, E0314,
                     "closure outlives stack frame");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "...the closure must be valid for ",
                     sub,
                     "...");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "...but the closure's stack frame is only valid for ",
                     sup,
                     "");
@@ -649,8 +640,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             infer::InvokeClosure(span) => {
                 span_err!(self.tcx.sess, span, E0315,
                     "cannot invoke closure outside of its lifetime");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the closure is only valid for ",
                     sup,
                     "");
@@ -659,8 +649,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                 self.tcx.sess.span_err(
                     span,
                     "dereference of reference outside its lifetime");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the reference is only valid for ",
                     sup,
                     "");
@@ -669,16 +658,13 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                 self.tcx.sess.span_err(
                     span,
                     &format!("captured variable `{}` does not \
-                            outlive the enclosing closure",
-                            ty::local_var_name_str(self.tcx,
-                                                   id).to_string()));
-                note_and_explain_region(
-                    self.tcx,
+                              outlive the enclosing closure",
+                             self.tcx.local_var_name_str(id)));
+                self.tcx.note_and_explain_region(
                     "captured variable is valid for ",
                     sup,
                     "");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "closure is valid for ",
                     sub,
                     "");
@@ -686,8 +672,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
             infer::IndexSlice(span) => {
                 self.tcx.sess.span_err(span,
                                        "index of slice outside its lifetime");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the slice is only valid for ",
                     sup,
                     "");
@@ -697,13 +682,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     "lifetime of the source pointer does not outlive \
                      lifetime bound of the object type");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "object type is valid for ",
                     sub,
                     "");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "source pointer is only valid for ",
                     sup,
                     "");
@@ -714,7 +697,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     &format!("the type `{}` does not fulfill the \
                              required lifetime",
                             self.ty_to_string(ty)));
-                note_and_explain_region(self.tcx,
+                self.tcx.note_and_explain_region(
                                         "type must outlive ",
                                         sub,
                                         "");
@@ -723,13 +706,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                 self.tcx.sess.span_err(
                     span,
                     "lifetime bound not satisfied");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "lifetime parameter instantiated with ",
                     sup,
                     "");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "but lifetime parameter must outlive ",
                     sub,
                     "");
@@ -740,7 +721,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     &format!("the type `{}` (provided as the value of \
                              a type parameter) is not valid at this point",
                             self.ty_to_string(ty)));
-                note_and_explain_region(self.tcx,
+                self.tcx.note_and_explain_region(
                                         "type must outlive ",
                                         sub,
                                         "");
@@ -750,8 +731,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     "lifetime of method receiver does not outlive \
                      the method call");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the receiver is only valid for ",
                     sup,
                     "");
@@ -761,8 +741,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     "lifetime of function argument does not outlive \
                      the function call");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the function argument is only valid for ",
                     sup,
                     "");
@@ -772,8 +751,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     "lifetime of return value does not outlive \
                      the function call");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the return value is only valid for ",
                     sup,
                     "");
@@ -783,8 +761,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     "lifetime of operand does not outlive \
                      the operation");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the operand is only valid for ",
                     sup,
                     "");
@@ -794,8 +771,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     "reference is not valid \
                      at the time of borrow");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the borrow is only valid for ",
                     sup,
                     "");
@@ -805,8 +781,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     "automatically reference is not valid \
                      at the time of borrow");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the automatic borrow is only valid for ",
                     sup,
                     "");
@@ -817,8 +792,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     &format!("type of expression contains references \
                              that are not valid during the expression: `{}`",
                             self.ty_to_string(t)));
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "type is only valid for ",
                     sup,
                     "");
@@ -829,13 +803,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     "unsafe use of destructor: destructor might be called \
                      while references are dead");
                 // FIXME (22171): terms "super/subregion" are suboptimal
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "superregion: ",
                     sup,
                     "");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "subregion: ",
                     sub,
                     "");
@@ -844,8 +816,7 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                 self.tcx.sess.span_err(
                     span,
                     "lifetime of variable does not enclose its declaration");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the variable is only valid for ",
                     sup,
                     "");
@@ -856,13 +827,11 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                     &format!("in type `{}`, reference has a longer lifetime \
                              than the data it references",
                             self.ty_to_string(ty)));
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "the pointer is valid for ",
                     sub,
                     "");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "but the referenced data is only valid for ",
                     sup,
                     "");
@@ -878,16 +847,14 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                sup_region: Region) {
         self.report_inference_failure(var_origin);
 
-        note_and_explain_region(
-            self.tcx,
+        self.tcx.note_and_explain_region(
             "first, the lifetime cannot outlive ",
             sup_region,
             "...");
 
         self.note_region_origin(&sup_origin);
 
-        note_and_explain_region(
-            self.tcx,
+        self.tcx.note_and_explain_region(
             "but, the lifetime must be valid for ",
             sub_region,
             "...");
@@ -903,16 +870,14 @@ impl<'a, 'tcx> ErrorReporting<'tcx> for InferCtxt<'a, 'tcx> {
                                region2: Region) {
         self.report_inference_failure(var_origin);
 
-        note_and_explain_region(
-            self.tcx,
+        self.tcx.note_and_explain_region(
             "first, the lifetime must be contained by ",
             region1,
             "...");
 
         self.note_region_origin(&origin1);
 
-        note_and_explain_region(
-            self.tcx,
+        self.tcx.note_and_explain_region(
             "but, the lifetime must also be contained by ",
             region2,
             "...");
@@ -1353,7 +1318,7 @@ impl<'a, 'tcx> Rebuilder<'a, 'tcx> {
                     };
                     match a_def {
                         def::DefTy(did, _) | def::DefStruct(did) => {
-                            let generics = ty::lookup_item_type(self.tcx, did).generics;
+                            let generics = self.tcx.lookup_item_type(did).generics;
 
                             let expected =
                                 generics.regions.len(subst::TypeSpace) as u32;
@@ -1591,7 +1556,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
             }
             infer::UpvarRegion(ref upvar_id, _) => {
                 format!(" for capture of `{}` by closure",
-                        ty::local_var_name_str(self.tcx, upvar_id.var_id).to_string())
+                        self.tcx.local_var_name_str(upvar_id.var_id).to_string())
             }
         };
 
@@ -1671,7 +1636,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     &format!(
                         "...so that closure can access `{}`",
-                        ty::local_var_name_str(self.tcx, upvar_id.var_id)
+                        self.tcx.local_var_name_str(upvar_id.var_id)
                             .to_string()))
             }
             infer::InfStackClosure(span) => {
@@ -1695,9 +1660,7 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
                     span,
                     &format!("...so that captured variable `{}` \
                             does not outlive the enclosing closure",
-                            ty::local_var_name_str(
-                                self.tcx,
-                                id).to_string()));
+                            self.tcx.local_var_name_str(id)));
             }
             infer::IndexSlice(span) => {
                 self.tcx.sess.span_note(
@@ -1793,16 +1756,12 @@ impl<'a, 'tcx> ErrorReportingHelpers<'tcx> for InferCtxt<'a, 'tcx> {
 
 pub trait Resolvable<'tcx> {
     fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Self;
-    fn contains_error(&self) -> bool;
 }
 
 impl<'tcx> Resolvable<'tcx> for Ty<'tcx> {
     fn resolve<'a>(&self, infcx: &InferCtxt<'a, 'tcx>) -> Ty<'tcx> {
         infcx.resolve_type_vars_if_possible(self)
     }
-    fn contains_error(&self) -> bool {
-        ty::type_is_error(*self)
-    }
 }
 
 impl<'tcx> Resolvable<'tcx> for ty::TraitRef<'tcx> {
@@ -1810,9 +1769,6 @@ impl<'tcx> Resolvable<'tcx> for ty::TraitRef<'tcx> {
                    -> ty::TraitRef<'tcx> {
         infcx.resolve_type_vars_if_possible(self)
     }
-    fn contains_error(&self) -> bool {
-        ty::trait_ref_contains_error(self)
-    }
 }
 
 impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
@@ -1822,10 +1778,6 @@ impl<'tcx> Resolvable<'tcx> for ty::PolyTraitRef<'tcx> {
     {
         infcx.resolve_type_vars_if_possible(self)
     }
-
-    fn contains_error(&self) -> bool {
-        ty::trait_ref_contains_error(&self.0)
-    }
 }
 
 fn lifetimes_in_scope(tcx: &ty::ctxt,
diff --git a/src/librustc/middle/infer/freshen.rs b/src/librustc/middle/infer/freshen.rs
index 1aa54863c20..d65c4061f11 100644
--- a/src/librustc/middle/infer/freshen.rs
+++ b/src/librustc/middle/infer/freshen.rs
@@ -30,7 +30,7 @@
 //! variable only once, and it does so as soon as it can, so it is reasonable to ask what the type
 //! inferencer knows "so far".
 
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty_fold;
 use middle::ty_fold::TypeFoldable;
 use middle::ty_fold::TypeFolder;
@@ -71,7 +71,7 @@ impl<'a, 'tcx> TypeFreshener<'a, 'tcx> {
             Entry::Vacant(entry) => {
                 let index = self.freshen_count;
                 self.freshen_count += 1;
-                let t = ty::mk_infer(self.infcx.tcx, freshener(index));
+                let t = self.infcx.tcx.mk_infer(freshener(index));
                 entry.insert(t);
                 t
             }
@@ -104,7 +104,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for TypeFreshener<'a, 'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty::type_needs_infer(t) && !ty::type_has_erasable_regions(t) {
+        if !t.needs_infer() && !t.has_erasable_regions() {
             return t;
         }
 
diff --git a/src/librustc/middle/infer/higher_ranked/mod.rs b/src/librustc/middle/infer/higher_ranked/mod.rs
index 7b26f6b1537..9005e1b8c53 100644
--- a/src/librustc/middle/infer/higher_ranked/mod.rs
+++ b/src/librustc/middle/infer/higher_ranked/mod.rs
@@ -507,7 +507,7 @@ pub fn construct_skolemized_substs<'a,'tcx>(infcx: &InferCtxt<'a,'tcx>,
                                   types: &mut subst::VecPerParamSpace<ty::Ty<'tcx>>,
                                   defs: &[ty::TypeParameterDef<'tcx>]) {
         for def in defs {
-            let ty = ty::mk_param_from_def(tcx, def);
+            let ty = tcx.mk_param_from_def(def);
             types.push(def.space, ty);
         }
     }
diff --git a/src/librustc/middle/infer/mod.rs b/src/librustc/middle/infer/mod.rs
index 2df335b5c3c..f1af2705d4e 100644
--- a/src/librustc/middle/infer/mod.rs
+++ b/src/librustc/middle/infer/mod.rs
@@ -26,7 +26,7 @@ use middle::free_region::FreeRegionMap;
 use middle::subst;
 use middle::subst::Substs;
 use middle::ty::{TyVid, IntVid, FloatVid, RegionVid, UnconstrainedNumeric};
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty_fold::{self, TypeFolder, TypeFoldable};
 use middle::ty_relate::{Relate, RelateResult, TypeRelation};
 use rustc_data_structures::unify::{self, UnificationTable};
@@ -772,11 +772,11 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
     }
 
     pub fn next_ty_var(&self) -> Ty<'tcx> {
-        ty::mk_var(self.tcx, self.next_ty_var_id(false))
+        self.tcx.mk_var(self.next_ty_var_id(false))
     }
 
     pub fn next_diverging_ty_var(&self) -> Ty<'tcx> {
-        ty::mk_var(self.tcx, self.next_ty_var_id(true))
+        self.tcx.mk_var(self.next_ty_var_id(true))
     }
 
     pub fn next_ty_vars(&self, n: usize) -> Vec<Ty<'tcx>> {
@@ -973,20 +973,17 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
 
         let resolved_expected = expected_ty.map(|e_ty| self.resolve_type_vars_if_possible(&e_ty));
 
-        match resolved_expected {
-            Some(t) if ty::type_is_error(t) => (),
-            _ => {
-                let error_str = err.map_or("".to_string(), |t_err| {
-                    format!(" ({})", t_err)
-                });
+        if !resolved_expected.references_error() {
+            let error_str = err.map_or("".to_string(), |t_err| {
+                format!(" ({})", t_err)
+            });
 
-                self.tcx.sess.span_err(sp, &format!("{}{}",
-                    mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty),
-                    error_str));
+            self.tcx.sess.span_err(sp, &format!("{}{}",
+                mk_msg(resolved_expected.map(|t| self.ty_to_string(t)), actual_ty),
+                error_str));
 
-                if let Some(err) = err {
-                    ty::note_and_explain_type_err(self.tcx, err, sp)
-                }
+            if let Some(err) = err {
+                self.tcx.note_and_explain_type_err(err, sp)
             }
         }
     }
@@ -1001,7 +998,7 @@ impl<'a, 'tcx> InferCtxt<'a, 'tcx> {
         let actual_ty = self.resolve_type_vars_if_possible(&actual_ty);
 
         // Don't report an error if actual type is TyError.
-        if ty::type_is_error(actual_ty) {
+        if actual_ty.references_error() {
             return;
         }
 
diff --git a/src/librustc/middle/infer/region_inference/mod.rs b/src/librustc/middle/infer/region_inference/mod.rs
index e397f356855..fac7b53ca76 100644
--- a/src/librustc/middle/infer/region_inference/mod.rs
+++ b/src/librustc/middle/infer/region_inference/mod.rs
@@ -1672,7 +1672,7 @@ impl<'tcx> GenericKind<'tcx> {
             GenericKind::Param(ref p) =>
                 p.to_ty(tcx),
             GenericKind::Projection(ref p) =>
-                ty::mk_projection(tcx, p.trait_ref.clone(), p.item_name),
+                tcx.mk_projection(p.trait_ref.clone(), p.item_name),
         }
     }
 }
diff --git a/src/librustc/middle/infer/resolve.rs b/src/librustc/middle/infer/resolve.rs
index b67437fd127..41a0d373fba 100644
--- a/src/librustc/middle/infer/resolve.rs
+++ b/src/librustc/middle/infer/resolve.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use super::{InferCtxt, fixup_err, fres, unresolved_ty, unresolved_int_ty, unresolved_float_ty};
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty_fold::{self, TypeFoldable};
 
 ///////////////////////////////////////////////////////////////////////////
@@ -36,7 +36,7 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for OpportunisticTypeResolver<'a, 'tcx>
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty::type_has_ty_infer(t) {
+        if !t.has_infer_types() {
             t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             let t0 = self.infcx.shallow_resolve(t);
@@ -75,7 +75,7 @@ impl<'a, 'tcx> ty_fold::TypeFolder<'tcx> for FullTypeResolver<'a, 'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty::type_needs_infer(t) {
+        if !t.needs_infer() {
             t // micro-optimize -- if there is nothing in this type that this fold affects...
         } else {
             let t = self.infcx.shallow_resolve(t);
diff --git a/src/librustc/middle/infer/unify_key.rs b/src/librustc/middle/infer/unify_key.rs
index 6b23e2c5029..c13cec45dc4 100644
--- a/src/librustc/middle/infer/unify_key.rs
+++ b/src/librustc/middle/infer/unify_key.rs
@@ -26,8 +26,8 @@ impl UnifyKey for ty::IntVid {
 impl<'tcx> ToType<'tcx> for IntVarValue {
     fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
         match *self {
-            ty::IntType(i) => ty::mk_mach_int(tcx, i),
-            ty::UintType(i) => ty::mk_mach_uint(tcx, i),
+            ty::IntType(i) => tcx.mk_mach_int(i),
+            ty::UintType(i) => tcx.mk_mach_uint(i),
         }
     }
 }
@@ -43,6 +43,6 @@ impl UnifyKey for ty::FloatVid {
 
 impl<'tcx> ToType<'tcx> for ast::FloatTy {
     fn to_type(&self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
-        ty::mk_mach_float(tcx, *self)
+        tcx.mk_mach_float(*self)
     }
 }
diff --git a/src/librustc/middle/intrinsicck.rs b/src/librustc/middle/intrinsicck.rs
index c4d924d676c..c5f6f0126de 100644
--- a/src/librustc/middle/intrinsicck.rs
+++ b/src/librustc/middle/intrinsicck.rs
@@ -13,7 +13,7 @@ use metadata::csearch;
 use middle::def::DefFn;
 use middle::subst::{Subst, Substs, EnumeratedItems};
 use middle::ty::{TransmuteRestriction, ctxt, TyBareFn};
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 
 use std::fmt;
 
@@ -30,7 +30,7 @@ pub fn check_crate(tcx: &ctxt) {
         tcx: tcx,
         param_envs: Vec::new(),
         dummy_sized_ty: tcx.types.isize,
-        dummy_unsized_ty: ty::mk_vec(tcx, tcx.types.isize, None),
+        dummy_unsized_ty: tcx.mk_slice(tcx.types.isize),
     };
     visit::walk_crate(&mut visitor, tcx.map.krate());
 }
@@ -54,7 +54,7 @@ struct IntrinsicCheckingVisitor<'a, 'tcx: 'a> {
 
 impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
     fn def_id_is_transmute(&self, def_id: DefId) -> bool {
-        let intrinsic = match ty::lookup_item_type(self.tcx, def_id).ty.sty {
+        let intrinsic = match self.tcx.lookup_item_type(def_id).ty.sty {
             ty::TyBareFn(_, ref bfty) => bfty.abi == RustIntrinsic,
             _ => return false
         };
@@ -92,8 +92,8 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
 
         // Simple case: no type parameters involved.
         if
-            !ty::type_has_params(from) && !ty::type_has_self(from) &&
-            !ty::type_has_params(to) && !ty::type_has_self(to)
+            !from.has_param_types() && !from.has_self_ty() &&
+            !to.has_param_types() && !to.has_self_ty()
         {
             let restriction = TransmuteRestriction {
                 span: span,
@@ -160,8 +160,8 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
         // In all cases, we keep the original unsubstituted types
         // around for error reporting.
 
-        let from_tc = ty::type_contents(self.tcx, from);
-        let to_tc = ty::type_contents(self.tcx, to);
+        let from_tc = from.type_contents(self.tcx);
+        let to_tc = to.type_contents(self.tcx);
         if from_tc.interior_param() || to_tc.interior_param() {
             span_err!(self.tcx.sess, span, E0139,
                       "cannot transmute to or from a type that contains \
@@ -213,7 +213,7 @@ impl<'a, 'tcx> IntrinsicCheckingVisitor<'a, 'tcx> {
                 debug!("with_each_combination: space={:?}, index={}, param_ty={:?}",
                        space, index, param_ty);
 
-                if !ty::type_is_sized(Some(param_env), self.tcx, span, param_ty) {
+                if !param_ty.is_sized(param_env, span) {
                     debug!("with_each_combination: param_ty is not known to be sized");
 
                     substs.types.get_mut_slice(space)[index] = self.dummy_unsized_ty;
@@ -253,9 +253,9 @@ impl<'a, 'tcx, 'v> Visitor<'v> for IntrinsicCheckingVisitor<'a, 'tcx> {
 
     fn visit_expr(&mut self, expr: &ast::Expr) {
         if let ast::ExprPath(..) = expr.node {
-            match ty::resolve_expr(self.tcx, expr) {
+            match self.tcx.resolve_expr(expr) {
                 DefFn(did, _) if self.def_id_is_transmute(did) => {
-                    let typ = ty::node_id_to_type(self.tcx, expr.id);
+                    let typ = self.tcx.node_id_to_type(expr.id);
                     match typ.sty {
                         TyBareFn(_, ref bare_fn_ty) if bare_fn_ty.abi == RustIntrinsic => {
                             if let ty::FnConverging(to) = bare_fn_ty.sig.0.output {
diff --git a/src/librustc/middle/liveness.rs b/src/librustc/middle/liveness.rs
index 9bcc251725c..d354c1667da 100644
--- a/src/librustc/middle/liveness.rs
+++ b/src/librustc/middle/liveness.rs
@@ -465,7 +465,7 @@ fn visit_expr(ir: &mut IrMaps, expr: &Expr) {
         // in better error messages than just pointing at the closure
         // construction site.
         let mut call_caps = Vec::new();
-        ty::with_freevars(ir.tcx, expr.id, |freevars| {
+        ir.tcx.with_freevars(expr.id, |freevars| {
             for fv in freevars {
                 if let DefLocal(rv) = fv.def {
                     let fv_ln = ir.add_live_node(FreeVarNode(fv.span));
@@ -1137,9 +1137,8 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
           }
 
           ast::ExprCall(ref f, ref args) => {
-            let diverges = !self.ir.tcx.is_method_call(expr.id) && {
-                ty::ty_fn_ret(ty::expr_ty_adjusted(self.ir.tcx, &**f)).diverges()
-            };
+            let diverges = !self.ir.tcx.is_method_call(expr.id) &&
+                self.ir.tcx.expr_ty_adjusted(&**f).fn_ret().diverges();
             let succ = if diverges {
                 self.s.exit_ln
             } else {
@@ -1152,8 +1151,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
           ast::ExprMethodCall(_, _, ref args) => {
             let method_call = ty::MethodCall::expr(expr.id);
             let method_ty = self.ir.tcx.method_map.borrow().get(&method_call).unwrap().ty;
-            let diverges = ty::ty_fn_ret(method_ty).diverges();
-            let succ = if diverges {
+            let succ = if method_ty.fn_ret().diverges() {
                 self.s.exit_ln
             } else {
                 succ
@@ -1496,12 +1494,11 @@ fn check_fn(_v: &Liveness,
 
 impl<'a, 'tcx> Liveness<'a, 'tcx> {
     fn fn_ret(&self, id: NodeId) -> ty::PolyFnOutput<'tcx> {
-        let fn_ty = ty::node_id_to_type(self.ir.tcx, id);
+        let fn_ty = self.ir.tcx.node_id_to_type(id);
         match fn_ty.sty {
             ty::TyClosure(closure_def_id, substs) =>
                 self.ir.tcx.closure_type(closure_def_id, substs).sig.output(),
-            _ =>
-                ty::ty_fn_ret(fn_ty),
+            _ => fn_ty.fn_ret()
         }
     }
 
@@ -1514,8 +1511,7 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
     {
         // within the fn body, late-bound regions are liberated:
         let fn_ret =
-            ty::liberate_late_bound_regions(
-                self.ir.tcx,
+            self.ir.tcx.liberate_late_bound_regions(
                 region::DestructionScopeData::new(body.id),
                 &self.fn_ret(id));
 
@@ -1523,14 +1519,14 @@ impl<'a, 'tcx> Liveness<'a, 'tcx> {
             ty::FnConverging(t_ret)
                 if self.live_on_entry(entry_ln, self.s.no_ret_var).is_some() => {
 
-                if ty::type_is_nil(t_ret) {
+                if t_ret.is_nil() {
                     // for nil return types, it is ok to not return a value expl.
                 } else {
                     let ends_with_stmt = match body.expr {
                         None if !body.stmts.is_empty() =>
                             match body.stmts.first().unwrap().node {
                                 ast::StmtSemi(ref e, _) => {
-                                    ty::expr_ty(self.ir.tcx, &**e) == t_ret
+                                    self.ir.tcx.expr_ty(&**e) == t_ret
                                 },
                                 _ => false
                             },
diff --git a/src/librustc/middle/mem_categorization.rs b/src/librustc/middle/mem_categorization.rs
index ca8de74b35b..969ffaf88a7 100644
--- a/src/librustc/middle/mem_categorization.rs
+++ b/src/librustc/middle/mem_categorization.rs
@@ -285,7 +285,7 @@ pub type McResult<T> = Result<T, ()>;
 pub trait Typer<'tcx> : ty::ClosureTyper<'tcx> {
     fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>>;
     fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>>;
-    fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool;
+    fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool;
     fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>>;
     fn node_method_origin(&self, method_call: ty::MethodCall)
                           -> Option<ty::MethodOrigin<'tcx>>;
@@ -406,9 +406,10 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
 
     fn expr_ty_adjusted(&self, expr: &ast::Expr) -> McResult<Ty<'tcx>> {
         let unadjusted_ty = try!(self.expr_ty(expr));
-        Ok(ty::adjust_ty(self.tcx(), expr.span, expr.id, unadjusted_ty,
-                         self.typer.adjustments().borrow().get(&expr.id),
-                         |method_call| self.typer.node_method_ty(method_call)))
+        Ok(unadjusted_ty.adjust(
+            self.tcx(), expr.span, expr.id,
+            self.typer.adjustments().borrow().get(&expr.id),
+            |method_call| self.typer.node_method_ty(method_call)))
     }
 
     fn node_ty(&self, id: ast::NodeId) -> McResult<Ty<'tcx>> {
@@ -426,7 +427,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 // a bind-by-ref means that the base_ty will be the type of the ident itself,
                 // but what we want here is the type of the underlying value being borrowed.
                 // So peel off one-level, turning the &T into T.
-                match ty::deref(base_ty, false) {
+                match base_ty.builtin_deref(false) {
                     Some(t) => t.ty,
                     None => { return Err(()); }
                 }
@@ -927,14 +928,13 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         let base_cmt = match method_ty {
             Some(method_ty) => {
                 let ref_ty =
-                    ty::no_late_bound_regions(
-                        self.tcx(), &ty::ty_fn_ret(method_ty)).unwrap().unwrap();
+                    self.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap().unwrap();
                 self.cat_rvalue_node(node.id(), node.span(), ref_ty)
             }
             None => base_cmt
         };
         let base_cmt_ty = base_cmt.ty;
-        match ty::deref(base_cmt_ty, true) {
+        match base_cmt_ty.builtin_deref(true) {
             Some(mt) => {
                 let ret = self.cat_deref_common(node, base_cmt, deref_cnt,
                                               mt.ty,
@@ -1023,11 +1023,11 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                 base_cmt = self.cat_rvalue_node(elt.id(), elt.span(), ref_ty);
 
                 // FIXME(#20649) -- why are we using the `self_ty` as the element type...?
-                let self_ty = ty::ty_fn_sig(method_ty).input(0);
-                ty::no_late_bound_regions(self.tcx(), &self_ty).unwrap()
+                let self_ty = method_ty.fn_sig().input(0);
+                self.tcx().no_late_bound_regions(&self_ty).unwrap()
             }
             None => {
-                match ty::array_element_ty(self.tcx(), base_cmt.ty) {
+                match base_cmt.ty.builtin_index() {
                     Some(ty) => ty,
                     None => {
                         return Err(());
@@ -1081,7 +1081,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
                     span:elt.span(),
                     cat:cat_deref(base_cmt.clone(), 0, ptr),
                     mutbl:m,
-                    ty: match ty::deref(base_cmt.ty, false) {
+                    ty: match base_cmt.ty.builtin_deref(false) {
                         Some(mt) => mt.ty,
                         None => self.tcx().sess.bug("Found non-derefable type")
                     },
@@ -1244,7 +1244,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         let cmt = match opt_def {
             Some(def::DefVariant(enum_did, variant_did, _))
                 // univariant enums do not need downcasts
-                if !ty::enum_is_univariant(self.tcx(), enum_did) => {
+                if !self.tcx().enum_is_univariant(enum_did) => {
                     self.cat_downcast(pat, cmt.clone(), cmt.ty, variant_did)
                 }
             _ => cmt
@@ -1375,7 +1375,7 @@ impl<'t,'tcx,TYPER:Typer<'tcx>> MemCategorizationContext<'t,TYPER> {
         // types are generated by method resolution and always have
         // all late-bound regions fully instantiated, so we just want
         // to skip past the binder.
-        ty::no_late_bound_regions(self.tcx(), &ty::ty_fn_ret(method_ty))
+        self.tcx().no_late_bound_regions(&method_ty.fn_ret())
            .unwrap()
            .unwrap() // overloaded ops do not diverge, either
     }
@@ -1583,7 +1583,7 @@ impl<'tcx> fmt::Debug for categorization<'tcx> {
             cat_static_item => write!(f, "static"),
             cat_rvalue(r) => write!(f, "rvalue({:?})", r),
             cat_local(id) => {
-               let name = ty::tls::with(|tcx| ty::local_var_name_str(tcx, id));
+               let name = ty::tls::with(|tcx| tcx.local_var_name_str(id));
                write!(f, "local({})", name)
             }
             cat_upvar(upvar) => {
diff --git a/src/librustc/middle/pat_util.rs b/src/librustc/middle/pat_util.rs
index 0cb302d79b8..15a1ba85324 100644
--- a/src/librustc/middle/pat_util.rs
+++ b/src/librustc/middle/pat_util.rs
@@ -192,7 +192,7 @@ pub fn simple_identifier<'a>(pat: &'a ast::Pat) -> Option<&'a ast::Ident> {
 }
 
 pub fn def_to_path(tcx: &ty::ctxt, id: ast::DefId) -> ast::Path {
-    ty::with_path(tcx, id, |path| ast::Path {
+    tcx.with_path(id, |path| ast::Path {
         global: false,
         segments: path.last().map(|elem| ast::PathSegment {
             identifier: ast::Ident::new(elem.name()),
diff --git a/src/librustc/middle/stability.rs b/src/librustc/middle/stability.rs
index dad41bdd3a3..4766ae8933d 100644
--- a/src/librustc/middle/stability.rs
+++ b/src/librustc/middle/stability.rs
@@ -382,7 +382,7 @@ pub fn check_item(tcx: &ty::ctxt, item: &ast::Item, warn_about_defns: bool,
         // items.
         ast::ItemImpl(_, _, _, Some(ref t), _, ref impl_items) => {
             let trait_did = tcx.def_map.borrow().get(&t.ref_id).unwrap().def_id();
-            let trait_items = ty::trait_items(tcx, trait_did);
+            let trait_items = tcx.trait_items(trait_did);
 
             for impl_item in impl_items {
                 let item = trait_items.iter().find(|item| {
@@ -425,7 +425,7 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
                             method_num: index,
                             ..
                         }) => {
-                            ty::trait_item(tcx, trait_ref.def_id, index).def_id()
+                            tcx.trait_item(trait_ref.def_id, index).def_id()
                         }
                     }
                 }
@@ -434,9 +434,9 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
         }
         ast::ExprField(ref base_e, ref field) => {
             span = field.span;
-            match ty::expr_ty_adjusted(tcx, base_e).sty {
+            match tcx.expr_ty_adjusted(base_e).sty {
                 ty::TyStruct(did, _) => {
-                    ty::lookup_struct_fields(tcx, did)
+                    tcx.lookup_struct_fields(did)
                         .iter()
                         .find(|f| f.name == field.node.name)
                         .unwrap_or_else(|| {
@@ -451,9 +451,9 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
         }
         ast::ExprTupField(ref base_e, ref field) => {
             span = field.span;
-            match ty::expr_ty_adjusted(tcx, base_e).sty {
+            match tcx.expr_ty_adjusted(base_e).sty {
                 ty::TyStruct(did, _) => {
-                    ty::lookup_struct_fields(tcx, did)
+                    tcx.lookup_struct_fields(did)
                         .get(field.node)
                         .unwrap_or_else(|| {
                             tcx.sess.span_bug(field.span,
@@ -468,10 +468,10 @@ pub fn check_expr(tcx: &ty::ctxt, e: &ast::Expr,
             }
         }
         ast::ExprStruct(_, ref expr_fields, _) => {
-            let type_ = ty::expr_ty(tcx, e);
+            let type_ = tcx.expr_ty(e);
             match type_.sty {
                 ty::TyStruct(did, _) => {
-                    let struct_fields = ty::lookup_struct_fields(tcx, did);
+                    let struct_fields = tcx.lookup_struct_fields(did);
                     // check the stability of each field that appears
                     // in the construction expression.
                     for field in expr_fields {
@@ -525,11 +525,11 @@ pub fn check_pat(tcx: &ty::ctxt, pat: &ast::Pat,
     debug!("check_pat(pat = {:?})", pat);
     if is_internal(tcx, pat.span) { return; }
 
-    let did = match ty::pat_ty_opt(tcx, pat) {
+    let did = match tcx.pat_ty_opt(pat) {
         Some(&ty::TyS { sty: ty::TyStruct(did, _), .. }) => did,
         Some(_) | None => return,
     };
-    let struct_fields = ty::lookup_struct_fields(tcx, did);
+    let struct_fields = tcx.lookup_struct_fields(did);
     match pat.node {
         // Foo(a, b, c)
         ast::PatEnum(_, Some(ref pat_fields)) => {
@@ -574,7 +574,7 @@ fn is_internal(tcx: &ty::ctxt, span: Span) -> bool {
 }
 
 fn is_staged_api(tcx: &ty::ctxt, id: DefId) -> bool {
-    match ty::trait_item_of_item(tcx, id) {
+    match tcx.trait_item_of_item(id) {
         Some(ty::MethodTraitItemId(trait_method_id))
             if trait_method_id != id => {
                 is_staged_api(tcx, trait_method_id)
@@ -602,7 +602,7 @@ fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stabil
     debug!("lookup(id={:?})", id);
 
     // is this definition the implementation of a trait method?
-    match ty::trait_item_of_item(tcx, id) {
+    match tcx.trait_item_of_item(id) {
         Some(ty::MethodTraitItemId(trait_method_id)) if trait_method_id != id => {
             debug!("lookup: trait_method_id={:?}", trait_method_id);
             return lookup(tcx, trait_method_id)
@@ -617,8 +617,8 @@ fn lookup_uncached<'tcx>(tcx: &ty::ctxt<'tcx>, id: DefId) -> Option<&'tcx Stabil
     };
 
     item_stab.or_else(|| {
-        if ty::is_impl(tcx, id) {
-            if let Some(trait_id) = ty::trait_id_of_impl(tcx, id) {
+        if tcx.is_impl(id) {
+            if let Some(trait_id) = tcx.trait_id_of_impl(id) {
                 // FIXME (#18969): for the time being, simply use the
                 // stability of the trait to determine the stability of any
                 // unmarked impls for it. See FIXME above for more details.
diff --git a/src/librustc/middle/subst.rs b/src/librustc/middle/subst.rs
index c3c29d0ade8..56798ae6848 100644
--- a/src/librustc/middle/subst.rs
+++ b/src/librustc/middle/subst.rs
@@ -13,7 +13,7 @@
 pub use self::ParamSpace::*;
 pub use self::RegionSubsts::*;
 
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags, RegionEscape};
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
 
 use std::fmt;
@@ -100,17 +100,6 @@ impl<'tcx> Substs<'tcx> {
         *self.types.get(ty_param_def.space, ty_param_def.index as usize)
     }
 
-    pub fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        self.types.iter().any(|&t| ty::type_escapes_depth(t, depth)) || {
-            match self.regions {
-                ErasedRegions =>
-                    false,
-                NonerasedRegions(ref regions) =>
-                    regions.iter().any(|r| r.escapes_depth(depth)),
-            }
-        }
-    }
-
     pub fn self_ty(&self) -> Option<Ty<'tcx>> {
         self.types.get_self().cloned()
     }
@@ -632,7 +621,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for SubstFolder<'a, 'tcx> {
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty::type_needs_subst(t) {
+        if !t.needs_subst() {
             return t;
         }
 
@@ -729,10 +718,10 @@ impl<'a,'tcx> SubstFolder<'a,'tcx> {
     /// first case we do not increase the Debruijn index and in the second case we do. The reason
     /// is that only in the second case have we passed through a fn binder.
     fn shift_regions_through_binders(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
-        debug!("shift_regions(ty={:?}, region_binders_passed={:?}, type_has_escaping_regions={:?})",
-               ty, self.region_binders_passed, ty::type_has_escaping_regions(ty));
+        debug!("shift_regions(ty={:?}, region_binders_passed={:?}, has_escaping_regions={:?})",
+               ty, self.region_binders_passed, ty.has_escaping_regions());
 
-        if self.region_binders_passed == 0 || !ty::type_has_escaping_regions(ty) {
+        if self.region_binders_passed == 0 || !ty.has_escaping_regions() {
             return ty;
         }
 
diff --git a/src/librustc/middle/traits/coherence.rs b/src/librustc/middle/traits/coherence.rs
index a826836b10c..371b5c309a8 100644
--- a/src/librustc/middle/traits/coherence.rs
+++ b/src/librustc/middle/traits/coherence.rs
@@ -38,7 +38,7 @@ pub fn overlapping_impls(infcx: &InferCtxt,
            impl1_def_id,
            impl2_def_id);
 
-    let param_env = &ty::empty_parameter_environment(infcx.tcx);
+    let param_env = &infcx.tcx.empty_parameter_environment();
     let selcx = &mut SelectionContext::intercrate(infcx, param_env);
     infcx.probe(|_| {
         overlap(selcx, impl1_def_id, impl2_def_id) || overlap(selcx, impl2_def_id, impl1_def_id)
@@ -111,7 +111,7 @@ pub fn trait_ref_is_knowable<'tcx>(tcx: &ty::ctxt<'tcx>, trait_ref: &ty::TraitRe
     // already
     if
         trait_ref.def_id.krate != ast::LOCAL_CRATE &&
-        !ty::has_attr(tcx, trait_ref.def_id, "fundamental")
+        !tcx.has_attr(trait_ref.def_id, "fundamental")
     {
         debug!("trait_ref_is_knowable: trait is neither local nor fundamental");
         return false;
@@ -142,13 +142,13 @@ fn impl_trait_ref_and_oblig<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
     let impl_substs =
         &substs_fn(selcx.infcx(), DUMMY_SP, impl_def_id);
     let impl_trait_ref =
-        ty::impl_trait_ref(selcx.tcx(), impl_def_id).unwrap();
+        selcx.tcx().impl_trait_ref(impl_def_id).unwrap();
     let impl_trait_ref =
         impl_trait_ref.subst(selcx.tcx(), impl_substs);
     let Normalized { value: impl_trait_ref, obligations: normalization_obligations1 } =
         project::normalize(selcx, ObligationCause::dummy(), &impl_trait_ref);
 
-    let predicates = ty::lookup_predicates(selcx.tcx(), impl_def_id);
+    let predicates = selcx.tcx().lookup_predicates(impl_def_id);
     let predicates = predicates.instantiate(selcx.tcx(), impl_substs);
     let Normalized { value: predicates, obligations: normalization_obligations2 } =
         project::normalize(selcx, ObligationCause::dummy(), &predicates);
@@ -183,7 +183,7 @@ pub fn orphan_check<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     // We only except this routine to be invoked on implementations
     // of a trait, not inherent implementations.
-    let trait_ref = ty::impl_trait_ref(tcx, impl_def_id).unwrap();
+    let trait_ref = tcx.impl_trait_ref(impl_def_id).unwrap();
     debug!("orphan_check: trait_ref={:?}", trait_ref);
 
     // If the *trait* is local to the crate, ok.
@@ -280,9 +280,9 @@ fn fundamental_ty<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool
         ty::TyBox(..) | ty::TyRef(..) =>
             true,
         ty::TyEnum(def_id, _) | ty::TyStruct(def_id, _) =>
-            ty::has_attr(tcx, def_id, "fundamental"),
+            tcx.has_attr(def_id, "fundamental"),
         ty::TyTrait(ref data) =>
-            ty::has_attr(tcx, data.principal_def_id(), "fundamental"),
+            tcx.has_attr(data.principal_def_id(), "fundamental"),
         _ =>
             false
     }
diff --git a/src/librustc/middle/traits/error_reporting.rs b/src/librustc/middle/traits/error_reporting.rs
index dc7e4f9c571..582873082a6 100644
--- a/src/librustc/middle/traits/error_reporting.rs
+++ b/src/librustc/middle/traits/error_reporting.rs
@@ -25,7 +25,7 @@ use super::{
 
 use fmt_macros::{Parser, Piece, Position};
 use middle::infer::InferCtxt;
-use middle::ty::{self, ToPredicate, ReferencesError, ToPolyTraitRef, TraitRef};
+use middle::ty::{self, ToPredicate, HasTypeFlags, ToPolyTraitRef, TraitRef};
 use middle::ty_fold::TypeFoldable;
 use std::collections::HashMap;
 use std::fmt;
@@ -79,14 +79,14 @@ fn report_on_unimplemented<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                      span: Span) -> Option<String> {
     let def_id = trait_ref.def_id;
     let mut report = None;
-    for item in ty::get_attrs(infcx.tcx, def_id).iter() {
+    for item in infcx.tcx.get_attrs(def_id).iter() {
         if item.check_name("rustc_on_unimplemented") {
             let err_sp = if item.meta().span == DUMMY_SP {
                 span
             } else {
                 item.meta().span
             };
-            let def = ty::lookup_trait_def(infcx.tcx, def_id);
+            let def = infcx.tcx.lookup_trait_def(def_id);
             let trait_str = def.trait_ref.to_string();
             if let Some(ref istring) = item.value_str() {
                 let mut generic_map = def.generics.types.iter_enumerated()
@@ -245,7 +245,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         OutputTypeParameterMismatch(ref expected_trait_ref, ref actual_trait_ref, ref e) => {
             let expected_trait_ref = infcx.resolve_type_vars_if_possible(&*expected_trait_ref);
             let actual_trait_ref = infcx.resolve_type_vars_if_possible(&*actual_trait_ref);
-            if !ty::type_is_error(actual_trait_ref.self_ty()) {
+            if !actual_trait_ref.self_ty().references_error() {
                 span_err!(infcx.tcx.sess, obligation.cause.span, E0281,
                         "type mismatch: the type `{}` implements the trait `{}`, \
                         but the trait `{}` is required ({})",
@@ -260,7 +260,7 @@ pub fn report_selection_error<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
         TraitNotObjectSafe(did) => {
             span_err!(infcx.tcx.sess, obligation.cause.span, E0038,
                 "cannot convert to a trait object because trait `{}` is not object-safe",
-                ty::item_path_str(infcx.tcx, did));
+                infcx.tcx.item_path_str(did));
 
             for violation in object_safety_violations(infcx.tcx, did) {
                 match violation {
@@ -325,8 +325,8 @@ pub fn maybe_report_ambiguity<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
             let trait_ref = data.to_poly_trait_ref();
             let self_ty = trait_ref.self_ty();
             let all_types = &trait_ref.substs().types;
-            if all_types.iter().any(|&t| ty::type_is_error(t)) {
-            } else if all_types.iter().any(|&t| ty::type_needs_infer(t)) {
+            if all_types.references_error() {
+            } else if all_types.needs_infer() {
                 // This is kind of a hack: it frequently happens that some earlier
                 // error prevents types from being fully inferred, and then we get
                 // a bunch of uninteresting errors saying something like "<generic
@@ -401,7 +401,7 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
     match *cause_code {
         ObligationCauseCode::MiscObligation => { }
         ObligationCauseCode::ItemObligation(item_def_id) => {
-            let item_name = ty::item_path_str(tcx, item_def_id);
+            let item_name = tcx.item_path_str(item_def_id);
             tcx.sess.span_note(
                 cause_span,
                 &format!("required by `{}`", item_name));
@@ -442,8 +442,8 @@ fn note_obligation_cause_code<'a, 'tcx, T>(infcx: &InferCtxt<'a, 'tcx>,
         }
         ObligationCauseCode::ClosureCapture(var_id, closure_span, builtin_bound) => {
             let def_id = tcx.lang_items.from_builtin_kind(builtin_bound).unwrap();
-            let trait_name = ty::item_path_str(tcx, def_id);
-            let name = ty::local_var_name_str(tcx, var_id);
+            let trait_name = tcx.item_path_str(def_id);
+            let name = tcx.local_var_name_str(var_id);
             span_note!(tcx.sess, closure_span,
                        "the closure that captures `{}` requires that all captured variables \
                        implement the trait `{}`",
diff --git a/src/librustc/middle/traits/fulfill.rs b/src/librustc/middle/traits/fulfill.rs
index 593a71a30fe..5e274dcec70 100644
--- a/src/librustc/middle/traits/fulfill.rs
+++ b/src/librustc/middle/traits/fulfill.rs
@@ -9,7 +9,7 @@
 // except according to those terms.
 
 use middle::infer::InferCtxt;
-use middle::ty::{self, RegionEscape, Ty};
+use middle::ty::{self, RegionEscape, Ty, HasTypeFlags};
 
 use std::collections::HashSet;
 use std::fmt;
@@ -421,7 +421,7 @@ fn process_predicate<'a,'tcx>(selcx: &mut SelectionContext<'a,'tcx>,
             // regions.  If there are, we will call this obligation an
             // error. Eventually we should be able to support some
             // cases here, I imagine (e.g., `for<'a> int : 'a`).
-            if ty::count_late_bound_regions(selcx.tcx(), binder) != 0 {
+            if selcx.tcx().count_late_bound_regions(binder) != 0 {
                 errors.push(
                     FulfillmentError::new(
                         obligation.clone(),
diff --git a/src/librustc/middle/traits/mod.rs b/src/librustc/middle/traits/mod.rs
index e3c122e2f1f..845ba62307f 100644
--- a/src/librustc/middle/traits/mod.rs
+++ b/src/librustc/middle/traits/mod.rs
@@ -17,7 +17,7 @@ pub use self::ObligationCauseCode::*;
 
 use middle::free_region::FreeRegionMap;
 use middle::subst;
-use middle::ty::{self, HasProjectionTypes, Ty};
+use middle::ty::{self, HasTypeFlags, Ty};
 use middle::ty_fold::TypeFoldable;
 use middle::infer::{self, fixup_err_to_string, InferCtxt};
 use std::rc::Rc;
@@ -432,7 +432,7 @@ pub fn fully_normalize<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                                   cause: ObligationCause<'tcx>,
                                   value: &T)
                                   -> Result<T, Vec<FulfillmentError<'tcx>>>
-    where T : TypeFoldable<'tcx> + HasProjectionTypes
+    where T : TypeFoldable<'tcx> + HasTypeFlags
 {
     debug!("normalize_param_env(value={:?})", value);
 
diff --git a/src/librustc/middle/traits/object_safety.rs b/src/librustc/middle/traits/object_safety.rs
index afb30716c36..e7f11b06bd1 100644
--- a/src/librustc/middle/traits/object_safety.rs
+++ b/src/librustc/middle/traits/object_safety.rs
@@ -57,7 +57,7 @@ pub fn is_object_safe<'tcx>(tcx: &ty::ctxt<'tcx>,
                             -> bool
 {
     // Because we query yes/no results frequently, we keep a cache:
-    let def = ty::lookup_trait_def(tcx, trait_def_id);
+    let def = tcx.lookup_trait_def(trait_def_id);
 
     let result = def.object_safety().unwrap_or_else(|| {
         let result = object_safety_violations(tcx, trait_def_id).is_empty();
@@ -90,7 +90,7 @@ fn object_safety_violations_for_trait<'tcx>(tcx: &ty::ctxt<'tcx>,
 {
     // Check methods for violations.
     let mut violations: Vec<_> =
-        ty::trait_items(tcx, trait_def_id).iter()
+        tcx.trait_items(trait_def_id).iter()
         .flat_map(|item| {
             match *item {
                 ty::MethodTraitItem(ref m) => {
@@ -122,10 +122,10 @@ fn supertraits_reference_self<'tcx>(tcx: &ty::ctxt<'tcx>,
                                     trait_def_id: ast::DefId)
                                     -> bool
 {
-    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+    let trait_def = tcx.lookup_trait_def(trait_def_id);
     let trait_ref = trait_def.trait_ref.clone();
     let trait_ref = trait_ref.to_poly_trait_ref();
-    let predicates = ty::lookup_super_predicates(tcx, trait_def_id);
+    let predicates = tcx.lookup_super_predicates(trait_def_id);
     predicates
         .predicates
         .into_iter()
@@ -153,8 +153,8 @@ fn trait_has_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
                               trait_def_id: ast::DefId)
                               -> bool
 {
-    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
-    let trait_predicates = ty::lookup_predicates(tcx, trait_def_id);
+    let trait_def = tcx.lookup_trait_def(trait_def_id);
+    let trait_predicates = tcx.lookup_predicates(trait_def_id);
     generics_require_sized_self(tcx, &trait_def.generics, &trait_predicates)
 }
 
@@ -169,7 +169,7 @@ fn generics_require_sized_self<'tcx>(tcx: &ty::ctxt<'tcx>,
     };
 
     // Search for a predicate like `Self : Sized` amongst the trait bounds.
-    let free_substs = ty::construct_free_substs(tcx, generics, ast::DUMMY_NODE_ID);
+    let free_substs = tcx.construct_free_substs(generics, ast::DUMMY_NODE_ID);
     let predicates = predicates.instantiate(tcx, &free_substs).predicates.into_vec();
     elaborate_predicates(tcx, predicates)
         .any(|predicate| {
@@ -306,7 +306,7 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     let mut supertraits: Option<Vec<ty::PolyTraitRef<'tcx>>> = None;
     let mut error = false;
-    ty::maybe_walk_ty(ty, |ty| {
+    ty.maybe_walk(|ty| {
         match ty.sty {
             ty::TyParam(ref param_ty) => {
                 if param_ty.space == SelfSpace {
@@ -321,7 +321,7 @@ fn contains_illegal_self_type_reference<'tcx>(tcx: &ty::ctxt<'tcx>,
 
                 // Compute supertraits of current trait lazily.
                 if supertraits.is_none() {
-                    let trait_def = ty::lookup_trait_def(tcx, trait_def_id);
+                    let trait_def = tcx.lookup_trait_def(trait_def_id);
                     let trait_ref = ty::Binder(trait_def.trait_ref.clone());
                     supertraits = Some(traits::supertraits(tcx, trait_ref).collect());
                 }
diff --git a/src/librustc/middle/traits/project.rs b/src/librustc/middle/traits/project.rs
index cb5440fbf90..184de682c67 100644
--- a/src/librustc/middle/traits/project.rs
+++ b/src/librustc/middle/traits/project.rs
@@ -23,8 +23,7 @@ use super::util;
 
 use middle::infer;
 use middle::subst::Subst;
-use middle::ty::{self, ToPredicate, ReferencesError, RegionEscape,
-                 HasProjectionTypes, ToPolyTraitRef, Ty};
+use middle::ty::{self, ToPredicate, RegionEscape, HasTypeFlags, ToPolyTraitRef, Ty};
 use middle::ty_fold::{self, TypeFoldable, TypeFolder};
 use syntax::parse::token;
 use util::common::FN_OUTPUT_NAME;
@@ -195,7 +194,7 @@ pub fn normalize<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tcx>,
                                cause: ObligationCause<'tcx>,
                                value: &T)
                                -> Normalized<'tcx, T>
-    where T : TypeFoldable<'tcx> + HasProjectionTypes
+    where T : TypeFoldable<'tcx> + HasTypeFlags
 {
     normalize_with_depth(selcx, cause, 0, value)
 }
@@ -206,7 +205,7 @@ pub fn normalize_with_depth<'a,'b,'tcx,T>(selcx: &'a mut SelectionContext<'b,'tc
                                           depth: usize,
                                           value: &T)
                                           -> Normalized<'tcx, T>
-    where T : TypeFoldable<'tcx> + HasProjectionTypes
+    where T : TypeFoldable<'tcx> + HasTypeFlags
 {
     let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
     let result = normalizer.fold(value);
@@ -238,7 +237,7 @@ impl<'a,'b,'tcx> AssociatedTypeNormalizer<'a,'b,'tcx> {
         }
     }
 
-    fn fold<T:TypeFoldable<'tcx> + HasProjectionTypes>(&mut self, value: &T) -> T {
+    fn fold<T:TypeFoldable<'tcx> + HasTypeFlags>(&mut self, value: &T) -> T {
         let value = self.selcx.infcx().resolve_type_vars_if_possible(value);
 
         if !value.has_projection_types() {
@@ -374,7 +373,7 @@ fn opt_normalize_projection_type<'a,'b,'tcx>(
                    depth,
                    obligations);
 
-            if ty::type_has_projection(projected_ty) {
+            if projected_ty.has_projection_types() {
                 let mut normalizer = AssociatedTypeNormalizer::new(selcx, cause, depth);
                 let normalized_ty = normalizer.fold(&projected_ty);
 
@@ -525,9 +524,9 @@ fn project_type<'cx,'tcx>(
             Ok(ProjectedTy::Progress(ty, obligations))
         }
         None => {
-            Ok(ProjectedTy::NoProgress(ty::mk_projection(selcx.tcx(),
-                                                         obligation.predicate.trait_ref.clone(),
-                                                         obligation.predicate.item_name)))
+            Ok(ProjectedTy::NoProgress(selcx.tcx().mk_projection(
+                obligation.predicate.trait_ref.clone(),
+                obligation.predicate.item_name)))
         }
     }
 }
@@ -575,7 +574,7 @@ fn assemble_candidates_from_trait_def<'cx,'tcx>(
     };
 
     // If so, extract what we know from the trait and try to come up with a good answer.
-    let trait_predicates = ty::lookup_predicates(selcx.tcx(), trait_ref.def_id);
+    let trait_predicates = selcx.tcx().lookup_predicates(trait_ref.def_id);
     let bounds = trait_predicates.instantiate(selcx.tcx(), trait_ref.substs);
     let bounds = elaborate_predicates(selcx.tcx(), bounds.predicates.into_vec());
     assemble_candidates_from_predicates(selcx, obligation, obligation_trait_ref,
@@ -774,7 +773,7 @@ fn confirm_fn_pointer_candidate<'cx,'tcx>(
     -> (Ty<'tcx>, Vec<PredicateObligation<'tcx>>)
 {
     let fn_type = selcx.infcx().shallow_resolve(fn_type);
-    let sig = ty::ty_fn_sig(fn_type);
+    let sig = fn_type.fn_sig();
     confirm_callable_candidate(selcx, obligation, sig, util::TupleArgumentsFlag::Yes)
 }
 
@@ -893,7 +892,7 @@ fn confirm_impl_candidate<'cx,'tcx>(
 
     // It is not in the impl - get the default from the trait.
     let trait_ref = obligation.predicate.trait_ref;
-    for trait_item in ty::trait_items(selcx.tcx(), trait_ref.def_id).iter() {
+    for trait_item in selcx.tcx().trait_items(trait_ref.def_id).iter() {
         if let &ty::TypeTraitItem(ref assoc_ty) = trait_item {
             if assoc_ty.name == obligation.predicate.item_name {
                 if let Some(ty) = assoc_ty.ty {
diff --git a/src/librustc/middle/traits/select.rs b/src/librustc/middle/traits/select.rs
index 4246d5f0e83..01faa6b7cf7 100644
--- a/src/librustc/middle/traits/select.rs
+++ b/src/librustc/middle/traits/select.rs
@@ -38,7 +38,7 @@ use super::util;
 
 use middle::fast_reject;
 use middle::subst::{Subst, Substs, TypeSpace};
-use middle::ty::{self, ToPredicate, RegionEscape, ToPolyTraitRef, Ty};
+use middle::ty::{self, ToPredicate, RegionEscape, ToPolyTraitRef, Ty, HasTypeFlags};
 use middle::infer;
 use middle::infer::{InferCtxt, TypeFreshener};
 use middle::ty_fold::TypeFoldable;
@@ -540,7 +540,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // terms of `Fn` etc, but we could probably make this more
         // precise still.
         let input_types = stack.fresh_trait_ref.0.input_types();
-        let unbound_input_types = input_types.iter().any(|&t| ty::type_is_fresh(t));
+        let unbound_input_types = input_types.iter().any(|ty| ty.is_fresh());
         if
             unbound_input_types &&
              (self.intercrate ||
@@ -675,7 +675,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                               stack: &TraitObligationStack<'o, 'tcx>)
                                               -> SelectionResult<'tcx, SelectionCandidate<'tcx>>
     {
-        if ty::type_is_error(stack.obligation.predicate.0.self_ty()) {
+        if stack.obligation.predicate.0.self_ty().references_error() {
             return Ok(Some(ErrorCandidate));
         }
 
@@ -773,7 +773,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         match candidate {
             ImplCandidate(def_id) => {
-                match ty::trait_impl_polarity(self.tcx(), def_id) {
+                match self.tcx().trait_impl_polarity(def_id) {
                     Some(ast::ImplPolarity::Negative) => return Err(Unimplemented),
                     _ => {}
                 }
@@ -886,7 +886,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         match *candidate {
             Ok(Some(_)) | Err(_) => true,
             Ok(None) => {
-                cache_fresh_trait_pred.0.input_types().iter().any(|&t| ty::type_has_ty_infer(t))
+                cache_fresh_trait_pred.0.input_types().has_infer_types()
             }
         }
     }
@@ -1024,7 +1024,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                 projection_trait_ref={:?}",
                projection_trait_ref);
 
-        let trait_predicates = ty::lookup_predicates(self.tcx(), projection_trait_ref.def_id);
+        let trait_predicates = self.tcx().lookup_predicates(projection_trait_ref.def_id);
         let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
         debug!("match_projection_obligation_against_bounds_from_trait: \
                 bounds={:?}",
@@ -1224,7 +1224,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     {
         debug!("assemble_candidates_from_impls(obligation={:?})", obligation);
 
-        let def = ty::lookup_trait_def(self.tcx(), obligation.predicate.def_id());
+        let def = self.tcx().lookup_trait_def(obligation.predicate.def_id());
 
         def.for_each_relevant_impl(
             self.tcx(),
@@ -1252,7 +1252,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         let def_id = obligation.predicate.def_id();
 
-        if ty::trait_has_default_impl(self.tcx(), def_id) {
+        if self.tcx().trait_has_default_impl(def_id) {
             match self_ty.sty {
                 ty::TyTrait(..) => {
                     // For object types, we don't know what the closed
@@ -1264,7 +1264,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     // object types, because it just lets you reflect
                     // onto the object type, not into the object's
                     // interior.
-                    if ty::has_attr(self.tcx(), def_id, "rustc_reflect_like") {
+                    if self.tcx().has_attr(def_id, "rustc_reflect_like") {
                         candidates.vec.push(DefaultImplObjectCandidate(def_id));
                     }
                 }
@@ -1397,7 +1397,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         //     T: Trait
         // so it seems ok if we (conservatively) fail to accept that `Unsize`
         // obligation above. Should be possible to extend this in the future.
-        let self_ty = match ty::no_late_bound_regions(self.tcx(), &obligation.self_ty()) {
+        let self_ty = match self.tcx().no_late_bound_regions(&obligation.self_ty()) {
             Some(t) => t,
             None => {
                 // Don't add any candidates if there are bound regions.
@@ -1736,7 +1736,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             ty::TyStruct(def_id, substs) => {
                 let types: Vec<Ty> =
-                    ty::struct_fields(self.tcx(), def_id, substs).iter()
+                    self.tcx().struct_fields(def_id, substs).iter()
                                                                  .map(|f| f.mt.ty)
                                                                  .collect();
                 nominal(bound, types)
@@ -1744,7 +1744,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             ty::TyEnum(def_id, substs) => {
                 let types: Vec<Ty> =
-                    ty::substd_enum_variants(self.tcx(), def_id, substs)
+                    self.tcx().substd_enum_variants(def_id, substs)
                     .iter()
                     .flat_map(|variant| &variant.args)
                     .cloned()
@@ -1881,13 +1881,13 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
             }
 
             ty::TyStruct(def_id, substs) => {
-                Some(ty::struct_fields(self.tcx(), def_id, substs).iter()
+                Some(self.tcx().struct_fields(def_id, substs).iter()
                      .map(|f| f.mt.ty)
                      .collect())
             }
 
             ty::TyEnum(def_id, substs) => {
-                Some(ty::substd_enum_variants(self.tcx(), def_id, substs)
+                Some(self.tcx().substd_enum_variants(def_id, substs)
                      .iter()
                      .flat_map(|variant| &variant.args)
                      .map(|&ty| ty)
@@ -2161,7 +2161,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                obligation,
                trait_def_id);
 
-        assert!(ty::has_attr(self.tcx(), trait_def_id, "rustc_reflect_like"));
+        assert!(self.tcx().has_attr(trait_def_id, "rustc_reflect_like"));
 
         // OK to skip binder, it is reintroduced below
         let self_ty = self.infcx.shallow_resolve(obligation.predicate.skip_binder().self_ty());
@@ -2178,7 +2178,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
                 // reintroduce the two binding levels we skipped, then flatten into one
                 let all_types = ty::Binder(ty::Binder(all_types));
-                let all_types = ty::flatten_late_bound_regions(self.tcx(), &all_types);
+                let all_types = self.tcx().flatten_late_bound_regions(&all_types);
 
                 self.vtable_default_impl(obligation, trait_def_id, all_types)
             }
@@ -2334,7 +2334,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
         // ok to skip binder; it is reintroduced below
         let self_ty = self.infcx.shallow_resolve(*obligation.self_ty().skip_binder());
-        let sig = ty::ty_fn_sig(self_ty);
+        let sig = self_ty.fn_sig();
         let trait_ref =
             util::closure_trait_ref_and_return_type(self.tcx(),
                                                     obligation.predicate.def_id(),
@@ -2434,7 +2434,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
         // assemble_candidates_for_unsizing should ensure there are no late bound
         // regions here. See the comment there for more details.
         let source = self.infcx.shallow_resolve(
-            ty::no_late_bound_regions(tcx, &obligation.self_ty()).unwrap());
+            tcx.no_late_bound_regions(&obligation.self_ty()).unwrap());
         let target = self.infcx.shallow_resolve(obligation.predicate.0.input_types()[0]);
 
         debug!("confirm_builtin_unsize_candidate(source={:?}, target={:?})",
@@ -2451,7 +2451,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     projection_bounds: data_a.bounds.projection_bounds.clone(),
                 };
 
-                let new_trait = ty::mk_trait(tcx, data_a.principal.clone(), bounds);
+                let new_trait = tcx.mk_trait(data_a.principal.clone(), bounds);
                 let origin = infer::Misc(obligation.cause.span);
                 if self.infcx.sub_types(false, origin, new_trait, target).is_err() {
                     return Err(Unimplemented);
@@ -2525,8 +2525,8 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
 
             // Struct<T> -> Struct<U>.
             (&ty::TyStruct(def_id, substs_a), &ty::TyStruct(_, substs_b)) => {
-                let fields = ty::lookup_struct_fields(tcx, def_id).iter().map(|f| {
-                    ty::lookup_field_type_unsubstituted(tcx, def_id, f.id)
+                let fields = tcx.lookup_struct_fields(def_id).iter().map(|f| {
+                    tcx.lookup_field_type_unsubstituted(def_id, f.id)
                 }).collect::<Vec<_>>();
 
                 // The last field of the structure has to exist and contain type parameters.
@@ -2536,7 +2536,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     return Err(Unimplemented);
                 };
                 let mut ty_params = vec![];
-                ty::walk_ty(field, |ty| {
+                for ty in field.walk() {
                     if let ty::TyParam(p) = ty.sty {
                         assert!(p.space == TypeSpace);
                         let idx = p.idx as usize;
@@ -2544,7 +2544,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                             ty_params.push(idx);
                         }
                     }
-                });
+                }
                 if ty_params.is_empty() {
                     return Err(Unimplemented);
                 }
@@ -2558,7 +2558,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     new_substs.types.get_mut_slice(TypeSpace)[i] = tcx.types.err;
                 }
                 for &ty in fields.init() {
-                    if ty::type_is_error(ty.subst(tcx, &new_substs)) {
+                    if ty.subst(tcx, &new_substs).references_error() {
                         return Err(Unimplemented);
                     }
                 }
@@ -2573,7 +2573,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                     let param_b = *substs_b.types.get(TypeSpace, i);
                     new_substs.types.get_mut_slice(TypeSpace)[i] = param_b;
                 }
-                let new_struct = ty::mk_struct(tcx, def_id, tcx.mk_substs(new_substs));
+                let new_struct = tcx.mk_struct(def_id, tcx.mk_substs(new_substs));
                 let origin = infer::Misc(obligation.cause.span);
                 if self.infcx.sub_types(false, origin, new_struct, target).is_err() {
                     return Err(Unimplemented);
@@ -2628,7 +2628,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                   -> Result<(Normalized<'tcx, Substs<'tcx>>,
                              infer::SkolemizationMap), ()>
     {
-        let impl_trait_ref = ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap();
+        let impl_trait_ref = self.tcx().impl_trait_ref(impl_def_id).unwrap();
 
         // Before we create the substitutions and everything, first
         // consider a "quick reject". This avoids creating more types
@@ -2765,7 +2765,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
                                                          impl_def_id);
 
         // Find the self type for the impl.
-        let impl_self_ty = ty::lookup_item_type(self.tcx(), impl_def_id).ty;
+        let impl_self_ty = self.tcx().lookup_item_type(impl_def_id).ty;
         let impl_self_ty = impl_self_ty.subst(self.tcx(), &impl_substs);
 
         debug!("match_impl_self_types(obligation_self_ty={:?}, impl_self_ty={:?})",
@@ -2890,7 +2890,7 @@ impl<'cx, 'tcx> SelectionContext<'cx, 'tcx> {
     {
         debug!("impl_or_trait_obligations(def_id={:?})", def_id);
 
-        let predicates = ty::lookup_predicates(self.tcx(), def_id);
+        let predicates = self.tcx().lookup_predicates(def_id);
         let predicates = predicates.instantiate(self.tcx(), substs);
         let predicates = normalize_with_depth(self, cause.clone(), recursion_depth, &predicates);
         let mut predicates = self.infcx().plug_leaks(skol_map, snapshot, &predicates);
diff --git a/src/librustc/middle/traits/util.rs b/src/librustc/middle/traits/util.rs
index 7b4a59b5427..5c9a8d6c1aa 100644
--- a/src/librustc/middle/traits/util.rs
+++ b/src/librustc/middle/traits/util.rs
@@ -43,19 +43,19 @@ impl<'a,'tcx> PredicateSet<'a,'tcx> {
         // regions before we throw things into the underlying set.
         let normalized_pred = match *pred {
             ty::Predicate::Trait(ref data) =>
-                ty::Predicate::Trait(ty::anonymize_late_bound_regions(self.tcx, data)),
+                ty::Predicate::Trait(self.tcx.anonymize_late_bound_regions(data)),
 
             ty::Predicate::Equate(ref data) =>
-                ty::Predicate::Equate(ty::anonymize_late_bound_regions(self.tcx, data)),
+                ty::Predicate::Equate(self.tcx.anonymize_late_bound_regions(data)),
 
             ty::Predicate::RegionOutlives(ref data) =>
-                ty::Predicate::RegionOutlives(ty::anonymize_late_bound_regions(self.tcx, data)),
+                ty::Predicate::RegionOutlives(self.tcx.anonymize_late_bound_regions(data)),
 
             ty::Predicate::TypeOutlives(ref data) =>
-                ty::Predicate::TypeOutlives(ty::anonymize_late_bound_regions(self.tcx, data)),
+                ty::Predicate::TypeOutlives(self.tcx.anonymize_late_bound_regions(data)),
 
             ty::Predicate::Projection(ref data) =>
-                ty::Predicate::Projection(ty::anonymize_late_bound_regions(self.tcx, data)),
+                ty::Predicate::Projection(self.tcx.anonymize_late_bound_regions(data)),
         };
         self.set.insert(normalized_pred)
     }
@@ -116,7 +116,7 @@ impl<'cx, 'tcx> Elaborator<'cx, 'tcx> {
         match *predicate {
             ty::Predicate::Trait(ref data) => {
                 // Predicates declared on the trait.
-                let predicates = ty::lookup_super_predicates(self.tcx, data.def_id());
+                let predicates = self.tcx.lookup_super_predicates(data.def_id());
 
                 let mut predicates: Vec<_> =
                     predicates.predicates
@@ -236,7 +236,7 @@ impl<'cx, 'tcx> Iterator for SupertraitDefIds<'cx, 'tcx> {
             None => { return None; }
         };
 
-        let predicates = ty::lookup_super_predicates(self.tcx, def_id);
+        let predicates = self.tcx.lookup_super_predicates(def_id);
         let visited = &mut self.visited;
         self.stack.extend(
             predicates.predicates
@@ -297,7 +297,7 @@ pub fn fresh_type_vars_for_impl<'a, 'tcx>(infcx: &InferCtxt<'a, 'tcx>,
                                           -> Substs<'tcx>
 {
     let tcx = infcx.tcx;
-    let impl_generics = ty::lookup_item_type(tcx, impl_def_id).generics;
+    let impl_generics = tcx.lookup_item_type(impl_def_id).generics;
     infcx.fresh_substs_for_generics(span, &impl_generics)
 }
 
@@ -416,7 +416,7 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
             break;
         }
 
-        let trait_items = ty::trait_items(tcx, bound_ref.def_id());
+        let trait_items = tcx.trait_items(bound_ref.def_id());
         for trait_item in trait_items.iter() {
             match *trait_item {
                 ty::MethodTraitItem(_) => method_count += 1,
@@ -427,7 +427,7 @@ pub fn get_vtable_index_of_object_method<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     // count number of methods preceding the one we are selecting and
     // add them to the total offset; skip over associated types.
-    let trait_items = ty::trait_items(tcx, trait_def_id);
+    let trait_items = tcx.trait_items(trait_def_id);
     for trait_item in trait_items.iter().take(method_offset_in_trait) {
         match *trait_item {
             ty::MethodTraitItem(_) => method_count += 1,
@@ -456,14 +456,14 @@ pub fn closure_trait_ref_and_return_type<'tcx>(
 {
     let arguments_tuple = match tuple_arguments {
         TupleArgumentsFlag::No => sig.0.inputs[0],
-        TupleArgumentsFlag::Yes => ty::mk_tup(tcx, sig.0.inputs.to_vec()),
+        TupleArgumentsFlag::Yes => tcx.mk_tup(sig.0.inputs.to_vec()),
     };
     let trait_substs = Substs::new_trait(vec![arguments_tuple], vec![], self_ty);
     let trait_ref = ty::TraitRef {
         def_id: fn_trait_def_id,
         substs: tcx.mk_substs(trait_substs),
     };
-    ty::Binder((trait_ref, sig.0.output.unwrap_or(ty::mk_nil(tcx))))
+    ty::Binder((trait_ref, sig.0.output.unwrap_or(tcx.mk_nil())))
 }
 
 impl<'tcx,O:fmt::Debug> fmt::Debug for super::Obligation<'tcx, O> {
diff --git a/src/librustc/middle/ty.rs b/src/librustc/middle/ty.rs
index 3f84d433e9c..302ec08db6f 100644
--- a/src/librustc/middle/ty.rs
+++ b/src/librustc/middle/ty.rs
@@ -51,9 +51,9 @@ use middle::def::{self, DefMap, ExportMap};
 use middle::dependency_format;
 use middle::fast_reject;
 use middle::free_region::FreeRegionMap;
-use middle::infer::error_reporting::note_and_explain_region;
 use middle::lang_items::{FnTraitLangItem, FnMutTraitLangItem, FnOnceTraitLangItem};
 use middle::mem_categorization as mc;
+use middle::mem_categorization::Typer;
 use middle::region;
 use middle::resolve_lifetime;
 use middle::infer;
@@ -85,7 +85,7 @@ use std::collections::{HashMap, HashSet};
 use syntax::abi;
 use syntax::ast::{CrateNum, DefId, ItemImpl, ItemTrait, LOCAL_CRATE};
 use syntax::ast::{MutImmutable, MutMutable, Name, NamedField, NodeId};
-use syntax::ast::{StmtExpr, StmtSemi, StructField, UnnamedField, Visibility};
+use syntax::ast::{StructField, UnnamedField, Visibility};
 use syntax::ast_util::{self, is_local, local_def};
 use syntax::attr::{self, AttrMetaMethods, SignedInt, UnsignedInt};
 use syntax::codemap::Span;
@@ -117,6 +117,221 @@ pub struct field<'tcx> {
     pub mt: mt<'tcx>
 }
 
+
+
+// Enum information
+#[derive(Clone)]
+pub struct VariantInfo<'tcx> {
+    pub args: Vec<Ty<'tcx>>,
+    pub arg_names: Option<Vec<ast::Name>>,
+    pub ctor_ty: Option<Ty<'tcx>>,
+    pub name: ast::Name,
+    pub id: ast::DefId,
+    pub disr_val: Disr,
+    pub vis: Visibility
+}
+
+impl<'tcx> VariantInfo<'tcx> {
+
+    /// Creates a new VariantInfo from the corresponding ast representation.
+    ///
+    /// Does not do any caching of the value in the type context.
+    pub fn from_ast_variant(cx: &ctxt<'tcx>,
+                            ast_variant: &ast::Variant,
+                            discriminant: Disr) -> VariantInfo<'tcx> {
+        let ctor_ty = cx.node_id_to_type(ast_variant.node.id);
+
+        match ast_variant.node.kind {
+            ast::TupleVariantKind(ref args) => {
+                let arg_tys = if !args.is_empty() {
+                    // the regions in the argument types come from the
+                    // enum def'n, and hence will all be early bound
+                    cx.no_late_bound_regions(&ctor_ty.fn_args()).unwrap()
+                } else {
+                    Vec::new()
+                };
+
+                return VariantInfo {
+                    args: arg_tys,
+                    arg_names: None,
+                    ctor_ty: Some(ctor_ty),
+                    name: ast_variant.node.name.name,
+                    id: ast_util::local_def(ast_variant.node.id),
+                    disr_val: discriminant,
+                    vis: ast_variant.node.vis
+                };
+            },
+            ast::StructVariantKind(ref struct_def) => {
+                let fields: &[StructField] = &struct_def.fields;
+
+                assert!(!fields.is_empty());
+
+                let arg_tys = struct_def.fields.iter()
+                    .map(|field| cx.node_id_to_type(field.node.id)).collect();
+                let arg_names = fields.iter().map(|field| {
+                    match field.node.kind {
+                        NamedField(ident, _) => ident.name,
+                        UnnamedField(..) => cx.sess.bug(
+                            "enum_variants: all fields in struct must have a name")
+                    }
+                }).collect();
+
+                return VariantInfo {
+                    args: arg_tys,
+                    arg_names: Some(arg_names),
+                    ctor_ty: None,
+                    name: ast_variant.node.name.name,
+                    id: ast_util::local_def(ast_variant.node.id),
+                    disr_val: discriminant,
+                    vis: ast_variant.node.vis
+                };
+            }
+        }
+    }
+}
+
+#[derive(Copy, Clone)]
+pub enum DtorKind {
+    NoDtor,
+    TraitDtor(DefId, bool)
+}
+
+impl DtorKind {
+    pub fn is_present(&self) -> bool {
+        match *self {
+            TraitDtor(..) => true,
+            _ => false
+        }
+    }
+
+    pub fn has_drop_flag(&self) -> bool {
+        match self {
+            &NoDtor => false,
+            &TraitDtor(_, flag) => flag
+        }
+    }
+}
+
+trait IntTypeExt {
+    fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>;
+    fn i64_to_disr(&self, val: i64) -> Option<Disr>;
+    fn u64_to_disr(&self, val: u64) -> Option<Disr>;
+    fn disr_incr(&self, val: Disr) -> Option<Disr>;
+    fn disr_string(&self, val: Disr) -> String;
+    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr;
+}
+
+impl IntTypeExt for attr::IntType {
+    fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
+        match *self {
+            SignedInt(ast::TyI8)      => cx.types.i8,
+            SignedInt(ast::TyI16)     => cx.types.i16,
+            SignedInt(ast::TyI32)     => cx.types.i32,
+            SignedInt(ast::TyI64)     => cx.types.i64,
+            SignedInt(ast::TyIs)   => cx.types.isize,
+            UnsignedInt(ast::TyU8)    => cx.types.u8,
+            UnsignedInt(ast::TyU16)   => cx.types.u16,
+            UnsignedInt(ast::TyU32)   => cx.types.u32,
+            UnsignedInt(ast::TyU64)   => cx.types.u64,
+            UnsignedInt(ast::TyUs) => cx.types.usize,
+        }
+    }
+
+    fn i64_to_disr(&self, val: i64) -> Option<Disr> {
+        match *self {
+            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+
+    fn u64_to_disr(&self, val: u64) -> Option<Disr> {
+        match *self {
+            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
+            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
+            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
+            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
+            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
+            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+
+    fn disr_incr(&self, val: Disr) -> Option<Disr> {
+        macro_rules! add1 {
+            ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) }
+        }
+        match *self {
+            // SignedInt repr means we *want* to reinterpret the bits
+            // treating the highest bit of Disr as a sign-bit, so
+            // cast to i64 before range-checking.
+            SignedInt(ast::TyI8)    => add1!((val as i64).to_i8()),
+            SignedInt(ast::TyI16)   => add1!((val as i64).to_i16()),
+            SignedInt(ast::TyI32)   => add1!((val as i64).to_i32()),
+            SignedInt(ast::TyI64)   => add1!(Some(val as i64)),
+
+            UnsignedInt(ast::TyU8)  => add1!(val.to_u8()),
+            UnsignedInt(ast::TyU16) => add1!(val.to_u16()),
+            UnsignedInt(ast::TyU32) => add1!(val.to_u32()),
+            UnsignedInt(ast::TyU64) => add1!(Some(val)),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+
+    // This returns a String because (1.) it is only used for
+    // rendering an error message and (2.) a string can represent the
+    // full range from `i64::MIN` through `u64::MAX`.
+    fn disr_string(&self, val: Disr) -> String {
+        match *self {
+            SignedInt(ast::TyI8)    => format!("{}", val as i8 ),
+            SignedInt(ast::TyI16)   => format!("{}", val as i16),
+            SignedInt(ast::TyI32)   => format!("{}", val as i32),
+            SignedInt(ast::TyI64)   => format!("{}", val as i64),
+            UnsignedInt(ast::TyU8)  => format!("{}", val as u8 ),
+            UnsignedInt(ast::TyU16) => format!("{}", val as u16),
+            UnsignedInt(ast::TyU32) => format!("{}", val as u32),
+            UnsignedInt(ast::TyU64) => format!("{}", val as u64),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+
+    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr {
+        macro_rules! add1 {
+            ($e:expr) => { ($e).wrapping_add(1) as Disr }
+        }
+        let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE);
+        match *self {
+            SignedInt(ast::TyI8)    => add1!(val as i8 ),
+            SignedInt(ast::TyI16)   => add1!(val as i16),
+            SignedInt(ast::TyI32)   => add1!(val as i32),
+            SignedInt(ast::TyI64)   => add1!(val as i64),
+            UnsignedInt(ast::TyU8)  => add1!(val as u8 ),
+            UnsignedInt(ast::TyU16) => add1!(val as u16),
+            UnsignedInt(ast::TyU32) => add1!(val as u32),
+            UnsignedInt(ast::TyU64) => add1!(val as u64),
+
+            UnsignedInt(ast::TyUs) |
+            SignedInt(ast::TyIs) => unreachable!(),
+        }
+    }
+}
+
 #[derive(Clone, Copy, Debug)]
 pub enum ImplOrTraitItemContainer {
     TraitContainer(ast::DefId),
@@ -303,6 +518,17 @@ pub enum Variance {
     Bivariant,      // T<A> <: T<B>            -- e.g., unused type parameter
 }
 
+impl fmt::Debug for Variance {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        f.write_str(match *self {
+            Covariant => "+",
+            Contravariant => "-",
+            Invariant => "o",
+            Bivariant => "*",
+        })
+    }
+}
+
 #[derive(Copy, Clone)]
 pub enum AutoAdjustment<'tcx> {
     AdjustReifyFnPointer,   // go from a fn-item type to a fn-pointer type
@@ -963,7 +1189,7 @@ pub mod tls {
                     Some(ast_map::NodeTraitItem(..)) |
                     Some(ast_map::NodeVariant(..)) |
                     Some(ast_map::NodeStructCtor(..)) => {
-                        return write!(f, "{}", ty::item_path_str(tcx, def_id));
+                        return write!(f, "{}", tcx.item_path_str(def_id));
                     }
                     _ => {}
                 }
@@ -1180,64 +1406,6 @@ impl<'tcx> Borrow<TypeVariants<'tcx>> for InternedTy<'tcx> {
     }
 }
 
-pub fn type_has_params(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::HAS_PARAMS)
-}
-pub fn type_has_self(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::HAS_SELF)
-}
-pub fn type_has_ty_infer(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::HAS_TY_INFER)
-}
-pub fn type_needs_infer(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
-}
-pub fn type_is_global(ty: Ty) -> bool {
-    !ty.flags.get().intersects(TypeFlags::HAS_LOCAL_NAMES)
-}
-pub fn type_has_projection(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::HAS_PROJECTION)
-}
-pub fn type_has_ty_closure(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::HAS_TY_CLOSURE)
-}
-
-pub fn type_has_erasable_regions(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::HAS_RE_EARLY_BOUND |
-                              TypeFlags::HAS_RE_INFER |
-                              TypeFlags::HAS_FREE_REGIONS)
-}
-
-/// An "escaping region" is a bound region whose binder is not part of `t`.
-///
-/// So, for example, consider a type like the following, which has two binders:
-///
-///    for<'a> fn(x: for<'b> fn(&'a isize, &'b isize))
-///    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
-///                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~  inner scope
-///
-/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the
-/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
-/// fn type*, that type has an escaping region: `'a`.
-///
-/// Note that what I'm calling an "escaping region" is often just called a "free region". However,
-/// we already use the term "free region". It refers to the regions that we use to represent bound
-/// regions on a fn definition while we are typechecking its body.
-///
-/// To clarify, conceptually there is no particular difference between an "escaping" region and a
-/// "free" region. However, there is a big difference in practice. Basically, when "entering" a
-/// binding level, one is generally required to do some sort of processing to a bound region, such
-/// as replacing it with a fresh/skolemized region, or making an entry in the environment to
-/// represent the scope to which it is attached, etc. An escaping region represents a bound region
-/// for which this processing has not yet been done.
-pub fn type_has_escaping_regions(ty: Ty) -> bool {
-    type_escapes_depth(ty, 0)
-}
-
-pub fn type_escapes_depth(ty: Ty, depth: u32) -> bool {
-    ty.region_depth > depth
-}
-
 #[derive(Clone, PartialEq, Eq, Hash, Debug)]
 pub struct BareFnTy<'tcx> {
     pub unsafety: ast::Unsafety,
@@ -1496,16 +1664,14 @@ pub struct UpvarBorrow {
 
 pub type UpvarCaptureMap = FnvHashMap<UpvarId, UpvarCapture>;
 
-impl Region {
-    pub fn is_global(&self) -> bool {
-        // does this represent a region that can be named in a global
-        // way? used in fulfillment caching.
-        match *self {
-            ty::ReStatic | ty::ReEmpty => true,
-            _ => false,
-        }
-    }
+#[derive(Copy, Clone)]
+pub struct ClosureUpvar<'tcx> {
+    pub def: def::Def,
+    pub span: Span,
+    pub ty: Ty<'tcx>,
+}
 
+impl Region {
     pub fn is_bound(&self) -> bool {
         match *self {
             ty::ReEarlyBound(..) => true,
@@ -1907,13 +2073,6 @@ pub enum BuiltinBound {
     Sync,
 }
 
-/// An existential bound that does not implement any traits.
-pub fn region_existential_bound<'tcx>(r: ty::Region) -> ExistentialBounds<'tcx> {
-    ty::ExistentialBounds { region_bound: r,
-                            builtin_bounds: BuiltinBounds::empty(),
-                            projection_bounds: Vec::new() }
-}
-
 impl CLike for BuiltinBound {
     fn to_usize(&self) -> usize {
         *self as usize
@@ -2130,7 +2289,7 @@ impl<'tcx> GenericPredicates<'tcx> {
         }
     }
 
-    pub fn instantiate(&self, tcx: &ty::ctxt<'tcx>, substs: &Substs<'tcx>)
+    pub fn instantiate(&self, tcx: &ctxt<'tcx>, substs: &Substs<'tcx>)
                        -> InstantiatedPredicates<'tcx> {
         InstantiatedPredicates {
             predicates: self.predicates.subst(tcx, substs),
@@ -2138,7 +2297,7 @@ impl<'tcx> GenericPredicates<'tcx> {
     }
 
     pub fn instantiate_supertrait(&self,
-                                  tcx: &ty::ctxt<'tcx>,
+                                  tcx: &ctxt<'tcx>,
                                   poly_trait_ref: &ty::PolyTraitRef<'tcx>)
                                   -> InstantiatedPredicates<'tcx>
     {
@@ -2176,7 +2335,7 @@ impl<'tcx> Predicate<'tcx> {
     /// substitution in terms of what happens with bound regions.  See
     /// lengthy comment below for details.
     pub fn subst_supertrait(&self,
-                            tcx: &ty::ctxt<'tcx>,
+                            tcx: &ctxt<'tcx>,
                             trait_ref: &ty::PolyTraitRef<'tcx>)
                             -> ty::Predicate<'tcx>
     {
@@ -2254,29 +2413,6 @@ impl<'tcx> Predicate<'tcx> {
                 Predicate::Projection(ty::Binder(data.subst(tcx, substs))),
         }
     }
-
-    // Indicates whether this predicate references only 'global'
-    // types/lifetimes that are the same regardless of what fn we are
-    // in. This is used for caching. Errs on the side of returning
-    // false.
-    pub fn is_global(&self) -> bool {
-        match *self {
-            ty::Predicate::Trait(ref data) => {
-                let substs = data.skip_binder().trait_ref.substs;
-
-                substs.types.iter().all(|t| ty::type_is_global(t)) && {
-                    match substs.regions {
-                        subst::ErasedRegions => true,
-                        subst::NonerasedRegions(ref r) => r.iter().all(|r| r.is_global()),
-                    }
-                }
-            }
-
-            _ => {
-                false
-            }
-        }
-    }
 }
 
 #[derive(Clone, PartialEq, Eq, Hash)]
@@ -2608,22 +2744,20 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                 match impl_item.node {
                     ast::ConstImplItem(_, _) => {
                         let def_id = ast_util::local_def(id);
-                        let scheme = lookup_item_type(cx, def_id);
-                        let predicates = lookup_predicates(cx, def_id);
-                        construct_parameter_environment(cx,
-                                                        impl_item.span,
-                                                        &scheme.generics,
-                                                        &predicates,
-                                                        id)
+                        let scheme = cx.lookup_item_type(def_id);
+                        let predicates = cx.lookup_predicates(def_id);
+                        cx.construct_parameter_environment(impl_item.span,
+                                                           &scheme.generics,
+                                                           &predicates,
+                                                           id)
                     }
                     ast::MethodImplItem(_, ref body) => {
                         let method_def_id = ast_util::local_def(id);
-                        match ty::impl_or_trait_item(cx, method_def_id) {
+                        match cx.impl_or_trait_item(method_def_id) {
                             MethodTraitItem(ref method_ty) => {
                                 let method_generics = &method_ty.generics;
                                 let method_bounds = &method_ty.predicates;
-                                construct_parameter_environment(
-                                    cx,
+                                cx.construct_parameter_environment(
                                     impl_item.span,
                                     method_generics,
                                     method_bounds,
@@ -2650,13 +2784,12 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                         match *default {
                             Some(_) => {
                                 let def_id = ast_util::local_def(id);
-                                let scheme = lookup_item_type(cx, def_id);
-                                let predicates = lookup_predicates(cx, def_id);
-                                construct_parameter_environment(cx,
-                                                                trait_item.span,
-                                                                &scheme.generics,
-                                                                &predicates,
-                                                                id)
+                                let scheme = cx.lookup_item_type(def_id);
+                                let predicates = cx.lookup_predicates(def_id);
+                                cx.construct_parameter_environment(trait_item.span,
+                                                                   &scheme.generics,
+                                                                   &predicates,
+                                                                   id)
                             }
                             None => {
                                 cx.sess.bug("ParameterEnvironment::from_item(): \
@@ -2674,12 +2807,11 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                     }
                     ast::MethodTraitItem(_, Some(ref body)) => {
                         let method_def_id = ast_util::local_def(id);
-                        match ty::impl_or_trait_item(cx, method_def_id) {
+                        match cx.impl_or_trait_item(method_def_id) {
                             MethodTraitItem(ref method_ty) => {
                                 let method_generics = &method_ty.generics;
                                 let method_bounds = &method_ty.predicates;
-                                construct_parameter_environment(
-                                    cx,
+                                cx.construct_parameter_environment(
                                     trait_item.span,
                                     method_generics,
                                     method_bounds,
@@ -2705,14 +2837,13 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                     ast::ItemFn(_, _, _, _, _, ref body) => {
                         // We assume this is a function.
                         let fn_def_id = ast_util::local_def(id);
-                        let fn_scheme = lookup_item_type(cx, fn_def_id);
-                        let fn_predicates = lookup_predicates(cx, fn_def_id);
-
-                        construct_parameter_environment(cx,
-                                                        item.span,
-                                                        &fn_scheme.generics,
-                                                        &fn_predicates,
-                                                        body.id)
+                        let fn_scheme = cx.lookup_item_type(fn_def_id);
+                        let fn_predicates = cx.lookup_predicates(fn_def_id);
+
+                        cx.construct_parameter_environment(item.span,
+                                                           &fn_scheme.generics,
+                                                           &fn_predicates,
+                                                           body.id)
                     }
                     ast::ItemEnum(..) |
                     ast::ItemStruct(..) |
@@ -2720,13 +2851,12 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
                     ast::ItemConst(..) |
                     ast::ItemStatic(..) => {
                         let def_id = ast_util::local_def(id);
-                        let scheme = lookup_item_type(cx, def_id);
-                        let predicates = lookup_predicates(cx, def_id);
-                        construct_parameter_environment(cx,
-                                                        item.span,
-                                                        &scheme.generics,
-                                                        &predicates,
-                                                        id)
+                        let scheme = cx.lookup_item_type(def_id);
+                        let predicates = cx.lookup_predicates(def_id);
+                        cx.construct_parameter_environment(item.span,
+                                                           &scheme.generics,
+                                                           &predicates,
+                                                           id)
                     }
                     _ => {
                         cx.sess.span_bug(item.span,
@@ -2747,6 +2877,51 @@ impl<'a, 'tcx> ParameterEnvironment<'a, 'tcx> {
             }
         }
     }
+
+    pub fn can_type_implement_copy(&self, self_type: Ty<'tcx>, span: Span)
+                                   -> Result<(),CopyImplementationError> {
+        let tcx = self.tcx;
+
+        let did = match self_type.sty {
+            ty::TyStruct(struct_did, substs) => {
+                let fields = tcx.struct_fields(struct_did, substs);
+                for field in &fields {
+                    if self.type_moves_by_default(field.mt.ty, span) {
+                        return Err(FieldDoesNotImplementCopy(field.name))
+                    }
+                }
+                struct_did
+            }
+            ty::TyEnum(enum_did, substs) => {
+                let enum_variants = tcx.enum_variants(enum_did);
+                for variant in enum_variants.iter() {
+                    for variant_arg_type in &variant.args {
+                        let substd_arg_type =
+                            variant_arg_type.subst(tcx, substs);
+                        if self.type_moves_by_default(substd_arg_type, span) {
+                            return Err(VariantDoesNotImplementCopy(variant.name))
+                        }
+                    }
+                }
+                enum_did
+            }
+            _ => return Err(TypeIsStructural),
+        };
+
+        if tcx.has_dtor(did) {
+            return Err(TypeHasDestructor)
+        }
+
+        Ok(())
+    }
+}
+
+#[derive(Copy, Clone)]
+pub enum CopyImplementationError {
+    FieldDoesNotImplementCopy(ast::Name),
+    VariantDoesNotImplementCopy(ast::Name),
+    TypeIsStructural,
+    TypeHasDestructor,
 }
 
 /// A "type scheme", in ML terminology, is a type combined with some
@@ -2874,7 +3049,7 @@ impl<'tcx> TraitDef<'tcx> {
 
 
     pub fn for_each_impl<F: FnMut(DefId)>(&self, tcx: &ctxt<'tcx>, mut f: F)  {
-        ty::populate_implementations_for_trait_if_necessary(tcx, self.trait_ref.def_id);
+        tcx.populate_implementations_for_trait_if_necessary(self.trait_ref.def_id);
 
         for &impl_def_id in self.blanket_impls.borrow().iter() {
             f(impl_def_id);
@@ -2892,7 +3067,7 @@ impl<'tcx> TraitDef<'tcx> {
                                                    self_ty: Ty<'tcx>,
                                                    mut f: F)
     {
-        ty::populate_implementations_for_trait_if_necessary(tcx, self.trait_ref.def_id);
+        tcx.populate_implementations_for_trait_if_necessary(self.trait_ref.def_id);
 
         for &impl_def_id in self.blanket_impls.borrow().iter() {
             f(impl_def_id);
@@ -2966,7 +3141,7 @@ impl ClosureKind {
 }
 
 pub trait ClosureTyper<'tcx> {
-    fn tcx(&self) -> &ty::ctxt<'tcx> {
+    fn tcx(&self) -> &ctxt<'tcx> {
         self.param_env().tcx
     }
 
@@ -2999,215 +3174,27 @@ impl<'tcx> CommonTypes<'tcx> {
            interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>)
            -> CommonTypes<'tcx>
     {
+        let mut mk = |sty| ctxt::intern_ty(arena, interner, sty);
         CommonTypes {
-            bool: intern_ty(arena, interner, TyBool),
-            char: intern_ty(arena, interner, TyChar),
-            err: intern_ty(arena, interner, TyError),
-            isize: intern_ty(arena, interner, TyInt(ast::TyIs)),
-            i8: intern_ty(arena, interner, TyInt(ast::TyI8)),
-            i16: intern_ty(arena, interner, TyInt(ast::TyI16)),
-            i32: intern_ty(arena, interner, TyInt(ast::TyI32)),
-            i64: intern_ty(arena, interner, TyInt(ast::TyI64)),
-            usize: intern_ty(arena, interner, TyUint(ast::TyUs)),
-            u8: intern_ty(arena, interner, TyUint(ast::TyU8)),
-            u16: intern_ty(arena, interner, TyUint(ast::TyU16)),
-            u32: intern_ty(arena, interner, TyUint(ast::TyU32)),
-            u64: intern_ty(arena, interner, TyUint(ast::TyU64)),
-            f32: intern_ty(arena, interner, TyFloat(ast::TyF32)),
-            f64: intern_ty(arena, interner, TyFloat(ast::TyF64)),
-        }
-    }
-}
-
-/// Create a type context and call the closure with a `&ty::ctxt` reference
-/// to the context. The closure enforces that the type context and any interned
-/// value (types, substs, etc.) can only be used while `ty::tls` has a valid
-/// reference to the context, to allow formatting values that need it.
-pub fn with_ctxt<'tcx, F, R>(s: Session,
-                             arenas: &'tcx CtxtArenas<'tcx>,
-                             def_map: DefMap,
-                             named_region_map: resolve_lifetime::NamedRegionMap,
-                             map: ast_map::Map<'tcx>,
-                             freevars: RefCell<FreevarMap>,
-                             region_maps: RegionMaps,
-                             lang_items: middle::lang_items::LanguageItems,
-                             stability: stability::Index<'tcx>,
-                             f: F) -> (Session, R)
-                             where F: FnOnce(&ctxt<'tcx>) -> R
-{
-    let mut interner = FnvHashMap();
-    let common_types = CommonTypes::new(&arenas.type_, &mut interner);
-
-    tls::enter(ctxt {
-        arenas: arenas,
-        interner: RefCell::new(interner),
-        substs_interner: RefCell::new(FnvHashMap()),
-        bare_fn_interner: RefCell::new(FnvHashMap()),
-        region_interner: RefCell::new(FnvHashMap()),
-        stability_interner: RefCell::new(FnvHashMap()),
-        types: common_types,
-        named_region_map: named_region_map,
-        region_maps: region_maps,
-        free_region_maps: RefCell::new(FnvHashMap()),
-        item_variance_map: RefCell::new(DefIdMap()),
-        variance_computed: Cell::new(false),
-        sess: s,
-        def_map: def_map,
-        node_types: RefCell::new(FnvHashMap()),
-        item_substs: RefCell::new(NodeMap()),
-        impl_trait_refs: RefCell::new(DefIdMap()),
-        trait_defs: RefCell::new(DefIdMap()),
-        predicates: RefCell::new(DefIdMap()),
-        super_predicates: RefCell::new(DefIdMap()),
-        fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
-        map: map,
-        freevars: freevars,
-        tcache: RefCell::new(DefIdMap()),
-        rcache: RefCell::new(FnvHashMap()),
-        tc_cache: RefCell::new(FnvHashMap()),
-        ast_ty_to_ty_cache: RefCell::new(NodeMap()),
-        enum_var_cache: RefCell::new(DefIdMap()),
-        impl_or_trait_items: RefCell::new(DefIdMap()),
-        trait_item_def_ids: RefCell::new(DefIdMap()),
-        trait_items_cache: RefCell::new(DefIdMap()),
-        ty_param_defs: RefCell::new(NodeMap()),
-        adjustments: RefCell::new(NodeMap()),
-        normalized_cache: RefCell::new(FnvHashMap()),
-        lang_items: lang_items,
-        provided_method_sources: RefCell::new(DefIdMap()),
-        struct_fields: RefCell::new(DefIdMap()),
-        destructor_for_type: RefCell::new(DefIdMap()),
-        destructors: RefCell::new(DefIdSet()),
-        inherent_impls: RefCell::new(DefIdMap()),
-        impl_items: RefCell::new(DefIdMap()),
-        used_unsafe: RefCell::new(NodeSet()),
-        used_mut_nodes: RefCell::new(NodeSet()),
-        populated_external_types: RefCell::new(DefIdSet()),
-        populated_external_primitive_impls: RefCell::new(DefIdSet()),
-        upvar_capture_map: RefCell::new(FnvHashMap()),
-        extern_const_statics: RefCell::new(DefIdMap()),
-        extern_const_variants: RefCell::new(DefIdMap()),
-        extern_const_fns: RefCell::new(DefIdMap()),
-        method_map: RefCell::new(FnvHashMap()),
-        dependency_formats: RefCell::new(FnvHashMap()),
-        closure_kinds: RefCell::new(DefIdMap()),
-        closure_tys: RefCell::new(DefIdMap()),
-        node_lint_levels: RefCell::new(FnvHashMap()),
-        transmute_restrictions: RefCell::new(Vec::new()),
-        stability: RefCell::new(stability),
-        selection_cache: traits::SelectionCache::new(),
-        repr_hint_cache: RefCell::new(DefIdMap()),
-        const_qualif_map: RefCell::new(NodeMap()),
-        custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
-        cast_kinds: RefCell::new(NodeMap()),
-   }, f)
-}
-
-// Type constructors
-
-impl<'tcx> ctxt<'tcx> {
-    pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> {
-        if let Some(substs) = self.substs_interner.borrow().get(&substs) {
-            return *substs;
+            bool: mk(TyBool),
+            char: mk(TyChar),
+            err: mk(TyError),
+            isize: mk(TyInt(ast::TyIs)),
+            i8: mk(TyInt(ast::TyI8)),
+            i16: mk(TyInt(ast::TyI16)),
+            i32: mk(TyInt(ast::TyI32)),
+            i64: mk(TyInt(ast::TyI64)),
+            usize: mk(TyUint(ast::TyUs)),
+            u8: mk(TyUint(ast::TyU8)),
+            u16: mk(TyUint(ast::TyU16)),
+            u32: mk(TyUint(ast::TyU32)),
+            u64: mk(TyUint(ast::TyU64)),
+            f32: mk(TyFloat(ast::TyF32)),
+            f64: mk(TyFloat(ast::TyF64)),
         }
-
-        let substs = self.arenas.substs.alloc(substs);
-        self.substs_interner.borrow_mut().insert(substs, substs);
-        substs
-    }
-
-    /// Create an unsafe fn ty based on a safe fn ty.
-    pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
-        assert_eq!(bare_fn.unsafety, ast::Unsafety::Normal);
-        let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
-            unsafety: ast::Unsafety::Unsafe,
-            abi: bare_fn.abi,
-            sig: bare_fn.sig.clone()
-        });
-        ty::mk_bare_fn(self, None, unsafe_fn_ty_a)
-    }
-
-    pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> {
-        if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) {
-            return *bare_fn;
-        }
-
-        let bare_fn = self.arenas.bare_fn.alloc(bare_fn);
-        self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn);
-        bare_fn
-    }
-
-    pub fn mk_region(&self, region: Region) -> &'tcx Region {
-        if let Some(region) = self.region_interner.borrow().get(&region) {
-            return *region;
-        }
-
-        let region = self.arenas.region.alloc(region);
-        self.region_interner.borrow_mut().insert(region, region);
-        region
-    }
-
-    pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind {
-        *self.closure_kinds.borrow().get(&def_id).unwrap()
-    }
-
-    pub fn closure_type(&self,
-                        def_id: ast::DefId,
-                        substs: &subst::Substs<'tcx>)
-                        -> ty::ClosureTy<'tcx>
-    {
-        self.closure_tys.borrow().get(&def_id).unwrap().subst(self, substs)
-    }
-
-    pub fn type_parameter_def(&self,
-                              node_id: ast::NodeId)
-                              -> TypeParameterDef<'tcx>
-    {
-        self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
-    }
-
-    pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> Option<ast::Mutability> {
-        pat_util::pat_contains_ref_binding(&self.def_map, pat)
-    }
-
-    pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> Option<ast::Mutability> {
-        pat_util::arm_contains_ref_binding(&self.def_map, arm)
     }
 }
 
-// Interns a type/name combination, stores the resulting box in cx.interner,
-// and returns the box as cast to an unsafe ptr (see comments for Ty above).
-pub fn mk_t<'tcx>(cx: &ctxt<'tcx>, st: TypeVariants<'tcx>) -> Ty<'tcx> {
-    let mut interner = cx.interner.borrow_mut();
-    intern_ty(&cx.arenas.type_, &mut *interner, st)
-}
-
-fn intern_ty<'tcx>(type_arena: &'tcx TypedArena<TyS<'tcx>>,
-                   interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>,
-                   st: TypeVariants<'tcx>)
-                   -> Ty<'tcx>
-{
-    match interner.get(&st) {
-        Some(ty) => return *ty,
-        _ => ()
-    }
-
-    let flags = FlagComputation::for_sty(&st);
-
-    let ty = match () {
-        () => type_arena.alloc(TyS { sty: st,
-                                     flags: Cell::new(flags.flags),
-                                     region_depth: flags.depth, }),
-    };
-
-    debug!("Interned type: {:?} Pointer: {:?}",
-           ty, ty as *const TyS);
-
-    interner.insert(InternedTy { ty: ty }, ty);
-
-    ty
-}
-
 struct FlagComputation {
     flags: TypeFlags,
 
@@ -3399,201 +3386,381 @@ impl FlagComputation {
     }
 }
 
-pub fn mk_mach_int<'tcx>(tcx: &ctxt<'tcx>, tm: ast::IntTy) -> Ty<'tcx> {
-    match tm {
-        ast::TyIs   => tcx.types.isize,
-        ast::TyI8   => tcx.types.i8,
-        ast::TyI16  => tcx.types.i16,
-        ast::TyI32  => tcx.types.i32,
-        ast::TyI64  => tcx.types.i64,
+impl<'tcx> ctxt<'tcx> {
+    /// Create a type context and call the closure with a `&ty::ctxt` reference
+    /// to the context. The closure enforces that the type context and any interned
+    /// value (types, substs, etc.) can only be used while `ty::tls` has a valid
+    /// reference to the context, to allow formatting values that need it.
+    pub fn create_and_enter<F, R>(s: Session,
+                                 arenas: &'tcx CtxtArenas<'tcx>,
+                                 def_map: DefMap,
+                                 named_region_map: resolve_lifetime::NamedRegionMap,
+                                 map: ast_map::Map<'tcx>,
+                                 freevars: RefCell<FreevarMap>,
+                                 region_maps: RegionMaps,
+                                 lang_items: middle::lang_items::LanguageItems,
+                                 stability: stability::Index<'tcx>,
+                                 f: F) -> (Session, R)
+                                 where F: FnOnce(&ctxt<'tcx>) -> R
+    {
+        let mut interner = FnvHashMap();
+        let common_types = CommonTypes::new(&arenas.type_, &mut interner);
+
+        tls::enter(ctxt {
+            arenas: arenas,
+            interner: RefCell::new(interner),
+            substs_interner: RefCell::new(FnvHashMap()),
+            bare_fn_interner: RefCell::new(FnvHashMap()),
+            region_interner: RefCell::new(FnvHashMap()),
+            stability_interner: RefCell::new(FnvHashMap()),
+            types: common_types,
+            named_region_map: named_region_map,
+            region_maps: region_maps,
+            free_region_maps: RefCell::new(FnvHashMap()),
+            item_variance_map: RefCell::new(DefIdMap()),
+            variance_computed: Cell::new(false),
+            sess: s,
+            def_map: def_map,
+            node_types: RefCell::new(FnvHashMap()),
+            item_substs: RefCell::new(NodeMap()),
+            impl_trait_refs: RefCell::new(DefIdMap()),
+            trait_defs: RefCell::new(DefIdMap()),
+            predicates: RefCell::new(DefIdMap()),
+            super_predicates: RefCell::new(DefIdMap()),
+            fulfilled_predicates: RefCell::new(traits::FulfilledPredicates::new()),
+            map: map,
+            freevars: freevars,
+            tcache: RefCell::new(DefIdMap()),
+            rcache: RefCell::new(FnvHashMap()),
+            tc_cache: RefCell::new(FnvHashMap()),
+            ast_ty_to_ty_cache: RefCell::new(NodeMap()),
+            enum_var_cache: RefCell::new(DefIdMap()),
+            impl_or_trait_items: RefCell::new(DefIdMap()),
+            trait_item_def_ids: RefCell::new(DefIdMap()),
+            trait_items_cache: RefCell::new(DefIdMap()),
+            ty_param_defs: RefCell::new(NodeMap()),
+            adjustments: RefCell::new(NodeMap()),
+            normalized_cache: RefCell::new(FnvHashMap()),
+            lang_items: lang_items,
+            provided_method_sources: RefCell::new(DefIdMap()),
+            struct_fields: RefCell::new(DefIdMap()),
+            destructor_for_type: RefCell::new(DefIdMap()),
+            destructors: RefCell::new(DefIdSet()),
+            inherent_impls: RefCell::new(DefIdMap()),
+            impl_items: RefCell::new(DefIdMap()),
+            used_unsafe: RefCell::new(NodeSet()),
+            used_mut_nodes: RefCell::new(NodeSet()),
+            populated_external_types: RefCell::new(DefIdSet()),
+            populated_external_primitive_impls: RefCell::new(DefIdSet()),
+            upvar_capture_map: RefCell::new(FnvHashMap()),
+            extern_const_statics: RefCell::new(DefIdMap()),
+            extern_const_variants: RefCell::new(DefIdMap()),
+            extern_const_fns: RefCell::new(DefIdMap()),
+            method_map: RefCell::new(FnvHashMap()),
+            dependency_formats: RefCell::new(FnvHashMap()),
+            closure_kinds: RefCell::new(DefIdMap()),
+            closure_tys: RefCell::new(DefIdMap()),
+            node_lint_levels: RefCell::new(FnvHashMap()),
+            transmute_restrictions: RefCell::new(Vec::new()),
+            stability: RefCell::new(stability),
+            selection_cache: traits::SelectionCache::new(),
+            repr_hint_cache: RefCell::new(DefIdMap()),
+            const_qualif_map: RefCell::new(NodeMap()),
+            custom_coerce_unsized_kinds: RefCell::new(DefIdMap()),
+            cast_kinds: RefCell::new(NodeMap()),
+       }, f)
     }
-}
 
-pub fn mk_mach_uint<'tcx>(tcx: &ctxt<'tcx>, tm: ast::UintTy) -> Ty<'tcx> {
-    match tm {
-        ast::TyUs   => tcx.types.usize,
-        ast::TyU8   => tcx.types.u8,
-        ast::TyU16  => tcx.types.u16,
-        ast::TyU32  => tcx.types.u32,
-        ast::TyU64  => tcx.types.u64,
+    // Type constructors
+
+    pub fn mk_substs(&self, substs: Substs<'tcx>) -> &'tcx Substs<'tcx> {
+        if let Some(substs) = self.substs_interner.borrow().get(&substs) {
+            return *substs;
+        }
+
+        let substs = self.arenas.substs.alloc(substs);
+        self.substs_interner.borrow_mut().insert(substs, substs);
+        substs
     }
-}
 
-pub fn mk_mach_float<'tcx>(tcx: &ctxt<'tcx>, tm: ast::FloatTy) -> Ty<'tcx> {
-    match tm {
-        ast::TyF32  => tcx.types.f32,
-        ast::TyF64  => tcx.types.f64,
+    /// Create an unsafe fn ty based on a safe fn ty.
+    pub fn safe_to_unsafe_fn_ty(&self, bare_fn: &BareFnTy<'tcx>) -> Ty<'tcx> {
+        assert_eq!(bare_fn.unsafety, ast::Unsafety::Normal);
+        let unsafe_fn_ty_a = self.mk_bare_fn(ty::BareFnTy {
+            unsafety: ast::Unsafety::Unsafe,
+            abi: bare_fn.abi,
+            sig: bare_fn.sig.clone()
+        });
+        self.mk_fn(None, unsafe_fn_ty_a)
     }
-}
 
-pub fn mk_str<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, TyStr)
-}
+    pub fn mk_bare_fn(&self, bare_fn: BareFnTy<'tcx>) -> &'tcx BareFnTy<'tcx> {
+        if let Some(bare_fn) = self.bare_fn_interner.borrow().get(&bare_fn) {
+            return *bare_fn;
+        }
 
-pub fn mk_str_slice<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, m: ast::Mutability) -> Ty<'tcx> {
-    mk_rptr(cx, r,
-            mt {
-                ty: mk_t(cx, TyStr),
-                mutbl: m
-            })
-}
+        let bare_fn = self.arenas.bare_fn.alloc(bare_fn);
+        self.bare_fn_interner.borrow_mut().insert(bare_fn, bare_fn);
+        bare_fn
+    }
 
-pub fn mk_enum<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
-    // take a copy of substs so that we own the vectors inside
-    mk_t(cx, TyEnum(did, substs))
-}
+    pub fn mk_region(&self, region: Region) -> &'tcx Region {
+        if let Some(region) = self.region_interner.borrow().get(&region) {
+            return *region;
+        }
 
-pub fn mk_uniq<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> { mk_t(cx, TyBox(ty)) }
+        let region = self.arenas.region.alloc(region);
+        self.region_interner.borrow_mut().insert(region, region);
+        region
+    }
 
-pub fn mk_ptr<'tcx>(cx: &ctxt<'tcx>, tm: mt<'tcx>) -> Ty<'tcx> { mk_t(cx, TyRawPtr(tm)) }
+    pub fn closure_kind(&self, def_id: ast::DefId) -> ty::ClosureKind {
+        *self.closure_kinds.borrow().get(&def_id).unwrap()
+    }
 
-pub fn mk_rptr<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, TyRef(r, tm))
-}
+    pub fn closure_type(&self,
+                        def_id: ast::DefId,
+                        substs: &subst::Substs<'tcx>)
+                        -> ty::ClosureTy<'tcx>
+    {
+        self.closure_tys.borrow().get(&def_id).unwrap().subst(self, substs)
+    }
 
-pub fn mk_mut_rptr<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
-    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutMutable})
-}
-pub fn mk_imm_rptr<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
-    mk_rptr(cx, r, mt {ty: ty, mutbl: ast::MutImmutable})
-}
+    pub fn type_parameter_def(&self,
+                              node_id: ast::NodeId)
+                              -> TypeParameterDef<'tcx>
+    {
+        self.ty_param_defs.borrow().get(&node_id).unwrap().clone()
+    }
 
-pub fn mk_mut_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    mk_ptr(cx, mt {ty: ty, mutbl: ast::MutMutable})
-}
+    pub fn pat_contains_ref_binding(&self, pat: &ast::Pat) -> Option<ast::Mutability> {
+        pat_util::pat_contains_ref_binding(&self.def_map, pat)
+    }
 
-pub fn mk_imm_ptr<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    mk_ptr(cx, mt {ty: ty, mutbl: ast::MutImmutable})
-}
+    pub fn arm_contains_ref_binding(&self, arm: &ast::Arm) -> Option<ast::Mutability> {
+        pat_util::arm_contains_ref_binding(&self.def_map, arm)
+    }
 
-pub fn mk_nil_ptr<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
-    mk_ptr(cx, mt {ty: mk_nil(cx), mutbl: ast::MutImmutable})
-}
+    fn intern_ty(type_arena: &'tcx TypedArena<TyS<'tcx>>,
+                 interner: &mut FnvHashMap<InternedTy<'tcx>, Ty<'tcx>>,
+                 st: TypeVariants<'tcx>)
+                 -> Ty<'tcx> {
+        match interner.get(&st) {
+            Some(ty) => return *ty,
+            _ => ()
+        }
+
+        let flags = FlagComputation::for_sty(&st);
+
+        let ty = match () {
+            () => type_arena.alloc(TyS { sty: st,
+                                        flags: Cell::new(flags.flags),
+                                        region_depth: flags.depth, }),
+        };
 
-pub fn mk_vec<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>, sz: Option<usize>) -> Ty<'tcx> {
-    match sz {
-        Some(n) => mk_t(cx, TyArray(ty, n)),
-        None => mk_t(cx, TySlice(ty))
+        debug!("Interned type: {:?} Pointer: {:?}",
+            ty, ty as *const TyS);
+
+        interner.insert(InternedTy { ty: ty }, ty);
+
+        ty
     }
-}
 
-pub fn mk_slice<'tcx>(cx: &ctxt<'tcx>, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx> {
-    mk_rptr(cx, r,
-            mt {
-                ty: mk_vec(cx, tm.ty, None),
-                mutbl: tm.mutbl
-            })
-}
+    // Interns a type/name combination, stores the resulting box in cx.interner,
+    // and returns the box as cast to an unsafe ptr (see comments for Ty above).
+    pub fn mk_ty(&self, st: TypeVariants<'tcx>) -> Ty<'tcx> {
+        let mut interner = self.interner.borrow_mut();
+        ctxt::intern_ty(&self.arenas.type_, &mut *interner, st)
+    }
 
-pub fn mk_tup<'tcx>(cx: &ctxt<'tcx>, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
-    mk_t(cx, TyTuple(ts))
-}
+    pub fn mk_mach_int(&self, tm: ast::IntTy) -> Ty<'tcx> {
+        match tm {
+            ast::TyIs   => self.types.isize,
+            ast::TyI8   => self.types.i8,
+            ast::TyI16  => self.types.i16,
+            ast::TyI32  => self.types.i32,
+            ast::TyI64  => self.types.i64,
+        }
+    }
 
-pub fn mk_nil<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
-    mk_tup(cx, Vec::new())
-}
+    pub fn mk_mach_uint(&self, tm: ast::UintTy) -> Ty<'tcx> {
+        match tm {
+            ast::TyUs   => self.types.usize,
+            ast::TyU8   => self.types.u8,
+            ast::TyU16  => self.types.u16,
+            ast::TyU32  => self.types.u32,
+            ast::TyU64  => self.types.u64,
+        }
+    }
 
-pub fn mk_bool<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, TyBool)
-}
+    pub fn mk_mach_float(&self, tm: ast::FloatTy) -> Ty<'tcx> {
+        match tm {
+            ast::TyF32  => self.types.f32,
+            ast::TyF64  => self.types.f64,
+        }
+    }
 
-pub fn mk_bare_fn<'tcx>(cx: &ctxt<'tcx>,
-                        opt_def_id: Option<ast::DefId>,
-                        fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
-    mk_t(cx, TyBareFn(opt_def_id, fty))
-}
+    pub fn mk_str(&self) -> Ty<'tcx> {
+        self.mk_ty(TyStr)
+    }
 
-pub fn mk_ctor_fn<'tcx>(cx: &ctxt<'tcx>,
-                        def_id: ast::DefId,
-                        input_tys: &[Ty<'tcx>],
-                        output: Ty<'tcx>) -> Ty<'tcx> {
-    let input_args = input_tys.iter().cloned().collect();
-    mk_bare_fn(cx,
-               Some(def_id),
-               cx.mk_bare_fn(BareFnTy {
-                   unsafety: ast::Unsafety::Normal,
-                   abi: abi::Rust,
-                   sig: ty::Binder(FnSig {
-                    inputs: input_args,
-                    output: ty::FnConverging(output),
-                    variadic: false
-                   })
-                }))
-}
-
-pub fn mk_trait<'tcx>(cx: &ctxt<'tcx>,
-                      principal: ty::PolyTraitRef<'tcx>,
-                      bounds: ExistentialBounds<'tcx>)
-                      -> Ty<'tcx>
-{
-    assert!(bound_list_is_sorted(&bounds.projection_bounds));
+    pub fn mk_static_str(&self) -> Ty<'tcx> {
+        self.mk_imm_ref(self.mk_region(ty::ReStatic), self.mk_str())
+    }
 
-    let inner = box TraitTy {
-        principal: principal,
-        bounds: bounds
-    };
-    mk_t(cx, TyTrait(inner))
-}
+    pub fn mk_enum(&self, did: ast::DefId, substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        // take a copy of substs so that we own the vectors inside
+        self.mk_ty(TyEnum(did, substs))
+    }
 
-fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
-    bounds.is_empty() ||
-        bounds[1..].iter().enumerate().all(
-            |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
-}
+    pub fn mk_box(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyBox(ty))
+    }
 
-pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) {
-    bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()))
-}
+    pub fn mk_ptr(&self, tm: mt<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyRawPtr(tm))
+    }
 
-pub fn mk_projection<'tcx>(cx: &ctxt<'tcx>,
-                           trait_ref: TraitRef<'tcx>,
-                           item_name: ast::Name)
-                           -> Ty<'tcx> {
-    // take a copy of substs so that we own the vectors inside
-    let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
-    mk_t(cx, TyProjection(inner))
-}
+    pub fn mk_ref(&self, r: &'tcx Region, tm: mt<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyRef(r, tm))
+    }
 
-pub fn mk_struct<'tcx>(cx: &ctxt<'tcx>, struct_id: ast::DefId,
-                       substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
-    // take a copy of substs so that we own the vectors inside
-    mk_t(cx, TyStruct(struct_id, substs))
-}
+    pub fn mk_mut_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ref(r, mt {ty: ty, mutbl: ast::MutMutable})
+    }
 
-pub fn mk_closure<'tcx>(cx: &ctxt<'tcx>, closure_id: ast::DefId, substs: &'tcx Substs<'tcx>)
-                        -> Ty<'tcx> {
-    mk_t(cx, TyClosure(closure_id, substs))
-}
+    pub fn mk_imm_ref(&self, r: &'tcx Region, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ref(r, mt {ty: ty, mutbl: ast::MutImmutable})
+    }
 
-pub fn mk_var<'tcx>(cx: &ctxt<'tcx>, v: TyVid) -> Ty<'tcx> {
-    mk_infer(cx, TyVar(v))
-}
+    pub fn mk_mut_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ptr(mt {ty: ty, mutbl: ast::MutMutable})
+    }
 
-pub fn mk_int_var<'tcx>(cx: &ctxt<'tcx>, v: IntVid) -> Ty<'tcx> {
-    mk_infer(cx, IntVar(v))
-}
+    pub fn mk_imm_ptr(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ptr(mt {ty: ty, mutbl: ast::MutImmutable})
+    }
 
-pub fn mk_float_var<'tcx>(cx: &ctxt<'tcx>, v: FloatVid) -> Ty<'tcx> {
-    mk_infer(cx, FloatVar(v))
-}
+    pub fn mk_nil_ptr(&self) -> Ty<'tcx> {
+        self.mk_imm_ptr(self.mk_nil())
+    }
 
-pub fn mk_infer<'tcx>(cx: &ctxt<'tcx>, it: InferTy) -> Ty<'tcx> {
-    mk_t(cx, TyInfer(it))
-}
+    pub fn mk_array(&self, ty: Ty<'tcx>, n: usize) -> Ty<'tcx> {
+        self.mk_ty(TyArray(ty, n))
+    }
+
+    pub fn mk_slice(&self, ty: Ty<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TySlice(ty))
+    }
+
+    pub fn mk_tup(&self, ts: Vec<Ty<'tcx>>) -> Ty<'tcx> {
+        self.mk_ty(TyTuple(ts))
+    }
+
+    pub fn mk_nil(&self) -> Ty<'tcx> {
+        self.mk_tup(Vec::new())
+    }
+
+    pub fn mk_bool(&self) -> Ty<'tcx> {
+        self.mk_ty(TyBool)
+    }
 
-pub fn mk_param<'tcx>(cx: &ctxt<'tcx>,
-                      space: subst::ParamSpace,
-                      index: u32,
-                      name: ast::Name) -> Ty<'tcx> {
-    mk_t(cx, TyParam(ParamTy { space: space, idx: index, name: name }))
+    pub fn mk_fn(&self,
+                 opt_def_id: Option<ast::DefId>,
+                 fty: &'tcx BareFnTy<'tcx>) -> Ty<'tcx> {
+        self.mk_ty(TyBareFn(opt_def_id, fty))
+    }
+
+    pub fn mk_ctor_fn(&self,
+                      def_id: ast::DefId,
+                      input_tys: &[Ty<'tcx>],
+                      output: Ty<'tcx>) -> Ty<'tcx> {
+        let input_args = input_tys.iter().cloned().collect();
+        self.mk_fn(Some(def_id), self.mk_bare_fn(BareFnTy {
+            unsafety: ast::Unsafety::Normal,
+            abi: abi::Rust,
+            sig: ty::Binder(FnSig {
+                inputs: input_args,
+                output: ty::FnConverging(output),
+                variadic: false
+            })
+        }))
+    }
+
+    pub fn mk_trait(&self,
+                    principal: ty::PolyTraitRef<'tcx>,
+                    bounds: ExistentialBounds<'tcx>)
+                    -> Ty<'tcx>
+    {
+        assert!(bound_list_is_sorted(&bounds.projection_bounds));
+
+        let inner = box TraitTy {
+            principal: principal,
+            bounds: bounds
+        };
+        self.mk_ty(TyTrait(inner))
+    }
+
+    pub fn mk_projection(&self,
+                         trait_ref: TraitRef<'tcx>,
+                         item_name: ast::Name)
+                         -> Ty<'tcx> {
+        // take a copy of substs so that we own the vectors inside
+        let inner = ProjectionTy { trait_ref: trait_ref, item_name: item_name };
+        self.mk_ty(TyProjection(inner))
+    }
+
+    pub fn mk_struct(&self, struct_id: ast::DefId,
+                     substs: &'tcx Substs<'tcx>) -> Ty<'tcx> {
+        // take a copy of substs so that we own the vectors inside
+        self.mk_ty(TyStruct(struct_id, substs))
+    }
+
+    pub fn mk_closure(&self, closure_id: ast::DefId, substs: &'tcx Substs<'tcx>)
+                      -> Ty<'tcx> {
+        self.mk_ty(TyClosure(closure_id, substs))
+    }
+
+    pub fn mk_var(&self, v: TyVid) -> Ty<'tcx> {
+        self.mk_infer(TyVar(v))
+    }
+
+    pub fn mk_int_var(&self, v: IntVid) -> Ty<'tcx> {
+        self.mk_infer(IntVar(v))
+    }
+
+    pub fn mk_float_var(&self, v: FloatVid) -> Ty<'tcx> {
+        self.mk_infer(FloatVar(v))
+    }
+
+    pub fn mk_infer(&self, it: InferTy) -> Ty<'tcx> {
+        self.mk_ty(TyInfer(it))
+    }
+
+    pub fn mk_param(&self,
+                    space: subst::ParamSpace,
+                    index: u32,
+                    name: ast::Name) -> Ty<'tcx> {
+        self.mk_ty(TyParam(ParamTy { space: space, idx: index, name: name }))
+    }
+
+    pub fn mk_self_type(&self) -> Ty<'tcx> {
+        self.mk_param(subst::SelfSpace, 0, special_idents::type_self.name)
+    }
+
+    pub fn mk_param_from_def(&self, def: &TypeParameterDef) -> Ty<'tcx> {
+        self.mk_param(def.space, def.index, def.name)
+    }
 }
 
-pub fn mk_self_type<'tcx>(cx: &ctxt<'tcx>) -> Ty<'tcx> {
-    mk_param(cx, subst::SelfSpace, 0, special_idents::type_self.name)
+fn bound_list_is_sorted(bounds: &[ty::PolyProjectionPredicate]) -> bool {
+    bounds.is_empty() ||
+        bounds[1..].iter().enumerate().all(
+            |(index, bound)| bounds[index].sort_key() <= bound.sort_key())
 }
 
-pub fn mk_param_from_def<'tcx>(cx: &ctxt<'tcx>, def: &TypeParameterDef) -> Ty<'tcx> {
-    mk_param(cx, def.space, def.index, def.name)
+pub fn sort_bounds_list(bounds: &mut [ty::PolyProjectionPredicate]) {
+    bounds.sort_by(|a, b| a.sort_key().cmp(&b.sort_key()))
 }
 
 impl<'tcx> TyS<'tcx> {
@@ -3631,42 +3798,24 @@ impl<'tcx> TyS<'tcx> {
             _ => false,
         }
     }
-}
-
-pub fn walk_ty<'tcx, F>(ty_root: Ty<'tcx>, mut f: F)
-    where F: FnMut(Ty<'tcx>),
-{
-    for ty in ty_root.walk() {
-        f(ty);
-    }
-}
 
-/// Walks `ty` and any types appearing within `ty`, invoking the
-/// callback `f` on each type. If the callback returns false, then the
-/// children of the current type are ignored.
-///
-/// Note: prefer `ty.walk()` where possible.
-pub fn maybe_walk_ty<'tcx,F>(ty_root: Ty<'tcx>, mut f: F)
-    where F : FnMut(Ty<'tcx>) -> bool
-{
-    let mut walker = ty_root.walk();
-    while let Some(ty) = walker.next() {
-        if !f(ty) {
-            walker.skip_current_subtree();
+    /// Walks `ty` and any types appearing within `ty`, invoking the
+    /// callback `f` on each type. If the callback returns false, then the
+    /// children of the current type are ignored.
+    ///
+    /// Note: prefer `ty.walk()` where possible.
+    pub fn maybe_walk<F>(&'tcx self, mut f: F)
+        where F : FnMut(Ty<'tcx>) -> bool
+    {
+        let mut walker = self.walk();
+        while let Some(ty) = walker.next() {
+            if !f(ty) {
+                walker.skip_current_subtree();
+            }
         }
     }
 }
 
-// Folds types from the bottom up.
-pub fn fold_ty<'tcx, F>(cx: &ctxt<'tcx>, t0: Ty<'tcx>,
-                        fldop: F)
-                        -> Ty<'tcx> where
-    F: FnMut(Ty<'tcx>) -> Ty<'tcx>,
-{
-    let mut f = ty_fold::BottomUpFolder {tcx: cx, fldop: fldop};
-    f.fold_ty(t0)
-}
-
 impl ParamTy {
     pub fn new(space: subst::ParamSpace,
                index: u32,
@@ -3683,8 +3832,8 @@ impl ParamTy {
         ParamTy::new(def.space, def.index, def.name)
     }
 
-    pub fn to_ty<'tcx>(self, tcx: &ty::ctxt<'tcx>) -> Ty<'tcx> {
-        ty::mk_param(tcx, self.space, self.idx, self.name)
+    pub fn to_ty<'tcx>(self, tcx: &ctxt<'tcx>) -> Ty<'tcx> {
+        tcx.mk_param(self.space, self.idx, self.name)
     }
 
     pub fn is_self(&self) -> bool {
@@ -3703,140 +3852,142 @@ impl<'tcx> ItemSubsts<'tcx> {
 }
 
 // Type utilities
-
-pub fn type_is_nil(ty: Ty) -> bool {
-    match ty.sty {
-        TyTuple(ref tys) => tys.is_empty(),
-        _ => false
+impl<'tcx> TyS<'tcx> {
+    pub fn is_nil(&self) -> bool {
+        match self.sty {
+            TyTuple(ref tys) => tys.is_empty(),
+            _ => false
+        }
     }
-}
-
-pub fn type_is_error(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::HAS_TY_ERR)
-}
 
-pub fn type_needs_subst(ty: Ty) -> bool {
-    ty.flags.get().intersects(TypeFlags::NEEDS_SUBST)
-}
-
-pub fn trait_ref_contains_error(tref: &ty::TraitRef) -> bool {
-    tref.substs.types.any(|&ty| type_is_error(ty))
-}
+    pub fn is_empty(&self, cx: &ctxt) -> bool {
+        match self.sty {
+            TyEnum(did, _) => cx.enum_variants(did).is_empty(),
+            _ => false
+        }
+    }
 
-pub fn type_is_ty_var(ty: Ty) -> bool {
-    match ty.sty {
-        TyInfer(TyVar(_)) => true,
-        _ => false
+    pub fn is_ty_var(&self) -> bool {
+        match self.sty {
+            TyInfer(TyVar(_)) => true,
+            _ => false
+        }
     }
-}
 
-pub fn type_is_bool(ty: Ty) -> bool { ty.sty == TyBool }
+    pub fn is_bool(&self) -> bool { self.sty == TyBool }
 
-pub fn type_is_self(ty: Ty) -> bool {
-    match ty.sty {
-        TyParam(ref p) => p.space == subst::SelfSpace,
-        _ => false
+    pub fn is_self(&self) -> bool {
+        match self.sty {
+            TyParam(ref p) => p.space == subst::SelfSpace,
+            _ => false
+        }
     }
-}
 
-fn type_is_slice(ty: Ty) -> bool {
-    match ty.sty {
-        TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty {
-            TySlice(_) | TyStr => true,
-            _ => false,
-        },
-        _ => false
+    fn is_slice(&self) -> bool {
+        match self.sty {
+            TyRawPtr(mt) | TyRef(_, mt) => match mt.ty.sty {
+                TySlice(_) | TyStr => true,
+                _ => false,
+            },
+            _ => false
+        }
     }
-}
 
-pub fn type_is_structural(ty: Ty) -> bool {
-    match ty.sty {
-      TyStruct(..) | TyTuple(_) | TyEnum(..) |
-      TyArray(..) | TyClosure(..) => true,
-      _ => type_is_slice(ty) | type_is_trait(ty)
+    pub fn is_structural(&self) -> bool {
+        match self.sty {
+            TyStruct(..) | TyTuple(_) | TyEnum(..) |
+            TyArray(..) | TyClosure(..) => true,
+            _ => self.is_slice() | self.is_trait()
+        }
     }
-}
 
-pub fn type_is_simd(cx: &ctxt, ty: Ty) -> bool {
-    match ty.sty {
-        TyStruct(did, _) => lookup_simd(cx, did),
-        _ => false
+    pub fn is_simd(&self, cx: &ctxt) -> bool {
+        match self.sty {
+            TyStruct(did, _) => cx.lookup_simd(did),
+            _ => false
+        }
     }
-}
 
-pub fn sequence_element_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    match ty.sty {
-        TyArray(ty, _) | TySlice(ty) => ty,
-        TyStr => mk_mach_uint(cx, ast::TyU8),
-        _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
-                                  ty)),
+    pub fn sequence_element_type(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
+        match self.sty {
+            TyArray(ty, _) | TySlice(ty) => ty,
+            TyStr => cx.mk_mach_uint(ast::TyU8),
+            _ => cx.sess.bug(&format!("sequence_element_type called on non-sequence value: {}",
+                                      self)),
+        }
     }
-}
 
-pub fn simd_type<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Ty<'tcx> {
-    match ty.sty {
-        TyStruct(did, substs) => {
-            let fields = lookup_struct_fields(cx, did);
-            lookup_field_type(cx, did, fields[0].id, substs)
+    pub fn simd_type(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
+        match self.sty {
+            TyStruct(did, substs) => {
+                let fields = cx.lookup_struct_fields(did);
+                cx.lookup_field_type(did, fields[0].id, substs)
+            }
+            _ => panic!("simd_type called on invalid type")
         }
-        _ => panic!("simd_type called on invalid type")
     }
-}
 
-pub fn simd_size(cx: &ctxt, ty: Ty) -> usize {
-    match ty.sty {
-        TyStruct(did, _) => {
-            let fields = lookup_struct_fields(cx, did);
-            fields.len()
+    pub fn simd_size(&self, cx: &ctxt) -> usize {
+        match self.sty {
+            TyStruct(did, _) => {
+                cx.lookup_struct_fields(did).len()
+            }
+            _ => panic!("simd_size called on invalid type")
         }
-        _ => panic!("simd_size called on invalid type")
     }
-}
 
-pub fn type_is_region_ptr(ty: Ty) -> bool {
-    match ty.sty {
-        TyRef(..) => true,
-        _ => false
+    pub fn is_region_ptr(&self) -> bool {
+        match self.sty {
+            TyRef(..) => true,
+            _ => false
+        }
     }
-}
 
-pub fn type_is_unsafe_ptr(ty: Ty) -> bool {
-    match ty.sty {
-      TyRawPtr(_) => return true,
-      _ => return false
+    pub fn is_unsafe_ptr(&self) -> bool {
+        match self.sty {
+            TyRawPtr(_) => return true,
+            _ => return false
+        }
     }
-}
 
-pub fn type_is_unique(ty: Ty) -> bool {
-    match ty.sty {
-        TyBox(_) => true,
-        _ => false
+    pub fn is_unique(&self) -> bool {
+        match self.sty {
+            TyBox(_) => true,
+            _ => false
+        }
     }
-}
 
-/*
- A scalar type is one that denotes an atomic datum, with no sub-components.
- (A TyRawPtr is scalar because it represents a non-managed pointer, so its
- contents are abstract to rustc.)
-*/
-pub fn type_is_scalar(ty: Ty) -> bool {
-    match ty.sty {
-      TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
-      TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) |
-      TyBareFn(..) | TyRawPtr(_) => true,
-      _ => false
+    /*
+     A scalar type is one that denotes an atomic datum, with no sub-components.
+     (A TyRawPtr is scalar because it represents a non-managed pointer, so its
+     contents are abstract to rustc.)
+    */
+    pub fn is_scalar(&self) -> bool {
+        match self.sty {
+            TyBool | TyChar | TyInt(_) | TyFloat(_) | TyUint(_) |
+            TyInfer(IntVar(_)) | TyInfer(FloatVar(_)) |
+            TyBareFn(..) | TyRawPtr(_) => true,
+            _ => false
+        }
     }
-}
 
-/// Returns true if this type is a floating point type and false otherwise.
-pub fn type_is_floating_point(ty: Ty) -> bool {
-    match ty.sty {
-        TyFloat(_) |
-        TyInfer(FloatVar(_)) =>
-            true,
+    /// Returns true if this type is a floating point type and false otherwise.
+    pub fn is_floating_point(&self) -> bool {
+        match self.sty {
+            TyFloat(_) |
+            TyInfer(FloatVar(_)) => true,
+            _ => false,
+        }
+    }
 
-        _ =>
-            false,
+    pub fn ty_to_def_id(&self) -> Option<ast::DefId> {
+        match self.sty {
+            TyTrait(ref tt) => Some(tt.principal_def_id()),
+            TyStruct(id, _) |
+            TyEnum(id, _) |
+            TyClosure(id, _) => Some(id),
+            _ => None
+        }
     }
 }
 
@@ -3991,454 +4142,425 @@ impl fmt::Debug for TypeContents {
     }
 }
 
-pub fn type_contents<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> TypeContents {
-    return memoized(&cx.tc_cache, ty, |ty| {
-        tc_ty(cx, ty, &mut FnvHashMap())
-    });
+impl<'tcx> TyS<'tcx> {
+    pub fn type_contents(&'tcx self, cx: &ctxt<'tcx>) -> TypeContents {
+        return memoized(&cx.tc_cache, self, |ty| {
+            tc_ty(cx, ty, &mut FnvHashMap())
+        });
 
-    fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
-                   ty: Ty<'tcx>,
-                   cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
-    {
-        // Subtle: Note that we are *not* using cx.tc_cache here but rather a
-        // private cache for this walk.  This is needed in the case of cyclic
-        // types like:
-        //
-        //     struct List { next: Box<Option<List>>, ... }
-        //
-        // When computing the type contents of such a type, we wind up deeply
-        // recursing as we go.  So when we encounter the recursive reference
-        // to List, we temporarily use TC::None as its contents.  Later we'll
-        // patch up the cache with the correct value, once we've computed it
-        // (this is basically a co-inductive process, if that helps).  So in
-        // the end we'll compute TC::OwnsOwned, in this case.
-        //
-        // The problem is, as we are doing the computation, we will also
-        // compute an *intermediate* contents for, e.g., Option<List> of
-        // TC::None.  This is ok during the computation of List itself, but if
-        // we stored this intermediate value into cx.tc_cache, then later
-        // requests for the contents of Option<List> would also yield TC::None
-        // which is incorrect.  This value was computed based on the crutch
-        // value for the type contents of list.  The correct value is
-        // TC::OwnsOwned.  This manifested as issue #4821.
-        match cache.get(&ty) {
-            Some(tc) => { return *tc; }
-            None => {}
-        }
-        match cx.tc_cache.borrow().get(&ty) {    // Must check both caches!
-            Some(tc) => { return *tc; }
-            None => {}
-        }
-        cache.insert(ty, TC::None);
-
-        let result = match ty.sty {
-            // usize and isize are ffi-unsafe
-            TyUint(ast::TyUs) | TyInt(ast::TyIs) => {
-                TC::ReachesFfiUnsafe
-            }
-
-            // Scalar and unique types are sendable, and durable
-            TyInfer(ty::FreshIntTy(_)) | TyInfer(ty::FreshFloatTy(_)) |
-            TyBool | TyInt(_) | TyUint(_) | TyFloat(_) |
-            TyBareFn(..) | ty::TyChar => {
-                TC::None
-            }
-
-            TyBox(typ) => {
-                TC::ReachesFfiUnsafe | match typ.sty {
-                    TyStr => TC::OwnsOwned,
-                    _ => tc_ty(cx, typ, cache).owned_pointer(),
+        fn tc_ty<'tcx>(cx: &ctxt<'tcx>,
+                       ty: Ty<'tcx>,
+                       cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
+        {
+            // Subtle: Note that we are *not* using cx.tc_cache here but rather a
+            // private cache for this walk.  This is needed in the case of cyclic
+            // types like:
+            //
+            //     struct List { next: Box<Option<List>>, ... }
+            //
+            // When computing the type contents of such a type, we wind up deeply
+            // recursing as we go.  So when we encounter the recursive reference
+            // to List, we temporarily use TC::None as its contents.  Later we'll
+            // patch up the cache with the correct value, once we've computed it
+            // (this is basically a co-inductive process, if that helps).  So in
+            // the end we'll compute TC::OwnsOwned, in this case.
+            //
+            // The problem is, as we are doing the computation, we will also
+            // compute an *intermediate* contents for, e.g., Option<List> of
+            // TC::None.  This is ok during the computation of List itself, but if
+            // we stored this intermediate value into cx.tc_cache, then later
+            // requests for the contents of Option<List> would also yield TC::None
+            // which is incorrect.  This value was computed based on the crutch
+            // value for the type contents of list.  The correct value is
+            // TC::OwnsOwned.  This manifested as issue #4821.
+            match cache.get(&ty) {
+                Some(tc) => { return *tc; }
+                None => {}
+            }
+            match cx.tc_cache.borrow().get(&ty) {    // Must check both caches!
+                Some(tc) => { return *tc; }
+                None => {}
+            }
+            cache.insert(ty, TC::None);
+
+            let result = match ty.sty {
+                // usize and isize are ffi-unsafe
+                TyUint(ast::TyUs) | TyInt(ast::TyIs) => {
+                    TC::ReachesFfiUnsafe
                 }
-            }
 
-            TyTrait(box TraitTy { ref bounds, .. }) => {
-                object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
-            }
-
-            TyRawPtr(ref mt) => {
-                tc_ty(cx, mt.ty, cache).unsafe_pointer()
-            }
+                // Scalar and unique types are sendable, and durable
+                TyInfer(ty::FreshIntTy(_)) | TyInfer(ty::FreshFloatTy(_)) |
+                TyBool | TyInt(_) | TyUint(_) | TyFloat(_) |
+                TyBareFn(..) | ty::TyChar => {
+                    TC::None
+                }
 
-            TyRef(r, ref mt) => {
-                TC::ReachesFfiUnsafe | match mt.ty.sty {
-                    TyStr => borrowed_contents(*r, ast::MutImmutable),
-                    TyArray(..) |
-                    TySlice(_) => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r,
-                                                                                      mt.mutbl)),
-                    _ => tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r, mt.mutbl)),
+                TyBox(typ) => {
+                    TC::ReachesFfiUnsafe | tc_ty(cx, typ, cache).owned_pointer()
                 }
-            }
 
-            TyArray(ty, _) => {
-                tc_ty(cx, ty, cache)
-            }
+                TyTrait(box TraitTy { ref bounds, .. }) => {
+                    object_contents(bounds) | TC::ReachesFfiUnsafe | TC::Nonsized
+                }
 
-            TySlice(ty) => {
-                tc_ty(cx, ty, cache) | TC::Nonsized
-            }
-            TyStr => TC::Nonsized,
+                TyRawPtr(ref mt) => {
+                    tc_ty(cx, mt.ty, cache).unsafe_pointer()
+                }
 
-            TyStruct(did, substs) => {
-                let flds = struct_fields(cx, did, substs);
-                let mut res =
-                    TypeContents::union(&flds[..],
-                                        |f| tc_mt(cx, f.mt, cache));
+                TyRef(r, ref mt) => {
+                    tc_ty(cx, mt.ty, cache).reference(borrowed_contents(*r, mt.mutbl)) |
+                        TC::ReachesFfiUnsafe
+                }
 
-                if !lookup_repr_hints(cx, did).contains(&attr::ReprExtern) {
-                    res = res | TC::ReachesFfiUnsafe;
+                TyArray(ty, _) => {
+                    tc_ty(cx, ty, cache)
                 }
 
-                if ty::has_dtor(cx, did) {
-                    res = res | TC::OwnsDtor;
+                TySlice(ty) => {
+                    tc_ty(cx, ty, cache) | TC::Nonsized
                 }
-                apply_lang_items(cx, did, res)
-            }
+                TyStr => TC::Nonsized,
 
-            TyClosure(did, substs) => {
-                // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure.
-                let param_env = ty::empty_parameter_environment(cx);
-                let upvars = closure_upvars(&param_env, did, substs).unwrap();
-                TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache))
-            }
+                TyStruct(did, substs) => {
+                    let flds = cx.struct_fields(did, substs);
+                    let mut res =
+                        TypeContents::union(&flds[..],
+                                            |f| tc_mt(cx, f.mt, cache));
 
-            TyTuple(ref tys) => {
-                TypeContents::union(&tys[..],
-                                    |ty| tc_ty(cx, *ty, cache))
-            }
+                    if !cx.lookup_repr_hints(did).contains(&attr::ReprExtern) {
+                        res = res | TC::ReachesFfiUnsafe;
+                    }
 
-            TyEnum(did, substs) => {
-                let variants = substd_enum_variants(cx, did, substs);
-                let mut res =
-                    TypeContents::union(&variants[..], |variant| {
-                        TypeContents::union(&variant.args,
-                                            |arg_ty| {
-                            tc_ty(cx, *arg_ty, cache)
-                        })
-                    });
+                    if cx.has_dtor(did) {
+                        res = res | TC::OwnsDtor;
+                    }
+                    apply_lang_items(cx, did, res)
+                }
 
-                if ty::has_dtor(cx, did) {
-                    res = res | TC::OwnsDtor;
+                TyClosure(did, substs) => {
+                    // FIXME(#14449): `borrowed_contents` below assumes `&mut` closure.
+                    let param_env = cx.empty_parameter_environment();
+                    let upvars = param_env.closure_upvars(did, substs).unwrap();
+                    TypeContents::union(&upvars, |f| tc_ty(cx, &f.ty, cache))
                 }
 
-                if !variants.is_empty() {
-                    let repr_hints = lookup_repr_hints(cx, did);
-                    if repr_hints.len() > 1 {
-                        // this is an error later on, but this type isn't safe
-                        res = res | TC::ReachesFfiUnsafe;
+                TyTuple(ref tys) => {
+                    TypeContents::union(&tys[..],
+                                        |ty| tc_ty(cx, *ty, cache))
+                }
+
+                TyEnum(did, substs) => {
+                    let variants = cx.substd_enum_variants(did, substs);
+                    let mut res =
+                        TypeContents::union(&variants[..], |variant| {
+                            TypeContents::union(&variant.args,
+                                                |arg_ty| {
+                                tc_ty(cx, *arg_ty, cache)
+                            })
+                        });
+
+                    if cx.has_dtor(did) {
+                        res = res | TC::OwnsDtor;
                     }
 
-                    match repr_hints.get(0) {
-                        Some(h) => if !h.is_ffi_safe() {
-                            res = res | TC::ReachesFfiUnsafe;
-                        },
-                        // ReprAny
-                        None => {
+                    if !variants.is_empty() {
+                        let repr_hints = cx.lookup_repr_hints(did);
+                        if repr_hints.len() > 1 {
+                            // this is an error later on, but this type isn't safe
                             res = res | TC::ReachesFfiUnsafe;
+                        }
 
-                            // We allow ReprAny enums if they are eligible for
-                            // the nullable pointer optimization and the
-                            // contained type is an `extern fn`
+                        match repr_hints.get(0) {
+                            Some(h) => if !h.is_ffi_safe() {
+                                res = res | TC::ReachesFfiUnsafe;
+                            },
+                            // ReprAny
+                            None => {
+                                res = res | TC::ReachesFfiUnsafe;
 
-                            if variants.len() == 2 {
-                                let mut data_idx = 0;
+                                // We allow ReprAny enums if they are eligible for
+                                // the nullable pointer optimization and the
+                                // contained type is an `extern fn`
 
-                                if variants[0].args.is_empty() {
-                                    data_idx = 1;
-                                }
+                                if variants.len() == 2 {
+                                    let mut data_idx = 0;
+
+                                    if variants[0].args.is_empty() {
+                                        data_idx = 1;
+                                    }
 
-                                if variants[data_idx].args.len() == 1 {
-                                    match variants[data_idx].args[0].sty {
-                                        TyBareFn(..) => { res = res - TC::ReachesFfiUnsafe; }
-                                        _ => { }
+                                    if variants[data_idx].args.len() == 1 {
+                                        match variants[data_idx].args[0].sty {
+                                            TyBareFn(..) => { res = res - TC::ReachesFfiUnsafe; }
+                                            _ => { }
+                                        }
                                     }
                                 }
                             }
                         }
                     }
+
+
+                    apply_lang_items(cx, did, res)
                 }
 
+                TyProjection(..) |
+                TyParam(_) => {
+                    TC::All
+                }
 
-                apply_lang_items(cx, did, res)
-            }
+                TyInfer(_) |
+                TyError => {
+                    cx.sess.bug("asked to compute contents of error type");
+                }
+            };
 
-            TyProjection(..) |
-            TyParam(_) => {
-                TC::All
-            }
+            cache.insert(ty, result);
+            result
+        }
+
+        fn tc_mt<'tcx>(cx: &ctxt<'tcx>,
+                       mt: mt<'tcx>,
+                       cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
+        {
+            let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable);
+            mc | tc_ty(cx, mt.ty, cache)
+        }
 
-            TyInfer(_) |
-            TyError => {
-                cx.sess.bug("asked to compute contents of error type");
+        fn apply_lang_items(cx: &ctxt, did: ast::DefId, tc: TypeContents)
+                            -> TypeContents {
+            if Some(did) == cx.lang_items.unsafe_cell_type() {
+                tc | TC::InteriorUnsafe
+            } else {
+                tc
             }
-        };
+        }
 
-        cache.insert(ty, result);
-        result
+        /// Type contents due to containing a reference with
+        /// the region `region` and borrow kind `bk`.
+        fn borrowed_contents(region: ty::Region,
+                             mutbl: ast::Mutability)
+                             -> TypeContents {
+            let b = match mutbl {
+                ast::MutMutable => TC::ReachesMutable,
+                ast::MutImmutable => TC::None,
+            };
+            b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
+        }
+
+        fn object_contents(bounds: &ExistentialBounds) -> TypeContents {
+            // These are the type contents of the (opaque) interior. We
+            // make no assumptions (other than that it cannot have an
+            // in-scope type parameter within, which makes no sense).
+            let mut tc = TC::All - TC::InteriorParam;
+            for bound in &bounds.builtin_bounds {
+                tc = tc - match bound {
+                    BoundSync | BoundSend | BoundCopy => TC::None,
+                    BoundSized => TC::Nonsized,
+                };
+            }
+            return tc;
+        }
     }
 
-    fn tc_mt<'tcx>(cx: &ctxt<'tcx>,
-                   mt: mt<'tcx>,
-                   cache: &mut FnvHashMap<Ty<'tcx>, TypeContents>) -> TypeContents
+    fn impls_bound<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+                       bound: ty::BuiltinBound,
+                       span: Span)
+                       -> bool
     {
-        let mc = TC::ReachesMutable.when(mt.mutbl == MutMutable);
-        mc | tc_ty(cx, mt.ty, cache)
-    }
+        let infcx = infer::new_infer_ctxt(param_env.tcx());
 
-    fn apply_lang_items(cx: &ctxt, did: ast::DefId, tc: TypeContents)
-                        -> TypeContents {
-        if Some(did) == cx.lang_items.unsafe_cell_type() {
-            tc | TC::InteriorUnsafe
-        } else {
-            tc
-        }
-    }
+        let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env,
+                                                                self, bound, span);
 
-    /// Type contents due to containing a reference with the region `region` and borrow kind `bk`
-    fn borrowed_contents(region: ty::Region,
-                         mutbl: ast::Mutability)
-                         -> TypeContents {
-        let b = match mutbl {
-            ast::MutMutable => TC::ReachesMutable,
-            ast::MutImmutable => TC::None,
-        };
-        b | (TC::ReachesBorrowed).when(region != ty::ReStatic)
-    }
-
-    fn object_contents(bounds: &ExistentialBounds) -> TypeContents {
-        // These are the type contents of the (opaque) interior. We
-        // make no assumptions (other than that it cannot have an
-        // in-scope type parameter within, which makes no sense).
-        let mut tc = TC::All - TC::InteriorParam;
-        for bound in &bounds.builtin_bounds {
-            tc = tc - match bound {
-                BoundSync | BoundSend | BoundCopy => TC::None,
-                BoundSized => TC::Nonsized,
-            };
-        }
-        return tc;
+        debug!("Ty::impls_bound({:?}, {:?}) = {:?}",
+               self, bound, is_impld);
+
+        is_impld
     }
-}
 
-fn type_impls_bound<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
-                             tcx: &ty::ctxt<'tcx>,
-                             ty: Ty<'tcx>,
-                             bound: ty::BuiltinBound,
-                             span: Span)
-                             -> bool
-{
-    let pe;
-    let param_env = match param_env {
-        Some(e) => e,
-        None => {
-            pe = empty_parameter_environment(tcx);
-            &pe
+    fn moves_by_default<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+                           span: Span) -> bool {
+        if self.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
+            return self.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
         }
-    };
-    let infcx = infer::new_infer_ctxt(tcx);
 
-    let is_impld = traits::type_known_to_meet_builtin_bound(&infcx, param_env, ty, bound, span);
+        assert!(!self.needs_infer());
 
-    debug!("type_impls_bound({:?}, {:?}) = {:?}",
-           ty,
-           bound,
-           is_impld);
+        // Fast-path for primitive types
+        let result = match self.sty {
+            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+            TyRawPtr(..) | TyBareFn(..) | TyRef(_, mt {
+                mutbl: ast::MutImmutable, ..
+            }) => Some(false),
 
-    is_impld
-}
+            TyStr | TyBox(..) | TyRef(_, mt {
+                mutbl: ast::MutMutable, ..
+            }) => Some(true),
 
-pub fn type_moves_by_default<'a,'tcx>(param_env: &ParameterEnvironment<'a,'tcx>,
-                                      span: Span,
-                                      ty: Ty<'tcx>)
-                                      -> bool
-{
-    if ty.flags.get().intersects(TypeFlags::MOVENESS_CACHED) {
-        return ty.flags.get().intersects(TypeFlags::MOVES_BY_DEFAULT);
-    }
-
-    assert!(!ty::type_needs_infer(ty));
-
-    // Fast-path for primitive types
-    let result = match ty.sty {
-        TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-        TyRawPtr(..) | TyBareFn(..) | TyRef(_, mt {
-            mutbl: ast::MutImmutable, ..
-        }) => Some(false),
-
-        TyStr | TyBox(..) | TyRef(_, mt {
-            mutbl: ast::MutMutable, ..
-        }) => Some(true),
-
-        TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
-        TyClosure(..) | TyEnum(..) | TyStruct(..) |
-        TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
-    }.unwrap_or_else(|| !type_impls_bound(Some(param_env),
-                                          param_env.tcx,
-                                          ty,
-                                          ty::BoundCopy,
-                                          span));
-
-    if !type_has_params(ty) && !type_has_self(ty) {
-        ty.flags.set(ty.flags.get() | if result {
-            TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
-        } else {
-            TypeFlags::MOVENESS_CACHED
-        });
+            TyArray(..) | TySlice(_) | TyTrait(..) | TyTuple(..) |
+            TyClosure(..) | TyEnum(..) | TyStruct(..) |
+            TyProjection(..) | TyParam(..) | TyInfer(..) | TyError => None
+        }.unwrap_or_else(|| !self.impls_bound(param_env, ty::BoundCopy, span));
+
+        if !self.has_param_types() && !self.has_self_ty() {
+            self.flags.set(self.flags.get() | if result {
+                TypeFlags::MOVENESS_CACHED | TypeFlags::MOVES_BY_DEFAULT
+            } else {
+                TypeFlags::MOVENESS_CACHED
+            });
+        }
+
+        result
     }
 
-    result
-}
+    #[inline]
+    pub fn is_sized<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+                        span: Span) -> bool
+    {
+        if self.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
+            return self.flags.get().intersects(TypeFlags::IS_SIZED);
+        }
 
-#[inline]
-pub fn type_is_sized<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
-                              tcx: &ty::ctxt<'tcx>,
-                              span: Span,
-                              ty: Ty<'tcx>)
-                              -> bool
-{
-    if ty.flags.get().intersects(TypeFlags::SIZEDNESS_CACHED) {
-        let result = ty.flags.get().intersects(TypeFlags::IS_SIZED);
-        return result;
+        self.is_sized_uncached(param_env, span)
     }
 
-    type_is_sized_uncached(param_env, tcx, span, ty)
-}
+    fn is_sized_uncached<'a>(&'tcx self, param_env: &ParameterEnvironment<'a,'tcx>,
+                             span: Span) -> bool {
+        assert!(!self.needs_infer());
 
-fn type_is_sized_uncached<'a,'tcx>(param_env: Option<&ParameterEnvironment<'a,'tcx>>,
-                                   tcx: &ty::ctxt<'tcx>,
-                                   span: Span,
-                                   ty: Ty<'tcx>) -> bool {
-    assert!(!ty::type_needs_infer(ty));
+        // Fast-path for primitive types
+        let result = match self.sty {
+            TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
+            TyBox(..) | TyRawPtr(..) | TyRef(..) | TyBareFn(..) |
+            TyArray(..) | TyTuple(..) | TyClosure(..) => Some(true),
 
-    // Fast-path for primitive types
-    let result = match ty.sty {
-        TyBool | TyChar | TyInt(..) | TyUint(..) | TyFloat(..) |
-        TyBox(..) | TyRawPtr(..) | TyRef(..) | TyBareFn(..) |
-        TyArray(..) | TyTuple(..) | TyClosure(..) => Some(true),
+            TyStr | TyTrait(..) | TySlice(_) => Some(false),
 
-        TyStr | TyTrait(..) | TySlice(_) => Some(false),
+            TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
+            TyInfer(..) | TyError => None
+        }.unwrap_or_else(|| self.impls_bound(param_env, ty::BoundSized, span));
 
-        TyEnum(..) | TyStruct(..) | TyProjection(..) | TyParam(..) |
-        TyInfer(..) | TyError => None
-    }.unwrap_or_else(|| type_impls_bound(param_env, tcx, ty, ty::BoundSized, span));
+        if !self.has_param_types() && !self.has_self_ty() {
+            self.flags.set(self.flags.get() | if result {
+                TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
+            } else {
+                TypeFlags::SIZEDNESS_CACHED
+            });
+        }
 
-    if !type_has_params(ty) && !type_has_self(ty) {
-        ty.flags.set(ty.flags.get() | if result {
-            TypeFlags::SIZEDNESS_CACHED | TypeFlags::IS_SIZED
-        } else {
-            TypeFlags::SIZEDNESS_CACHED
-        });
+        result
     }
 
-    result
-}
+    pub fn is_ffi_safe(&'tcx self, cx: &ctxt<'tcx>) -> bool {
+        !self.type_contents(cx).intersects(TC::ReachesFfiUnsafe)
+    }
 
-pub fn is_ffi_safe<'tcx>(cx: &ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    !type_contents(cx, ty).intersects(TC::ReachesFfiUnsafe)
-}
+    // True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
+    pub fn is_instantiable(&'tcx self, cx: &ctxt<'tcx>) -> bool {
+        fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
+                               r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
+            debug!("type_requires({:?}, {:?})?",
+                   r_ty, ty);
 
-// True if instantiating an instance of `r_ty` requires an instance of `r_ty`.
-pub fn is_instantiable<'tcx>(cx: &ctxt<'tcx>, r_ty: Ty<'tcx>) -> bool {
-    fn type_requires<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
-                           r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
-        debug!("type_requires({:?}, {:?})?",
-               r_ty, ty);
+            let r = r_ty == ty || subtypes_require(cx, seen, r_ty, ty);
 
-        let r = r_ty == ty || subtypes_require(cx, seen, r_ty, ty);
+            debug!("type_requires({:?}, {:?})? {:?}",
+                   r_ty, ty, r);
+            return r;
+        }
 
-        debug!("type_requires({:?}, {:?})? {:?}",
-               r_ty, ty, r);
-        return r;
-    }
+        fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
+                                  r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
+            debug!("subtypes_require({:?}, {:?})?",
+                   r_ty, ty);
 
-    fn subtypes_require<'tcx>(cx: &ctxt<'tcx>, seen: &mut Vec<DefId>,
-                              r_ty: Ty<'tcx>, ty: Ty<'tcx>) -> bool {
-        debug!("subtypes_require({:?}, {:?})?",
-               r_ty, ty);
+            let r = match ty.sty {
+                // fixed length vectors need special treatment compared to
+                // normal vectors, since they don't necessarily have the
+                // possibility to have length zero.
+                TyArray(_, 0) => false, // don't need no contents
+                TyArray(ty, _) => type_requires(cx, seen, r_ty, ty),
 
-        let r = match ty.sty {
-            // fixed length vectors need special treatment compared to
-            // normal vectors, since they don't necessarily have the
-            // possibility to have length zero.
-            TyArray(_, 0) => false, // don't need no contents
-            TyArray(ty, _) => type_requires(cx, seen, r_ty, ty),
+                TyBool |
+                TyChar |
+                TyInt(_) |
+                TyUint(_) |
+                TyFloat(_) |
+                TyStr |
+                TyBareFn(..) |
+                TyParam(_) |
+                TyProjection(_) |
+                TySlice(_) => {
+                    false
+                }
+                TyBox(typ) => {
+                    type_requires(cx, seen, r_ty, typ)
+                }
+                TyRef(_, ref mt) => {
+                    type_requires(cx, seen, r_ty, mt.ty)
+                }
 
-            TyBool |
-            TyChar |
-            TyInt(_) |
-            TyUint(_) |
-            TyFloat(_) |
-            TyStr |
-            TyBareFn(..) |
-            TyParam(_) |
-            TyProjection(_) |
-            TySlice(_) => {
-                false
-            }
-            TyBox(typ) => {
-                type_requires(cx, seen, r_ty, typ)
-            }
-            TyRef(_, ref mt) => {
-                type_requires(cx, seen, r_ty, mt.ty)
-            }
+                TyRawPtr(..) => {
+                    false           // unsafe ptrs can always be NULL
+                }
 
-            TyRawPtr(..) => {
-                false           // unsafe ptrs can always be NULL
-            }
+                TyTrait(..) => {
+                    false
+                }
 
-            TyTrait(..) => {
-                false
-            }
+                TyStruct(ref did, _) if seen.contains(did) => {
+                    false
+                }
 
-            TyStruct(ref did, _) if seen.contains(did) => {
-                false
-            }
+                TyStruct(did, substs) => {
+                    seen.push(did);
+                    let fields = cx.struct_fields(did, substs);
+                    let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
+                    seen.pop().unwrap();
+                    r
+                }
 
-            TyStruct(did, substs) => {
-                seen.push(did);
-                let fields = struct_fields(cx, did, substs);
-                let r = fields.iter().any(|f| type_requires(cx, seen, r_ty, f.mt.ty));
-                seen.pop().unwrap();
-                r
-            }
+                TyError |
+                TyInfer(_) |
+                TyClosure(..) => {
+                    // this check is run on type definitions, so we don't expect to see
+                    // inference by-products or closure types
+                    cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
+                }
 
-            TyError |
-            TyInfer(_) |
-            TyClosure(..) => {
-                // this check is run on type definitions, so we don't expect to see
-                // inference by-products or closure types
-                cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
-            }
+                TyTuple(ref ts) => {
+                    ts.iter().any(|ty| type_requires(cx, seen, r_ty, *ty))
+                }
 
-            TyTuple(ref ts) => {
-                ts.iter().any(|ty| type_requires(cx, seen, r_ty, *ty))
-            }
+                TyEnum(ref did, _) if seen.contains(did) => {
+                    false
+                }
 
-            TyEnum(ref did, _) if seen.contains(did) => {
-                false
-            }
+                TyEnum(did, substs) => {
+                    seen.push(did);
+                    let vs = cx.enum_variants(did);
+                    let r = !vs.is_empty() && vs.iter().all(|variant| {
+                        variant.args.iter().any(|aty| {
+                            let sty = aty.subst(cx, substs);
+                            type_requires(cx, seen, r_ty, sty)
+                        })
+                    });
+                    seen.pop().unwrap();
+                    r
+                }
+            };
 
-            TyEnum(did, substs) => {
-                seen.push(did);
-                let vs = enum_variants(cx, did);
-                let r = !vs.is_empty() && vs.iter().all(|variant| {
-                    variant.args.iter().any(|aty| {
-                        let sty = aty.subst(cx, substs);
-                        type_requires(cx, seen, r_ty, sty)
-                    })
-                });
-                seen.pop().unwrap();
-                r
-            }
-        };
+            debug!("subtypes_require({:?}, {:?})? {:?}",
+                   r_ty, ty, r);
 
-        debug!("subtypes_require({:?}, {:?})? {:?}",
-               r_ty, ty, r);
+            return r;
+        }
 
-        return r;
+        let mut seen = Vec::new();
+        !subtypes_require(cx, &mut seen, self, self)
     }
-
-    let mut seen = Vec::new();
-    !subtypes_require(cx, &mut seen, r_ty, r_ty)
 }
 
 /// Describes whether a type is representable. For types that are not
@@ -4456,781 +4578,448 @@ pub enum Representability {
     SelfRecursive,
 }
 
-/// Check whether a type is representable. This means it cannot contain unboxed
-/// structural recursion. This check is needed for structs and enums.
-pub fn is_type_representable<'tcx>(cx: &ctxt<'tcx>, sp: Span, ty: Ty<'tcx>)
-                                   -> Representability {
-
-    // Iterate until something non-representable is found
-    fn find_nonrepresentable<'tcx, It: Iterator<Item=Ty<'tcx>>>(cx: &ctxt<'tcx>, sp: Span,
-                                                                seen: &mut Vec<Ty<'tcx>>,
-                                                                iter: It)
-                                                                -> Representability {
-        iter.fold(Representable,
-                  |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty)))
-    }
-
-    fn are_inner_types_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
-                                       seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
-                                       -> Representability {
-        match ty.sty {
-            TyTuple(ref ts) => {
-                find_nonrepresentable(cx, sp, seen, ts.iter().cloned())
-            }
-            // Fixed-length vectors.
-            // FIXME(#11924) Behavior undecided for zero-length vectors.
-            TyArray(ty, _) => {
-                is_type_structurally_recursive(cx, sp, seen, ty)
-            }
-            TyStruct(did, substs) => {
-                let fields = struct_fields(cx, did, substs);
-                find_nonrepresentable(cx, sp, seen, fields.iter().map(|f| f.mt.ty))
-            }
-            TyEnum(did, substs) => {
-                let vs = enum_variants(cx, did);
-                let iter = vs.iter()
-                    .flat_map(|variant| &variant.args)
-                    .map(|aty| { aty.subst_spanned(cx, substs, Some(sp)) });
+impl<'tcx> TyS<'tcx> {
+    /// Check whether a type is representable. This means it cannot contain unboxed
+    /// structural recursion. This check is needed for structs and enums.
+    pub fn is_representable(&'tcx self, cx: &ctxt<'tcx>, sp: Span) -> Representability {
+
+        // Iterate until something non-representable is found
+        fn find_nonrepresentable<'tcx, It: Iterator<Item=Ty<'tcx>>>(cx: &ctxt<'tcx>, sp: Span,
+                                                                    seen: &mut Vec<Ty<'tcx>>,
+                                                                    iter: It)
+                                                                    -> Representability {
+            iter.fold(Representable,
+                      |r, ty| cmp::max(r, is_type_structurally_recursive(cx, sp, seen, ty)))
+        }
+
+        fn are_inner_types_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
+                                           seen: &mut Vec<Ty<'tcx>>, ty: Ty<'tcx>)
+                                           -> Representability {
+            match ty.sty {
+                TyTuple(ref ts) => {
+                    find_nonrepresentable(cx, sp, seen, ts.iter().cloned())
+                }
+                // Fixed-length vectors.
+                // FIXME(#11924) Behavior undecided for zero-length vectors.
+                TyArray(ty, _) => {
+                    is_type_structurally_recursive(cx, sp, seen, ty)
+                }
+                TyStruct(did, substs) => {
+                    let fields = cx.struct_fields(did, substs);
+                    find_nonrepresentable(cx, sp, seen, fields.iter().map(|f| f.mt.ty))
+                }
+                TyEnum(did, substs) => {
+                    let vs = cx.enum_variants(did);
+                    let iter = vs.iter()
+                        .flat_map(|variant| &variant.args)
+                        .map(|aty| { aty.subst_spanned(cx, substs, Some(sp)) });
 
-                find_nonrepresentable(cx, sp, seen, iter)
-            }
-            TyClosure(..) => {
-                // this check is run on type definitions, so we don't expect
-                // to see closure types
-                cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
+                    find_nonrepresentable(cx, sp, seen, iter)
+                }
+                TyClosure(..) => {
+                    // this check is run on type definitions, so we don't expect
+                    // to see closure types
+                    cx.sess.bug(&format!("requires check invoked on inapplicable type: {:?}", ty))
+                }
+                _ => Representable,
             }
-            _ => Representable,
         }
-    }
 
-    fn same_struct_or_enum_def_id(ty: Ty, did: DefId) -> bool {
-        match ty.sty {
-            TyStruct(ty_did, _) | TyEnum(ty_did, _) => {
-                 ty_did == did
+        fn same_struct_or_enum_def_id(ty: Ty, did: DefId) -> bool {
+            match ty.sty {
+                TyStruct(ty_did, _) | TyEnum(ty_did, _) => {
+                     ty_did == did
+                }
+                _ => false
             }
-            _ => false
         }
-    }
 
-    fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
-        match (&a.sty, &b.sty) {
-            (&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) |
-            (&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => {
-                if did_a != did_b {
-                    return false;
-                }
+        fn same_type<'tcx>(a: Ty<'tcx>, b: Ty<'tcx>) -> bool {
+            match (&a.sty, &b.sty) {
+                (&TyStruct(did_a, ref substs_a), &TyStruct(did_b, ref substs_b)) |
+                (&TyEnum(did_a, ref substs_a), &TyEnum(did_b, ref substs_b)) => {
+                    if did_a != did_b {
+                        return false;
+                    }
 
-                let types_a = substs_a.types.get_slice(subst::TypeSpace);
-                let types_b = substs_b.types.get_slice(subst::TypeSpace);
+                    let types_a = substs_a.types.get_slice(subst::TypeSpace);
+                    let types_b = substs_b.types.get_slice(subst::TypeSpace);
 
-                let mut pairs = types_a.iter().zip(types_b);
+                    let mut pairs = types_a.iter().zip(types_b);
 
-                pairs.all(|(&a, &b)| same_type(a, b))
-            }
-            _ => {
-                a == b
+                    pairs.all(|(&a, &b)| same_type(a, b))
+                }
+                _ => {
+                    a == b
+                }
             }
         }
-    }
-
-    // Does the type `ty` directly (without indirection through a pointer)
-    // contain any types on stack `seen`?
-    fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
-                                            seen: &mut Vec<Ty<'tcx>>,
-                                            ty: Ty<'tcx>) -> Representability {
-        debug!("is_type_structurally_recursive: {:?}", ty);
 
-        match ty.sty {
-            TyStruct(did, _) | TyEnum(did, _) => {
-                {
-                    // Iterate through stack of previously seen types.
-                    let mut iter = seen.iter();
+        // Does the type `ty` directly (without indirection through a pointer)
+        // contain any types on stack `seen`?
+        fn is_type_structurally_recursive<'tcx>(cx: &ctxt<'tcx>, sp: Span,
+                                                seen: &mut Vec<Ty<'tcx>>,
+                                                ty: Ty<'tcx>) -> Representability {
+            debug!("is_type_structurally_recursive: {:?}", ty);
 
-                    // The first item in `seen` is the type we are actually curious about.
-                    // We want to return SelfRecursive if this type contains itself.
-                    // It is important that we DON'T take generic parameters into account
-                    // for this check, so that Bar<T> in this example counts as SelfRecursive:
-                    //
-                    // struct Foo;
-                    // struct Bar<T> { x: Bar<Foo> }
+            match ty.sty {
+                TyStruct(did, _) | TyEnum(did, _) => {
+                    {
+                        // Iterate through stack of previously seen types.
+                        let mut iter = seen.iter();
+
+                        // The first item in `seen` is the type we are actually curious about.
+                        // We want to return SelfRecursive if this type contains itself.
+                        // It is important that we DON'T take generic parameters into account
+                        // for this check, so that Bar<T> in this example counts as SelfRecursive:
+                        //
+                        // struct Foo;
+                        // struct Bar<T> { x: Bar<Foo> }
+
+                        match iter.next() {
+                            Some(&seen_type) => {
+                                if same_struct_or_enum_def_id(seen_type, did) {
+                                    debug!("SelfRecursive: {:?} contains {:?}",
+                                           seen_type,
+                                           ty);
+                                    return SelfRecursive;
+                                }
+                            }
+                            None => {}
+                        }
 
-                    match iter.next() {
-                        Some(&seen_type) => {
-                            if same_struct_or_enum_def_id(seen_type, did) {
-                                debug!("SelfRecursive: {:?} contains {:?}",
+                        // We also need to know whether the first item contains other types
+                        // that are structurally recursive. If we don't catch this case, we
+                        // will recurse infinitely for some inputs.
+                        //
+                        // It is important that we DO take generic parameters into account
+                        // here, so that code like this is considered SelfRecursive, not
+                        // ContainsRecursive:
+                        //
+                        // struct Foo { Option<Option<Foo>> }
+
+                        for &seen_type in iter {
+                            if same_type(ty, seen_type) {
+                                debug!("ContainsRecursive: {:?} contains {:?}",
                                        seen_type,
                                        ty);
-                                return SelfRecursive;
+                                return ContainsRecursive;
                             }
                         }
-                        None => {}
                     }
 
-                    // We also need to know whether the first item contains other types that
-                    // are structurally recursive. If we don't catch this case, we will recurse
-                    // infinitely for some inputs.
-                    //
-                    // It is important that we DO take generic parameters into account here,
-                    // so that code like this is considered SelfRecursive, not ContainsRecursive:
-                    //
-                    // struct Foo { Option<Option<Foo>> }
-
-                    for &seen_type in iter {
-                        if same_type(ty, seen_type) {
-                            debug!("ContainsRecursive: {:?} contains {:?}",
-                                   seen_type,
-                                   ty);
-                            return ContainsRecursive;
-                        }
-                    }
+                    // For structs and enums, track all previously seen types by pushing them
+                    // onto the 'seen' stack.
+                    seen.push(ty);
+                    let out = are_inner_types_recursive(cx, sp, seen, ty);
+                    seen.pop();
+                    out
+                }
+                _ => {
+                    // No need to push in other cases.
+                    are_inner_types_recursive(cx, sp, seen, ty)
                 }
-
-                // For structs and enums, track all previously seen types by pushing them
-                // onto the 'seen' stack.
-                seen.push(ty);
-                let out = are_inner_types_recursive(cx, sp, seen, ty);
-                seen.pop();
-                out
-            }
-            _ => {
-                // No need to push in other cases.
-                are_inner_types_recursive(cx, sp, seen, ty)
             }
         }
-    }
-
-    debug!("is_type_representable: {:?}", ty);
-
-    // To avoid a stack overflow when checking an enum variant or struct that
-    // contains a different, structurally recursive type, maintain a stack
-    // of seen types and check recursion for each of them (issues #3008, #3779).
-    let mut seen: Vec<Ty> = Vec::new();
-    let r = is_type_structurally_recursive(cx, sp, &mut seen, ty);
-    debug!("is_type_representable: {:?} is {:?}", ty, r);
-    r
-}
-
-pub fn type_is_trait(ty: Ty) -> bool {
-    match ty.sty {
-        TyTrait(..) => true,
-        _ => false
-    }
-}
-
-pub fn type_is_integral(ty: Ty) -> bool {
-    match ty.sty {
-      TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true,
-      _ => false
-    }
-}
 
-pub fn type_is_fresh(ty: Ty) -> bool {
-    match ty.sty {
-      TyInfer(FreshTy(_)) => true,
-      TyInfer(FreshIntTy(_)) => true,
-      TyInfer(FreshFloatTy(_)) => true,
-      _ => false
-    }
-}
+        debug!("is_type_representable: {:?}", self);
 
-pub fn type_is_uint(ty: Ty) -> bool {
-    match ty.sty {
-      TyInfer(IntVar(_)) | TyUint(ast::TyUs) => true,
-      _ => false
+        // To avoid a stack overflow when checking an enum variant or struct that
+        // contains a different, structurally recursive type, maintain a stack
+        // of seen types and check recursion for each of them (issues #3008, #3779).
+        let mut seen: Vec<Ty> = Vec::new();
+        let r = is_type_structurally_recursive(cx, sp, &mut seen, self);
+        debug!("is_type_representable: {:?} is {:?}", self, r);
+        r
     }
-}
 
-pub fn type_is_char(ty: Ty) -> bool {
-    match ty.sty {
-        TyChar => true,
-        _ => false
-    }
-}
-
-pub fn type_is_bare_fn(ty: Ty) -> bool {
-    match ty.sty {
-        TyBareFn(..) => true,
-        _ => false
-    }
-}
-
-pub fn type_is_bare_fn_item(ty: Ty) -> bool {
-    match ty.sty {
-        TyBareFn(Some(_), _) => true,
-        _ => false
+    pub fn is_trait(&self) -> bool {
+        match self.sty {
+            TyTrait(..) => true,
+            _ => false
+        }
     }
-}
 
-pub fn type_is_fp(ty: Ty) -> bool {
-    match ty.sty {
-      TyInfer(FloatVar(_)) | TyFloat(_) => true,
-      _ => false
+    pub fn is_integral(&self) -> bool {
+        match self.sty {
+            TyInfer(IntVar(_)) | TyInt(_) | TyUint(_) => true,
+            _ => false
+        }
     }
-}
 
-pub fn type_is_numeric(ty: Ty) -> bool {
-    return type_is_integral(ty) || type_is_fp(ty);
-}
-
-pub fn type_is_signed(ty: Ty) -> bool {
-    match ty.sty {
-      TyInt(_) => true,
-      _ => false
+    pub fn is_fresh(&self) -> bool {
+        match self.sty {
+            TyInfer(FreshTy(_)) => true,
+            TyInfer(FreshIntTy(_)) => true,
+            TyInfer(FreshFloatTy(_)) => true,
+            _ => false
+        }
     }
-}
 
-pub fn type_is_machine(ty: Ty) -> bool {
-    match ty.sty {
-        TyInt(ast::TyIs) | TyUint(ast::TyUs) => false,
-        TyInt(..) | TyUint(..) | TyFloat(..) => true,
-        _ => false
+    pub fn is_uint(&self) -> bool {
+        match self.sty {
+            TyInfer(IntVar(_)) | TyUint(ast::TyUs) => true,
+            _ => false
+        }
     }
-}
 
-// Whether a type is enum like, that is an enum type with only nullary
-// constructors
-pub fn type_is_c_like_enum(cx: &ctxt, ty: Ty) -> bool {
-    match ty.sty {
-        TyEnum(did, _) => {
-            let variants = enum_variants(cx, did);
-            if variants.is_empty() {
-                false
-            } else {
-                variants.iter().all(|v| v.args.is_empty())
-            }
+    pub fn is_char(&self) -> bool {
+        match self.sty {
+            TyChar => true,
+            _ => false
         }
-        _ => false
     }
-}
 
-// Returns the type and mutability of *ty.
-//
-// The parameter `explicit` indicates if this is an *explicit* dereference.
-// Some types---notably unsafe ptrs---can only be dereferenced explicitly.
-pub fn deref<'tcx>(ty: Ty<'tcx>, explicit: bool) -> Option<mt<'tcx>> {
-    match ty.sty {
-        TyBox(ty) => {
-            Some(mt {
-                ty: ty,
-                mutbl: ast::MutImmutable,
-            })
-        },
-        TyRef(_, mt) => Some(mt),
-        TyRawPtr(mt) if explicit => Some(mt),
-        _ => None
+    pub fn is_bare_fn(&self) -> bool {
+        match self.sty {
+            TyBareFn(..) => true,
+            _ => false
+        }
     }
-}
 
-pub fn type_content<'tcx>(ty: Ty<'tcx>) -> Ty<'tcx> {
-    match ty.sty {
-        TyBox(ty) => ty,
-        TyRef(_, mt) | TyRawPtr(mt) => mt.ty,
-        _ => ty
+    pub fn is_bare_fn_item(&self) -> bool {
+        match self.sty {
+            TyBareFn(Some(_), _) => true,
+            _ => false
+        }
     }
-}
 
-// Returns the type of ty[i]
-pub fn index<'tcx>(ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-    match ty.sty {
-        TyArray(ty, _) | TySlice(ty) => Some(ty),
-        _ => None
+    pub fn is_fp(&self) -> bool {
+        match self.sty {
+            TyInfer(FloatVar(_)) | TyFloat(_) => true,
+            _ => false
+        }
     }
-}
 
-// Returns the type of elements contained within an 'array-like' type.
-// This is exactly the same as the above, except it supports strings,
-// which can't actually be indexed.
-pub fn array_element_ty<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>) -> Option<Ty<'tcx>> {
-    match ty.sty {
-        TyArray(ty, _) | TySlice(ty) => Some(ty),
-        TyStr => Some(tcx.types.u8),
-        _ => None
+    pub fn is_numeric(&self) -> bool {
+        self.is_integral() || self.is_fp()
     }
-}
-
-/// Returns the type of element at index `i` in tuple or tuple-like type `t`.
-/// For an enum `t`, `variant` is None only if `t` is a univariant enum.
-pub fn positional_element_ty<'tcx>(cx: &ctxt<'tcx>,
-                                   ty: Ty<'tcx>,
-                                   i: usize,
-                                   variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
-
-    match (&ty.sty, variant) {
-        (&TyTuple(ref v), None) => v.get(i).cloned(),
 
-
-        (&TyStruct(def_id, substs), None) => lookup_struct_fields(cx, def_id)
-            .get(i)
-            .map(|&t|lookup_item_type(cx, t.id).ty.subst(cx, substs)),
-
-        (&TyEnum(def_id, substs), Some(variant_def_id)) => {
-            let variant_info = enum_variant_with_id(cx, def_id, variant_def_id);
-            variant_info.args.get(i).map(|t|t.subst(cx, substs))
-        }
-
-        (&TyEnum(def_id, substs), None) => {
-            assert!(enum_is_univariant(cx, def_id));
-            let enum_variants = enum_variants(cx, def_id);
-            let variant_info = &(*enum_variants)[0];
-            variant_info.args.get(i).map(|t|t.subst(cx, substs))
+    pub fn is_signed(&self) -> bool {
+        match self.sty {
+            TyInt(_) => true,
+            _ => false
         }
-
-        _ => None
     }
-}
-
-/// Returns the type of element at field `n` in struct or struct-like type `t`.
-/// For an enum `t`, `variant` must be some def id.
-pub fn named_element_ty<'tcx>(cx: &ctxt<'tcx>,
-                              ty: Ty<'tcx>,
-                              n: ast::Name,
-                              variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
 
-    match (&ty.sty, variant) {
-        (&TyStruct(def_id, substs), None) => {
-            let r = lookup_struct_fields(cx, def_id);
-            r.iter().find(|f| f.name == n)
-                .map(|&f| lookup_field_type(cx, def_id, f.id, substs))
-        }
-        (&TyEnum(def_id, substs), Some(variant_def_id)) => {
-            let variant_info = enum_variant_with_id(cx, def_id, variant_def_id);
-            variant_info.arg_names.as_ref()
-                .expect("must have struct enum variant if accessing a named fields")
-                .iter().zip(&variant_info.args)
-                .find(|&(&name, _)| name == n)
-                .map(|(_name, arg_t)| arg_t.subst(cx, substs))
+    pub fn is_machine(&self) -> bool {
+        match self.sty {
+            TyInt(ast::TyIs) | TyUint(ast::TyUs) => false,
+            TyInt(..) | TyUint(..) | TyFloat(..) => true,
+            _ => false
         }
-        _ => None
     }
-}
 
-pub fn node_id_to_type<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Ty<'tcx> {
-    match node_id_to_type_opt(cx, id) {
-       Some(ty) => ty,
-       None => cx.sess.bug(
-           &format!("node_id_to_type: no type for node `{}`",
-                   cx.map.node_to_string(id)))
-    }
-}
-
-pub fn node_id_to_type_opt<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> Option<Ty<'tcx>> {
-    match cx.node_types.borrow().get(&id) {
-       Some(&ty) => Some(ty),
-       None => None
-    }
-}
-
-pub fn node_id_item_substs<'tcx>(cx: &ctxt<'tcx>, id: ast::NodeId) -> ItemSubsts<'tcx> {
-    match cx.item_substs.borrow().get(&id) {
-      None => ItemSubsts::empty(),
-      Some(ts) => ts.clone(),
+    // Whether a type is enum like, that is an enum type with only nullary
+    // constructors
+    pub fn is_c_like_enum(&self, cx: &ctxt) -> bool {
+        match self.sty {
+            TyEnum(did, _) => {
+                let variants = cx.enum_variants(did);
+                if variants.is_empty() {
+                    false
+                } else {
+                    variants.iter().all(|v| v.args.is_empty())
+                }
+            }
+            _ => false
+        }
     }
-}
 
-pub fn fn_is_variadic(fty: Ty) -> bool {
-    match fty.sty {
-        TyBareFn(_, ref f) => f.sig.0.variadic,
-        ref s => {
-            panic!("fn_is_variadic() called on non-fn type: {:?}", s)
+    // Returns the type and mutability of *ty.
+    //
+    // The parameter `explicit` indicates if this is an *explicit* dereference.
+    // Some types---notably unsafe ptrs---can only be dereferenced explicitly.
+    pub fn builtin_deref(&self, explicit: bool) -> Option<mt<'tcx>> {
+        match self.sty {
+            TyBox(ty) => {
+                Some(mt {
+                    ty: ty,
+                    mutbl: ast::MutImmutable,
+                })
+            },
+            TyRef(_, mt) => Some(mt),
+            TyRawPtr(mt) if explicit => Some(mt),
+            _ => None
         }
     }
-}
 
-pub fn ty_fn_sig<'tcx>(fty: Ty<'tcx>) -> &'tcx PolyFnSig<'tcx> {
-    match fty.sty {
-        TyBareFn(_, ref f) => &f.sig,
-        ref s => {
-            panic!("ty_fn_sig() called on non-fn type: {:?}", s)
+    // Returns the type of ty[i]
+    pub fn builtin_index(&self) -> Option<Ty<'tcx>> {
+        match self.sty {
+            TyArray(ty, _) | TySlice(ty) => Some(ty),
+            _ => None
         }
     }
-}
 
-/// Returns the ABI of the given function.
-pub fn ty_fn_abi(fty: Ty) -> abi::Abi {
-    match fty.sty {
-        TyBareFn(_, ref f) => f.abi,
-        _ => panic!("ty_fn_abi() called on non-fn type"),
+    pub fn fn_sig(&self) -> &'tcx PolyFnSig<'tcx> {
+        match self.sty {
+            TyBareFn(_, ref f) => &f.sig,
+            _ => panic!("Ty::fn_sig() called on non-fn type: {:?}", self)
+        }
     }
-}
 
-// Type accessors for substructures of types
-pub fn ty_fn_args<'tcx>(fty: Ty<'tcx>) -> ty::Binder<Vec<Ty<'tcx>>> {
-    ty_fn_sig(fty).inputs()
-}
-
-pub fn ty_fn_ret<'tcx>(fty: Ty<'tcx>) -> Binder<FnOutput<'tcx>> {
-    match fty.sty {
-        TyBareFn(_, ref f) => f.sig.output(),
-        ref s => {
-            panic!("ty_fn_ret() called on non-fn type: {:?}", s)
+    /// Returns the ABI of the given function.
+    pub fn fn_abi(&self) -> abi::Abi {
+        match self.sty {
+            TyBareFn(_, ref f) => f.abi,
+            _ => panic!("Ty::fn_abi() called on non-fn type"),
         }
     }
-}
 
-pub fn is_fn_ty(fty: Ty) -> bool {
-    match fty.sty {
-        TyBareFn(..) => true,
-        _ => false
+    // Type accessors for substructures of types
+    pub fn fn_args(&self) -> ty::Binder<Vec<Ty<'tcx>>> {
+        self.fn_sig().inputs()
     }
-}
 
-pub fn ty_region(tcx: &ctxt,
-                 span: Span,
-                 ty: Ty) -> Region {
-    match ty.sty {
-        TyRef(r, _) => *r,
-        ref s => {
-            tcx.sess.span_bug(
-                span,
-                &format!("ty_region() invoked on an inappropriate ty: {:?}",
-                        s));
-        }
+    pub fn fn_ret(&self) -> Binder<FnOutput<'tcx>> {
+        self.fn_sig().output()
     }
-}
-
-pub fn free_region_from_def(outlives_extent: region::DestructionScopeData,
-                            def: &RegionParameterDef)
-    -> ty::Region
-{
-    let ret =
-        ty::ReFree(ty::FreeRegion { scope: outlives_extent,
-                                    bound_region: ty::BrNamed(def.def_id,
-                                                              def.name) });
-    debug!("free_region_from_def returns {:?}", ret);
-    ret
-}
 
-// Returns the type of a pattern as a monotype. Like @expr_ty, this function
-// doesn't provide type parameter substitutions.
-pub fn pat_ty<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Ty<'tcx> {
-    return node_id_to_type(cx, pat.id);
-}
-pub fn pat_ty_opt<'tcx>(cx: &ctxt<'tcx>, pat: &ast::Pat) -> Option<Ty<'tcx>> {
-    return node_id_to_type_opt(cx, pat.id);
-}
-
-
-// Returns the type of an expression as a monotype.
-//
-// NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
-// some cases, we insert `AutoAdjustment` annotations such as auto-deref or
-// auto-ref.  The type returned by this function does not consider such
-// adjustments.  See `expr_ty_adjusted()` instead.
-//
-// NB (2): This type doesn't provide type parameter substitutions; e.g. if you
-// ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
-// instead of "fn(ty) -> T with T = isize".
-pub fn expr_ty<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> {
-    return node_id_to_type(cx, expr.id);
-}
-
-pub fn expr_ty_opt<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Option<Ty<'tcx>> {
-    return node_id_to_type_opt(cx, expr.id);
-}
-
-/// Returns the type of `expr`, considering any `AutoAdjustment`
-/// entry recorded for that expression.
-///
-/// It would almost certainly be better to store the adjusted ty in with
-/// the `AutoAdjustment`, but I opted not to do this because it would
-/// require serializing and deserializing the type and, although that's not
-/// hard to do, I just hate that code so much I didn't want to touch it
-/// unless it was to fix it properly, which seemed a distraction from the
-/// thread at hand! -nmatsakis
-pub fn expr_ty_adjusted<'tcx>(cx: &ctxt<'tcx>, expr: &ast::Expr) -> Ty<'tcx> {
-    adjust_ty(cx, expr.span, expr.id, expr_ty(cx, expr),
-              cx.adjustments.borrow().get(&expr.id),
-              |method_call| cx.method_map.borrow().get(&method_call).map(|method| method.ty))
-}
-
-pub fn expr_span(cx: &ctxt, id: NodeId) -> Span {
-    match cx.map.find(id) {
-        Some(ast_map::NodeExpr(e)) => {
-            e.span
-        }
-        Some(f) => {
-            cx.sess.bug(&format!("Node id {} is not an expr: {:?}",
-                                id,
-                                f));
-        }
-        None => {
-            cx.sess.bug(&format!("Node id {} is not present \
-                                in the node map", id));
+    pub fn is_fn(&self) -> bool {
+        match self.sty {
+            TyBareFn(..) => true,
+            _ => false
         }
     }
-}
 
-pub fn local_var_name_str(cx: &ctxt, id: NodeId) -> InternedString {
-    match cx.map.find(id) {
-        Some(ast_map::NodeLocal(pat)) => {
-            match pat.node {
-                ast::PatIdent(_, ref path1, _) => {
-                    token::get_ident(path1.node)
-                }
-                _ => {
-                    cx.sess.bug(
-                        &format!("Variable id {} maps to {:?}, not local",
-                                id,
-                                pat));
-                }
-            }
-        }
-        r => {
-            cx.sess.bug(&format!("Variable id {} maps to {:?}, not local",
-                                id,
-                                r));
+    /// See `expr_ty_adjusted`
+    pub fn adjust<F>(&'tcx self, cx: &ctxt<'tcx>,
+                     span: Span,
+                     expr_id: ast::NodeId,
+                     adjustment: Option<&AutoAdjustment<'tcx>>,
+                     mut method_type: F)
+                     -> Ty<'tcx> where
+        F: FnMut(MethodCall) -> Option<Ty<'tcx>>,
+    {
+        if let TyError = self.sty {
+            return self;
         }
-    }
-}
-
-/// See `expr_ty_adjusted`
-pub fn adjust_ty<'tcx, F>(cx: &ctxt<'tcx>,
-                          span: Span,
-                          expr_id: ast::NodeId,
-                          unadjusted_ty: Ty<'tcx>,
-                          adjustment: Option<&AutoAdjustment<'tcx>>,
-                          mut method_type: F)
-                          -> Ty<'tcx> where
-    F: FnMut(MethodCall) -> Option<Ty<'tcx>>,
-{
-    if let TyError = unadjusted_ty.sty {
-        return unadjusted_ty;
-    }
 
-    return match adjustment {
-        Some(adjustment) => {
-            match *adjustment {
-               AdjustReifyFnPointer => {
-                    match unadjusted_ty.sty {
-                        ty::TyBareFn(Some(_), b) => {
-                            ty::mk_bare_fn(cx, None, b)
-                        }
-                        _ => {
-                            cx.sess.bug(
-                                &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
-                                          {:?}", unadjusted_ty));
+        return match adjustment {
+            Some(adjustment) => {
+                match *adjustment {
+                   AdjustReifyFnPointer => {
+                        match self.sty {
+                            ty::TyBareFn(Some(_), b) => {
+                                cx.mk_fn(None, b)
+                            }
+                            _ => {
+                                cx.sess.bug(
+                                    &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
+                                              {:?}", self));
+                            }
                         }
                     }
-                }
 
-               AdjustUnsafeFnPointer => {
-                    match unadjusted_ty.sty {
-                        ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
-                        ref b => {
-                            cx.sess.bug(
-                                &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
-                                         {:?}",
-                                        b));
+                   AdjustUnsafeFnPointer => {
+                        match self.sty {
+                            ty::TyBareFn(None, b) => cx.safe_to_unsafe_fn_ty(b),
+                            ref b => {
+                                cx.sess.bug(
+                                    &format!("AdjustReifyFnPointer adjustment on non-fn-item: \
+                                             {:?}",
+                                            b));
+                            }
                         }
-                    }
-               }
-
-                AdjustDerefRef(ref adj) => {
-                    let mut adjusted_ty = unadjusted_ty;
-
-                    if !ty::type_is_error(adjusted_ty) {
-                        for i in 0..adj.autoderefs {
-                            let method_call = MethodCall::autoderef(expr_id, i as u32);
-                            match method_type(method_call) {
-                                Some(method_ty) => {
-                                    // Overloaded deref operators have all late-bound
-                                    // regions fully instantiated and coverge.
-                                    let fn_ret =
-                                        ty::no_late_bound_regions(cx,
-                                                                  &ty_fn_ret(method_ty)).unwrap();
-                                    adjusted_ty = fn_ret.unwrap();
+                   }
+
+                    AdjustDerefRef(ref adj) => {
+                        let mut adjusted_ty = self;
+
+                        if !adjusted_ty.references_error() {
+                            for i in 0..adj.autoderefs {
+                                let method_call = MethodCall::autoderef(expr_id, i as u32);
+                                match method_type(method_call) {
+                                    Some(method_ty) => {
+                                        // Overloaded deref operators have all late-bound
+                                        // regions fully instantiated and coverge.
+                                        let fn_ret =
+                                            cx.no_late_bound_regions(&method_ty.fn_ret()).unwrap();
+                                        adjusted_ty = fn_ret.unwrap();
+                                    }
+                                    None => {}
                                 }
-                                None => {}
-                            }
-                            match deref(adjusted_ty, true) {
-                                Some(mt) => { adjusted_ty = mt.ty; }
-                                None => {
-                                    cx.sess.span_bug(
-                                        span,
-                                        &format!("the {}th autoderef failed: {}",
-                                                i,
-                                                 adjusted_ty)
-                                        );
+                                match adjusted_ty.builtin_deref(true) {
+                                    Some(mt) => { adjusted_ty = mt.ty; }
+                                    None => {
+                                        cx.sess.span_bug(
+                                            span,
+                                            &format!("the {}th autoderef failed: {}",
+                                                    i,
+                                                     adjusted_ty)
+                                            );
+                                    }
                                 }
                             }
                         }
-                    }
 
-                    if let Some(target) = adj.unsize {
-                        target
-                    } else {
-                        adjust_ty_for_autoref(cx, adjusted_ty, adj.autoref)
+                        if let Some(target) = adj.unsize {
+                            target
+                        } else {
+                            adjusted_ty.adjust_for_autoref(cx, adj.autoref)
+                        }
                     }
                 }
             }
-        }
-        None => unadjusted_ty
-    };
-}
-
-pub fn adjust_ty_for_autoref<'tcx>(cx: &ctxt<'tcx>,
-                                   ty: Ty<'tcx>,
-                                   autoref: Option<AutoRef<'tcx>>)
-                                   -> Ty<'tcx> {
-    match autoref {
-        None => ty,
-        Some(AutoPtr(r, m)) => {
-            mk_rptr(cx, r, mt { ty: ty, mutbl: m })
-        }
-        Some(AutoUnsafe(m)) => {
-            mk_ptr(cx, mt { ty: ty, mutbl: m })
-        }
+            None => self
+        };
     }
-}
 
-pub fn resolve_expr(tcx: &ctxt, expr: &ast::Expr) -> def::Def {
-    match tcx.def_map.borrow().get(&expr.id) {
-        Some(def) => def.full_def(),
-        None => {
-            tcx.sess.span_bug(expr.span, &format!(
-                "no def-map entry for expr {}", expr.id));
+    pub fn adjust_for_autoref(&'tcx self, cx: &ctxt<'tcx>,
+                              autoref: Option<AutoRef<'tcx>>)
+                              -> Ty<'tcx> {
+        match autoref {
+            None => self,
+            Some(AutoPtr(r, m)) => {
+                cx.mk_ref(r, mt { ty: self, mutbl: m })
+            }
+            Some(AutoUnsafe(m)) => {
+                cx.mk_ptr(mt { ty: self, mutbl: m })
+            }
         }
     }
-}
 
-pub fn expr_is_lval(tcx: &ctxt, expr: &ast::Expr) -> bool {
-     match expr.node {
-        ast::ExprPath(..) => {
-            // We can't use resolve_expr here, as this needs to run on broken
-            // programs. We don't need to through - associated items are all
-            // rvalues.
-            match tcx.def_map.borrow().get(&expr.id) {
-                Some(&def::PathResolution {
-                    base_def: def::DefStatic(..), ..
-                }) | Some(&def::PathResolution {
-                    base_def: def::DefUpvar(..), ..
-                }) | Some(&def::PathResolution {
-                    base_def: def::DefLocal(..), ..
-                }) => {
-                    true
+    fn sort_string(&self, cx: &ctxt) -> String {
+        match self.sty {
+            TyBool | TyChar | TyInt(_) |
+            TyUint(_) | TyFloat(_) | TyStr => self.to_string(),
+            TyTuple(ref tys) if tys.is_empty() => self.to_string(),
+
+            TyEnum(id, _) => format!("enum `{}`", cx.item_path_str(id)),
+            TyBox(_) => "box".to_string(),
+            TyArray(_, n) => format!("array of {} elements", n),
+            TySlice(_) => "slice".to_string(),
+            TyRawPtr(_) => "*-ptr".to_string(),
+            TyRef(_, _) => "&-ptr".to_string(),
+            TyBareFn(Some(_), _) => format!("fn item"),
+            TyBareFn(None, _) => "fn pointer".to_string(),
+            TyTrait(ref inner) => {
+                format!("trait {}", cx.item_path_str(inner.principal_def_id()))
+            }
+            TyStruct(id, _) => {
+                format!("struct `{}`", cx.item_path_str(id))
+            }
+            TyClosure(..) => "closure".to_string(),
+            TyTuple(_) => "tuple".to_string(),
+            TyInfer(TyVar(_)) => "inferred type".to_string(),
+            TyInfer(IntVar(_)) => "integral variable".to_string(),
+            TyInfer(FloatVar(_)) => "floating-point variable".to_string(),
+            TyInfer(FreshTy(_)) => "skolemized type".to_string(),
+            TyInfer(FreshIntTy(_)) => "skolemized integral type".to_string(),
+            TyInfer(FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
+            TyProjection(_) => "associated type".to_string(),
+            TyParam(ref p) => {
+                if p.space == subst::SelfSpace {
+                    "Self".to_string()
+                } else {
+                    "type parameter".to_string()
                 }
-
-                Some(..) => false,
-
-                None => tcx.sess.span_bug(expr.span, &format!(
-                    "no def for path {}", expr.id))
-            }
-        }
-
-        ast::ExprUnary(ast::UnDeref, _) |
-        ast::ExprField(..) |
-        ast::ExprTupField(..) |
-        ast::ExprIndex(..) => {
-            true
-        }
-
-        ast::ExprCall(..) |
-        ast::ExprMethodCall(..) |
-        ast::ExprStruct(..) |
-        ast::ExprRange(..) |
-        ast::ExprTup(..) |
-        ast::ExprIf(..) |
-        ast::ExprMatch(..) |
-        ast::ExprClosure(..) |
-        ast::ExprBlock(..) |
-        ast::ExprRepeat(..) |
-        ast::ExprVec(..) |
-        ast::ExprBreak(..) |
-        ast::ExprAgain(..) |
-        ast::ExprRet(..) |
-        ast::ExprWhile(..) |
-        ast::ExprLoop(..) |
-        ast::ExprAssign(..) |
-        ast::ExprInlineAsm(..) |
-        ast::ExprAssignOp(..) |
-        ast::ExprLit(_) |
-        ast::ExprUnary(..) |
-        ast::ExprBox(..) |
-        ast::ExprAddrOf(..) |
-        ast::ExprBinary(..) |
-        ast::ExprCast(..) => {
-            false
-        }
-
-        ast::ExprParen(ref e) => expr_is_lval(tcx, e),
-
-        ast::ExprIfLet(..) |
-        ast::ExprWhileLet(..) |
-        ast::ExprForLoop(..) |
-        ast::ExprMac(..) => {
-            tcx.sess.span_bug(
-                expr.span,
-                "macro expression remains after expansion");
-        }
-    }
-}
-
-pub fn stmt_node_id(s: &ast::Stmt) -> ast::NodeId {
-    match s.node {
-      ast::StmtDecl(_, id) | StmtExpr(_, id) | StmtSemi(_, id) => {
-        return id;
-      }
-      ast::StmtMac(..) => panic!("unexpanded macro in trans")
-    }
-}
-
-pub fn field_idx_strict(tcx: &ctxt, name: ast::Name, fields: &[field])
-                     -> usize {
-    let mut i = 0;
-    for f in fields { if f.name == name { return i; } i += 1; }
-    tcx.sess.bug(&format!(
-        "no field named `{}` found in the list of fields `{:?}`",
-        token::get_name(name),
-        fields.iter()
-              .map(|f| token::get_name(f.name).to_string())
-              .collect::<Vec<String>>()));
-}
-
-pub fn impl_or_trait_item_idx(id: ast::Name, trait_items: &[ImplOrTraitItem])
-                              -> Option<usize> {
-    trait_items.iter().position(|m| m.name() == id)
-}
-
-pub fn ty_sort_string(cx: &ctxt, ty: Ty) -> String {
-    match ty.sty {
-        TyBool | TyChar | TyInt(_) |
-        TyUint(_) | TyFloat(_) | TyStr => ty.to_string(),
-        TyTuple(ref tys) if tys.is_empty() => ty.to_string(),
-
-        TyEnum(id, _) => format!("enum `{}`", item_path_str(cx, id)),
-        TyBox(_) => "box".to_string(),
-        TyArray(_, n) => format!("array of {} elements", n),
-        TySlice(_) => "slice".to_string(),
-        TyRawPtr(_) => "*-ptr".to_string(),
-        TyRef(_, _) => "&-ptr".to_string(),
-        TyBareFn(Some(_), _) => format!("fn item"),
-        TyBareFn(None, _) => "fn pointer".to_string(),
-        TyTrait(ref inner) => {
-            format!("trait {}", item_path_str(cx, inner.principal_def_id()))
-        }
-        TyStruct(id, _) => {
-            format!("struct `{}`", item_path_str(cx, id))
-        }
-        TyClosure(..) => "closure".to_string(),
-        TyTuple(_) => "tuple".to_string(),
-        TyInfer(TyVar(_)) => "inferred type".to_string(),
-        TyInfer(IntVar(_)) => "integral variable".to_string(),
-        TyInfer(FloatVar(_)) => "floating-point variable".to_string(),
-        TyInfer(FreshTy(_)) => "skolemized type".to_string(),
-        TyInfer(FreshIntTy(_)) => "skolemized integral type".to_string(),
-        TyInfer(FreshFloatTy(_)) => "skolemized floating-point type".to_string(),
-        TyProjection(_) => "associated type".to_string(),
-        TyParam(ref p) => {
-            if p.space == subst::SelfSpace {
-                "Self".to_string()
-            } else {
-                "type parameter".to_string()
             }
+            TyError => "type error".to_string(),
         }
-        TyError => "type error".to_string(),
     }
 }
-
 /// Explains the source of a type err in a short, human readable way. This is meant to be placed
 /// in parentheses after some larger message. You should also invoke `note_and_explain_type_err()`
 /// afterwards to present additional details, particularly when it comes to lifetime-related
@@ -5298,8 +5087,8 @@ impl<'tcx> fmt::Display for type_err<'tcx> {
             terr_sorts(values) => tls::with(|tcx| {
                 // A naive approach to making sure that we're not reporting silly errors such as:
                 // (expected closure, found closure).
-                let expected_str = ty_sort_string(tcx, values.expected);
-                let found_str = ty_sort_string(tcx, values.found);
+                let expected_str = values.expected.sort_string(tcx);
+                let found_str = values.found.sort_string(tcx);
                 if expected_str == found_str {
                     write!(f, "expected {}, found a different {}", expected_str, found_str)
                 } else {
@@ -5308,8 +5097,8 @@ impl<'tcx> fmt::Display for type_err<'tcx> {
             }),
             terr_traits(values) => tls::with(|tcx| {
                 write!(f, "expected trait `{}`, found trait `{}`",
-                       item_path_str(tcx, values.expected),
-                       item_path_str(tcx, values.found))
+                       tcx.item_path_str(values.expected),
+                       tcx.item_path_str(values.found))
             }),
             terr_builtin_bounds(values) => {
                 if values.expected.is_empty() {
@@ -5361,127 +5150,6 @@ impl<'tcx> fmt::Display for type_err<'tcx> {
     }
 }
 
-pub fn note_and_explain_type_err<'tcx>(cx: &ctxt<'tcx>, err: &type_err<'tcx>, sp: Span) {
-    match *err {
-        terr_regions_does_not_outlive(subregion, superregion) => {
-            note_and_explain_region(cx, "", subregion, "...");
-            note_and_explain_region(cx, "...does not necessarily outlive ",
-                                    superregion, "");
-        }
-        terr_regions_not_same(region1, region2) => {
-            note_and_explain_region(cx, "", region1, "...");
-            note_and_explain_region(cx, "...is not the same lifetime as ",
-                                    region2, "");
-        }
-        terr_regions_no_overlap(region1, region2) => {
-            note_and_explain_region(cx, "", region1, "...");
-            note_and_explain_region(cx, "...does not overlap ",
-                                    region2, "");
-        }
-        terr_regions_insufficiently_polymorphic(_, conc_region) => {
-            note_and_explain_region(cx,
-                                    "concrete lifetime that was found is ",
-                                    conc_region, "");
-        }
-        terr_regions_overly_polymorphic(_, ty::ReInfer(ty::ReVar(_))) => {
-            // don't bother to print out the message below for
-            // inference variables, it's not very illuminating.
-        }
-        terr_regions_overly_polymorphic(_, conc_region) => {
-            note_and_explain_region(cx,
-                                    "expected concrete lifetime is ",
-                                    conc_region, "");
-        }
-        terr_sorts(values) => {
-            let expected_str = ty_sort_string(cx, values.expected);
-            let found_str = ty_sort_string(cx, values.found);
-            if expected_str == found_str && expected_str == "closure" {
-                cx.sess.span_note(sp, &format!("no two closures, even if identical, have the same \
-                                                type"));
-                cx.sess.span_help(sp, &format!("consider boxing your closure and/or \
-                                        using it as a trait object"));
-            }
-        }
-        _ => {}
-    }
-}
-
-pub fn provided_source(cx: &ctxt, id: ast::DefId) -> Option<ast::DefId> {
-    cx.provided_method_sources.borrow().get(&id).cloned()
-}
-
-pub fn provided_trait_methods<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                                    -> Vec<Rc<Method<'tcx>>> {
-    if is_local(id) {
-        if let ItemTrait(_, _, _, ref ms) = cx.map.expect_item(id.node).node {
-            ms.iter().filter_map(|ti| {
-                if let ast::MethodTraitItem(_, Some(_)) = ti.node {
-                    match impl_or_trait_item(cx, ast_util::local_def(ti.id)) {
-                        MethodTraitItem(m) => Some(m),
-                        _ => {
-                            cx.sess.bug("provided_trait_methods(): \
-                                         non-method item found from \
-                                         looking up provided method?!")
-                        }
-                    }
-                } else {
-                    None
-                }
-            }).collect()
-        } else {
-            cx.sess.bug(&format!("provided_trait_methods: `{:?}` is not a trait", id))
-        }
-    } else {
-        csearch::get_provided_trait_methods(cx, id)
-    }
-}
-
-pub fn associated_consts<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                               -> Vec<Rc<AssociatedConst<'tcx>>> {
-    if is_local(id) {
-        match cx.map.expect_item(id.node).node {
-            ItemTrait(_, _, _, ref tis) => {
-                tis.iter().filter_map(|ti| {
-                    if let ast::ConstTraitItem(_, _) = ti.node {
-                        match impl_or_trait_item(cx, ast_util::local_def(ti.id)) {
-                            ConstTraitItem(ac) => Some(ac),
-                            _ => {
-                                cx.sess.bug("associated_consts(): \
-                                             non-const item found from \
-                                             looking up a constant?!")
-                            }
-                        }
-                    } else {
-                        None
-                    }
-                }).collect()
-            }
-            ItemImpl(_, _, _, _, _, ref iis) => {
-                iis.iter().filter_map(|ii| {
-                    if let ast::ConstImplItem(_, _) = ii.node {
-                        match impl_or_trait_item(cx, ast_util::local_def(ii.id)) {
-                            ConstTraitItem(ac) => Some(ac),
-                            _ => {
-                                cx.sess.bug("associated_consts(): \
-                                             non-const item found from \
-                                             looking up a constant?!")
-                            }
-                        }
-                    } else {
-                        None
-                    }
-                }).collect()
-            }
-            _ => {
-                cx.sess.bug(&format!("associated_consts: `{:?}` is not a trait \
-                                      or impl", id))
-            }
-        }
-    } else {
-        csearch::get_associated_consts(cx, id)
-    }
-}
-
 /// Helper for looking things up in the various maps that are populated during
 /// typeck::collect (e.g., `cx.impl_or_trait_items`, `cx.tcache`, etc).  All of
 /// these share the pattern that if the id is local, it should have been loaded
@@ -5508,1445 +5176,1500 @@ fn lookup_locally_or_in_crate_store<V, F>(descr: &str,
     v
 }
 
-pub fn trait_item<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId, idx: usize)
-                        -> ImplOrTraitItem<'tcx> {
-    let method_def_id = (*ty::trait_item_def_ids(cx, trait_did))[idx].def_id();
-    impl_or_trait_item(cx, method_def_id)
-}
-
-pub fn trait_items<'tcx>(cx: &ctxt<'tcx>, trait_did: ast::DefId)
-                         -> Rc<Vec<ImplOrTraitItem<'tcx>>> {
-    let mut trait_items = cx.trait_items_cache.borrow_mut();
-    match trait_items.get(&trait_did).cloned() {
-        Some(trait_items) => trait_items,
-        None => {
-            let def_ids = ty::trait_item_def_ids(cx, trait_did);
-            let items: Rc<Vec<ImplOrTraitItem>> =
-                Rc::new(def_ids.iter()
-                               .map(|d| impl_or_trait_item(cx, d.def_id()))
-                               .collect());
-            trait_items.insert(trait_did, items.clone());
-            items
-        }
-    }
-}
-
-pub fn trait_impl_polarity<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                            -> Option<ast::ImplPolarity> {
-     if id.krate == ast::LOCAL_CRATE {
-         match cx.map.find(id.node) {
-             Some(ast_map::NodeItem(item)) => {
-                 match item.node {
-                     ast::ItemImpl(_, polarity, _, _, _, _) => Some(polarity),
-                     _ => None
-                 }
-             }
-             _ => None
-         }
-     } else {
-         csearch::get_impl_polarity(cx, id)
-     }
-}
-
-pub fn custom_coerce_unsized_kind<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
-                                        -> CustomCoerceUnsized {
-    memoized(&cx.custom_coerce_unsized_kinds, did, |did: DefId| {
-        let (kind, src) = if did.krate != ast::LOCAL_CRATE {
-            (csearch::get_custom_coerce_unsized_kind(cx, did), "external")
-        } else {
-            (None, "local")
-        };
-
-        match kind {
-            Some(kind) => kind,
-            None => {
-                cx.sess.bug(&format!("custom_coerce_unsized_kind: \
-                                      {} impl `{}` is missing its kind",
-                                     src, item_path_str(cx, did)));
-            }
+impl BorrowKind {
+    pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
+        match m {
+            ast::MutMutable => MutBorrow,
+            ast::MutImmutable => ImmBorrow,
         }
-    })
-}
+    }
 
-pub fn impl_or_trait_item<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                                -> ImplOrTraitItem<'tcx> {
-    lookup_locally_or_in_crate_store(
-        "impl_or_trait_items", id, &cx.impl_or_trait_items,
-        || csearch::get_impl_or_trait_item(cx, id))
-}
+    /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow
+    /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a
+    /// mutability that is stronger than necessary so that it at least *would permit* the borrow in
+    /// question.
+    pub fn to_mutbl_lossy(self) -> ast::Mutability {
+        match self {
+            MutBorrow => ast::MutMutable,
+            ImmBorrow => ast::MutImmutable,
 
-/// Returns the parameter index that the given associated type corresponds to.
-pub fn associated_type_parameter_index(cx: &ctxt,
-                                       trait_def: &TraitDef,
-                                       associated_type_id: ast::DefId)
-                                       -> usize {
-    for type_parameter_def in &trait_def.generics.types {
-        if type_parameter_def.def_id == associated_type_id {
-            return type_parameter_def.index as usize
+            // We have no type corresponding to a unique imm borrow, so
+            // use `&mut`. It gives all the capabilities of an `&uniq`
+            // and hence is a safe "over approximation".
+            UniqueImmBorrow => ast::MutMutable,
         }
     }
-    cx.sess.bug("couldn't find associated type parameter index")
-}
 
-pub fn trait_item_def_ids(cx: &ctxt, id: ast::DefId)
-                          -> Rc<Vec<ImplOrTraitItemId>> {
-    lookup_locally_or_in_crate_store(
-        "trait_item_def_ids", id, &cx.trait_item_def_ids,
-        || Rc::new(csearch::get_trait_item_def_ids(&cx.sess.cstore, id)))
+    pub fn to_user_str(&self) -> &'static str {
+        match *self {
+            MutBorrow => "mutable",
+            ImmBorrow => "immutable",
+            UniqueImmBorrow => "uniquely immutable",
+        }
+    }
 }
 
-/// Returns the trait-ref corresponding to a given impl, or None if it is
-/// an inherent impl.
-pub fn impl_trait_ref<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                            -> Option<TraitRef<'tcx>>
-{
-    lookup_locally_or_in_crate_store(
-        "impl_trait_refs", id, &cx.impl_trait_refs,
-        || csearch::get_impl_trait(cx, id))
-}
+impl<'tcx> ctxt<'tcx> {
+    /// Returns the type of element at index `i` in tuple or tuple-like type `t`.
+    /// For an enum `t`, `variant` is None only if `t` is a univariant enum.
+    pub fn positional_element_ty(&self,
+                                 ty: Ty<'tcx>,
+                                 i: usize,
+                                 variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
 
-/// Returns whether this DefId refers to an impl
-pub fn is_impl<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId) -> bool {
-    if id.krate == ast::LOCAL_CRATE {
-        if let Some(ast_map::NodeItem(
-            &ast::Item { node: ast::ItemImpl(..), .. })) = cx.map.find(id.node) {
-            true
-        } else {
-            false
+        match (&ty.sty, variant) {
+            (&TyTuple(ref v), None) => v.get(i).cloned(),
+
+
+            (&TyStruct(def_id, substs), None) => self.lookup_struct_fields(def_id)
+                .get(i)
+                .map(|&t| self.lookup_item_type(t.id).ty.subst(self, substs)),
+
+            (&TyEnum(def_id, substs), Some(variant_def_id)) => {
+                let variant_info = self.enum_variant_with_id(def_id, variant_def_id);
+                variant_info.args.get(i).map(|t|t.subst(self, substs))
+            }
+
+            (&TyEnum(def_id, substs), None) => {
+                assert!(self.enum_is_univariant(def_id));
+                let enum_variants = self.enum_variants(def_id);
+                let variant_info = &enum_variants[0];
+                variant_info.args.get(i).map(|t|t.subst(self, substs))
+            }
+
+            _ => None
         }
-    } else {
-        csearch::is_impl(&cx.sess.cstore, id)
     }
-}
 
-pub fn trait_ref_to_def_id(tcx: &ctxt, tr: &ast::TraitRef) -> ast::DefId {
-    tcx.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id()
-}
+    /// Returns the type of element at field `n` in struct or struct-like type `t`.
+    /// For an enum `t`, `variant` must be some def id.
+    pub fn named_element_ty(&self,
+                            ty: Ty<'tcx>,
+                            n: ast::Name,
+                            variant: Option<ast::DefId>) -> Option<Ty<'tcx>> {
 
-pub fn try_add_builtin_trait(
-    tcx: &ctxt,
-    trait_def_id: ast::DefId,
-    builtin_bounds: &mut EnumSet<BuiltinBound>)
-    -> bool
-{
-    //! Checks whether `trait_ref` refers to one of the builtin
-    //! traits, like `Send`, and adds the corresponding
-    //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
-    //! is a builtin trait.
-
-    match tcx.lang_items.to_builtin_kind(trait_def_id) {
-        Some(bound) => { builtin_bounds.insert(bound); true }
-        None => false
-    }
-}
-
-pub fn ty_to_def_id(ty: Ty) -> Option<ast::DefId> {
-    match ty.sty {
-        TyTrait(ref tt) =>
-            Some(tt.principal_def_id()),
-        TyStruct(id, _) |
-        TyEnum(id, _) |
-        TyClosure(id, _) =>
-            Some(id),
-        _ =>
-            None
+        match (&ty.sty, variant) {
+            (&TyStruct(def_id, substs), None) => {
+                let r = self.lookup_struct_fields(def_id);
+                r.iter().find(|f| f.name == n)
+                    .map(|&f| self.lookup_field_type(def_id, f.id, substs))
+            }
+            (&TyEnum(def_id, substs), Some(variant_def_id)) => {
+                let variant_info = self.enum_variant_with_id(def_id, variant_def_id);
+                variant_info.arg_names.as_ref()
+                    .expect("must have struct enum variant if accessing a named fields")
+                    .iter().zip(&variant_info.args)
+                    .find(|&(&name, _)| name == n)
+                    .map(|(_name, arg_t)| arg_t.subst(self, substs))
+            }
+            _ => None
+        }
     }
-}
 
-// Enum information
-#[derive(Clone)]
-pub struct VariantInfo<'tcx> {
-    pub args: Vec<Ty<'tcx>>,
-    pub arg_names: Option<Vec<ast::Name>>,
-    pub ctor_ty: Option<Ty<'tcx>>,
-    pub name: ast::Name,
-    pub id: ast::DefId,
-    pub disr_val: Disr,
-    pub vis: Visibility
-}
+    pub fn node_id_to_type(&self, id: ast::NodeId) -> Ty<'tcx> {
+        match self.node_id_to_type_opt(id) {
+           Some(ty) => ty,
+           None => self.sess.bug(
+               &format!("node_id_to_type: no type for node `{}`",
+                        self.map.node_to_string(id)))
+        }
+    }
 
-impl<'tcx> VariantInfo<'tcx> {
+    pub fn node_id_to_type_opt(&self, id: ast::NodeId) -> Option<Ty<'tcx>> {
+        self.node_types.borrow().get(&id).cloned()
+    }
 
-    /// Creates a new VariantInfo from the corresponding ast representation.
-    ///
-    /// Does not do any caching of the value in the type context.
-    pub fn from_ast_variant(cx: &ctxt<'tcx>,
-                            ast_variant: &ast::Variant,
-                            discriminant: Disr) -> VariantInfo<'tcx> {
-        let ctor_ty = node_id_to_type(cx, ast_variant.node.id);
+    pub fn node_id_item_substs(&self, id: ast::NodeId) -> ItemSubsts<'tcx> {
+        match self.item_substs.borrow().get(&id) {
+            None => ItemSubsts::empty(),
+            Some(ts) => ts.clone(),
+        }
+    }
 
-        match ast_variant.node.kind {
-            ast::TupleVariantKind(ref args) => {
-                let arg_tys = if !args.is_empty() {
-                    // the regions in the argument types come from the
-                    // enum def'n, and hence will all be early bound
-                    ty::no_late_bound_regions(cx, &ty_fn_args(ctor_ty)).unwrap()
-                } else {
-                    Vec::new()
-                };
+    // Returns the type of a pattern as a monotype. Like @expr_ty, this function
+    // doesn't provide type parameter substitutions.
+    pub fn pat_ty(&self, pat: &ast::Pat) -> Ty<'tcx> {
+        self.node_id_to_type(pat.id)
+    }
+    pub fn pat_ty_opt(&self, pat: &ast::Pat) -> Option<Ty<'tcx>> {
+        self.node_id_to_type_opt(pat.id)
+    }
 
-                return VariantInfo {
-                    args: arg_tys,
-                    arg_names: None,
-                    ctor_ty: Some(ctor_ty),
-                    name: ast_variant.node.name.name,
-                    id: ast_util::local_def(ast_variant.node.id),
-                    disr_val: discriminant,
-                    vis: ast_variant.node.vis
-                };
-            },
-            ast::StructVariantKind(ref struct_def) => {
-                let fields: &[StructField] = &struct_def.fields;
+    // Returns the type of an expression as a monotype.
+    //
+    // NB (1): This is the PRE-ADJUSTMENT TYPE for the expression.  That is, in
+    // some cases, we insert `AutoAdjustment` annotations such as auto-deref or
+    // auto-ref.  The type returned by this function does not consider such
+    // adjustments.  See `expr_ty_adjusted()` instead.
+    //
+    // NB (2): This type doesn't provide type parameter substitutions; e.g. if you
+    // ask for the type of "id" in "id(3)", it will return "fn(&isize) -> isize"
+    // instead of "fn(ty) -> T with T = isize".
+    pub fn expr_ty(&self, expr: &ast::Expr) -> Ty<'tcx> {
+        self.node_id_to_type(expr.id)
+    }
 
-                assert!(!fields.is_empty());
+    pub fn expr_ty_opt(&self, expr: &ast::Expr) -> Option<Ty<'tcx>> {
+        self.node_id_to_type_opt(expr.id)
+    }
 
-                let arg_tys = struct_def.fields.iter()
-                    .map(|field| node_id_to_type(cx, field.node.id)).collect();
-                let arg_names = fields.iter().map(|field| {
-                    match field.node.kind {
-                        NamedField(ident, _) => ident.name,
-                        UnnamedField(..) => cx.sess.bug(
-                            "enum_variants: all fields in struct must have a name")
-                    }
-                }).collect();
+    /// Returns the type of `expr`, considering any `AutoAdjustment`
+    /// entry recorded for that expression.
+    ///
+    /// It would almost certainly be better to store the adjusted ty in with
+    /// the `AutoAdjustment`, but I opted not to do this because it would
+    /// require serializing and deserializing the type and, although that's not
+    /// hard to do, I just hate that code so much I didn't want to touch it
+    /// unless it was to fix it properly, which seemed a distraction from the
+    /// thread at hand! -nmatsakis
+    pub fn expr_ty_adjusted(&self, expr: &ast::Expr) -> Ty<'tcx> {
+        self.expr_ty(expr)
+            .adjust(self, expr.span, expr.id,
+                    self.adjustments.borrow().get(&expr.id),
+                    |method_call| {
+            self.method_map.borrow().get(&method_call).map(|method| method.ty)
+        })
+    }
 
-                return VariantInfo {
-                    args: arg_tys,
-                    arg_names: Some(arg_names),
-                    ctor_ty: None,
-                    name: ast_variant.node.name.name,
-                    id: ast_util::local_def(ast_variant.node.id),
-                    disr_val: discriminant,
-                    vis: ast_variant.node.vis
-                };
+    pub fn expr_span(&self, id: NodeId) -> Span {
+        match self.map.find(id) {
+            Some(ast_map::NodeExpr(e)) => {
+                e.span
+            }
+            Some(f) => {
+                self.sess.bug(&format!("Node id {} is not an expr: {:?}",
+                                       id, f));
+            }
+            None => {
+                self.sess.bug(&format!("Node id {} is not present \
+                                        in the node map", id));
             }
         }
     }
-}
 
-pub fn substd_enum_variants<'tcx>(cx: &ctxt<'tcx>,
-                                  id: ast::DefId,
-                                  substs: &Substs<'tcx>)
-                                  -> Vec<Rc<VariantInfo<'tcx>>> {
-    enum_variants(cx, id).iter().map(|variant_info| {
-        let substd_args = variant_info.args.iter()
-            .map(|aty| aty.subst(cx, substs)).collect::<Vec<_>>();
+    pub fn local_var_name_str(&self, id: NodeId) -> InternedString {
+        match self.map.find(id) {
+            Some(ast_map::NodeLocal(pat)) => {
+                match pat.node {
+                    ast::PatIdent(_, ref path1, _) => {
+                        token::get_ident(path1.node)
+                    }
+                    _ => {
+                        self.sess.bug(&format!("Variable id {} maps to {:?}, not local",
+                                               id, pat));
+                    }
+                }
+            }
+            r => {
+                self.sess.bug(&format!("Variable id {} maps to {:?}, not local",
+                                       id, r));
+            }
+        }
+    }
 
-        let substd_ctor_ty = variant_info.ctor_ty.subst(cx, substs);
+    pub fn resolve_expr(&self, expr: &ast::Expr) -> def::Def {
+        match self.def_map.borrow().get(&expr.id) {
+            Some(def) => def.full_def(),
+            None => {
+                self.sess.span_bug(expr.span, &format!(
+                    "no def-map entry for expr {}", expr.id));
+            }
+        }
+    }
+
+    pub fn expr_is_lval(&self, expr: &ast::Expr) -> bool {
+         match expr.node {
+            ast::ExprPath(..) => {
+                // We can't use resolve_expr here, as this needs to run on broken
+                // programs. We don't need to through - associated items are all
+                // rvalues.
+                match self.def_map.borrow().get(&expr.id) {
+                    Some(&def::PathResolution {
+                        base_def: def::DefStatic(..), ..
+                    }) | Some(&def::PathResolution {
+                        base_def: def::DefUpvar(..), ..
+                    }) | Some(&def::PathResolution {
+                        base_def: def::DefLocal(..), ..
+                    }) => {
+                        true
+                    }
 
-        Rc::new(VariantInfo {
-            args: substd_args,
-            ctor_ty: substd_ctor_ty,
-            ..(**variant_info).clone()
-        })
-    }).collect()
-}
+                    Some(..) => false,
 
-pub fn item_path_str(cx: &ctxt, id: ast::DefId) -> String {
-    with_path(cx, id, |path| ast_map::path_to_string(path)).to_string()
-}
+                    None => self.sess.span_bug(expr.span, &format!(
+                        "no def for path {}", expr.id))
+                }
+            }
 
-#[derive(Copy, Clone)]
-pub enum DtorKind {
-    NoDtor,
-    TraitDtor(DefId, bool)
-}
+            ast::ExprUnary(ast::UnDeref, _) |
+            ast::ExprField(..) |
+            ast::ExprTupField(..) |
+            ast::ExprIndex(..) => {
+                true
+            }
+
+            ast::ExprCall(..) |
+            ast::ExprMethodCall(..) |
+            ast::ExprStruct(..) |
+            ast::ExprRange(..) |
+            ast::ExprTup(..) |
+            ast::ExprIf(..) |
+            ast::ExprMatch(..) |
+            ast::ExprClosure(..) |
+            ast::ExprBlock(..) |
+            ast::ExprRepeat(..) |
+            ast::ExprVec(..) |
+            ast::ExprBreak(..) |
+            ast::ExprAgain(..) |
+            ast::ExprRet(..) |
+            ast::ExprWhile(..) |
+            ast::ExprLoop(..) |
+            ast::ExprAssign(..) |
+            ast::ExprInlineAsm(..) |
+            ast::ExprAssignOp(..) |
+            ast::ExprLit(_) |
+            ast::ExprUnary(..) |
+            ast::ExprBox(..) |
+            ast::ExprAddrOf(..) |
+            ast::ExprBinary(..) |
+            ast::ExprCast(..) => {
+                false
+            }
 
-impl DtorKind {
-    pub fn is_present(&self) -> bool {
-        match *self {
-            TraitDtor(..) => true,
-            _ => false
+            ast::ExprParen(ref e) => self.expr_is_lval(e),
+
+            ast::ExprIfLet(..) |
+            ast::ExprWhileLet(..) |
+            ast::ExprForLoop(..) |
+            ast::ExprMac(..) => {
+                self.sess.span_bug(
+                    expr.span,
+                    "macro expression remains after expansion");
+            }
+        }
+    }
+
+    pub fn field_idx_strict(&self, name: ast::Name, fields: &[field])
+                            -> usize {
+        let mut i = 0;
+        for f in fields { if f.name == name { return i; } i += 1; }
+        self.sess.bug(&format!(
+            "no field named `{}` found in the list of fields `{:?}`",
+            token::get_name(name),
+            fields.iter()
+                  .map(|f| token::get_name(f.name).to_string())
+                  .collect::<Vec<String>>()));
+    }
+
+    pub fn note_and_explain_type_err(&self, err: &type_err<'tcx>, sp: Span) {
+        match *err {
+            terr_regions_does_not_outlive(subregion, superregion) => {
+                self.note_and_explain_region("", subregion, "...");
+                self.note_and_explain_region("...does not necessarily outlive ",
+                                           superregion, "");
+            }
+            terr_regions_not_same(region1, region2) => {
+                self.note_and_explain_region("", region1, "...");
+                self.note_and_explain_region("...is not the same lifetime as ",
+                                           region2, "");
+            }
+            terr_regions_no_overlap(region1, region2) => {
+                self.note_and_explain_region("", region1, "...");
+                self.note_and_explain_region("...does not overlap ",
+                                           region2, "");
+            }
+            terr_regions_insufficiently_polymorphic(_, conc_region) => {
+                self.note_and_explain_region("concrete lifetime that was found is ",
+                                           conc_region, "");
+            }
+            terr_regions_overly_polymorphic(_, ty::ReInfer(ty::ReVar(_))) => {
+                // don't bother to print out the message below for
+                // inference variables, it's not very illuminating.
+            }
+            terr_regions_overly_polymorphic(_, conc_region) => {
+                self.note_and_explain_region("expected concrete lifetime is ",
+                                           conc_region, "");
+            }
+            terr_sorts(values) => {
+                let expected_str = values.expected.sort_string(self);
+                let found_str = values.found.sort_string(self);
+                if expected_str == found_str && expected_str == "closure" {
+                    self.sess.span_note(sp,
+                        &format!("no two closures, even if identical, have the same type"));
+                    self.sess.span_help(sp,
+                        &format!("consider boxing your closure and/or \
+                                  using it as a trait object"));
+                }
+            }
+            _ => {}
         }
     }
 
-    pub fn has_drop_flag(&self) -> bool {
-        match self {
-            &NoDtor => false,
-            &TraitDtor(_, flag) => flag
+    pub fn provided_source(&self, id: ast::DefId) -> Option<ast::DefId> {
+        self.provided_method_sources.borrow().get(&id).cloned()
+    }
+
+    pub fn provided_trait_methods(&self, id: ast::DefId) -> Vec<Rc<Method<'tcx>>> {
+        if is_local(id) {
+            if let ItemTrait(_, _, _, ref ms) = self.map.expect_item(id.node).node {
+                ms.iter().filter_map(|ti| {
+                    if let ast::MethodTraitItem(_, Some(_)) = ti.node {
+                        match self.impl_or_trait_item(ast_util::local_def(ti.id)) {
+                            MethodTraitItem(m) => Some(m),
+                            _ => {
+                                self.sess.bug("provided_trait_methods(): \
+                                               non-method item found from \
+                                               looking up provided method?!")
+                            }
+                        }
+                    } else {
+                        None
+                    }
+                }).collect()
+            } else {
+                self.sess.bug(&format!("provided_trait_methods: `{:?}` is not a trait", id))
+            }
+        } else {
+            csearch::get_provided_trait_methods(self, id)
+        }
+    }
+
+    pub fn associated_consts(&self, id: ast::DefId) -> Vec<Rc<AssociatedConst<'tcx>>> {
+        if is_local(id) {
+            match self.map.expect_item(id.node).node {
+                ItemTrait(_, _, _, ref tis) => {
+                    tis.iter().filter_map(|ti| {
+                        if let ast::ConstTraitItem(_, _) = ti.node {
+                            match self.impl_or_trait_item(ast_util::local_def(ti.id)) {
+                                ConstTraitItem(ac) => Some(ac),
+                                _ => {
+                                    self.sess.bug("associated_consts(): \
+                                                   non-const item found from \
+                                                   looking up a constant?!")
+                                }
+                            }
+                        } else {
+                            None
+                        }
+                    }).collect()
+                }
+                ItemImpl(_, _, _, _, _, ref iis) => {
+                    iis.iter().filter_map(|ii| {
+                        if let ast::ConstImplItem(_, _) = ii.node {
+                            match self.impl_or_trait_item(ast_util::local_def(ii.id)) {
+                                ConstTraitItem(ac) => Some(ac),
+                                _ => {
+                                    self.sess.bug("associated_consts(): \
+                                                   non-const item found from \
+                                                   looking up a constant?!")
+                                }
+                            }
+                        } else {
+                            None
+                        }
+                    }).collect()
+                }
+                _ => {
+                    self.sess.bug(&format!("associated_consts: `{:?}` is not a trait \
+                                            or impl", id))
+                }
+            }
+        } else {
+            csearch::get_associated_consts(self, id)
         }
     }
-}
 
-/* If struct_id names a struct with a dtor. */
-pub fn ty_dtor(cx: &ctxt, struct_id: DefId) -> DtorKind {
-    match cx.destructor_for_type.borrow().get(&struct_id) {
-        Some(&method_def_id) => {
-            let flag = !has_attr(cx, struct_id, "unsafe_no_drop_flag");
+    pub fn trait_item(&self, trait_did: ast::DefId, idx: usize) -> ImplOrTraitItem<'tcx> {
+        let method_def_id = self.trait_item_def_ids(trait_did)[idx].def_id();
+        self.impl_or_trait_item(method_def_id)
+    }
 
-            TraitDtor(method_def_id, flag)
+    pub fn trait_items(&self, trait_did: ast::DefId) -> Rc<Vec<ImplOrTraitItem<'tcx>>> {
+        let mut trait_items = self.trait_items_cache.borrow_mut();
+        match trait_items.get(&trait_did).cloned() {
+            Some(trait_items) => trait_items,
+            None => {
+                let def_ids = self.trait_item_def_ids(trait_did);
+                let items: Rc<Vec<ImplOrTraitItem>> =
+                    Rc::new(def_ids.iter()
+                                   .map(|d| self.impl_or_trait_item(d.def_id()))
+                                   .collect());
+                trait_items.insert(trait_did, items.clone());
+                items
+            }
         }
-        None => NoDtor,
     }
-}
 
-pub fn has_dtor(cx: &ctxt, struct_id: DefId) -> bool {
-    cx.destructor_for_type.borrow().contains_key(&struct_id)
-}
-
-pub fn with_path<T, F>(cx: &ctxt, id: ast::DefId, f: F) -> T where
-    F: FnOnce(ast_map::PathElems) -> T,
-{
-    if id.krate == ast::LOCAL_CRATE {
-        cx.map.with_path(id.node, f)
-    } else {
-        f(csearch::get_item_path(cx, id).iter().cloned().chain(LinkedPath::empty()))
+    pub fn trait_impl_polarity(&self, id: ast::DefId) -> Option<ast::ImplPolarity> {
+        if id.krate == ast::LOCAL_CRATE {
+            match self.map.find(id.node) {
+                Some(ast_map::NodeItem(item)) => {
+                    match item.node {
+                        ast::ItemImpl(_, polarity, _, _, _, _) => Some(polarity),
+                        _ => None
+                    }
+                }
+                _ => None
+            }
+        } else {
+            csearch::get_impl_polarity(self, id)
+        }
     }
-}
 
-pub fn enum_is_univariant(cx: &ctxt, id: ast::DefId) -> bool {
-    enum_variants(cx, id).len() == 1
-}
+    pub fn custom_coerce_unsized_kind(&self, did: ast::DefId) -> CustomCoerceUnsized {
+        memoized(&self.custom_coerce_unsized_kinds, did, |did: DefId| {
+            let (kind, src) = if did.krate != ast::LOCAL_CRATE {
+                (csearch::get_custom_coerce_unsized_kind(self, did), "external")
+            } else {
+                (None, "local")
+            };
 
-pub fn type_is_empty(cx: &ctxt, ty: Ty) -> bool {
-    match ty.sty {
-       TyEnum(did, _) => (*enum_variants(cx, did)).is_empty(),
-       _ => false
-     }
-}
+            match kind {
+                Some(kind) => kind,
+                None => {
+                    self.sess.bug(&format!("custom_coerce_unsized_kind: \
+                                            {} impl `{}` is missing its kind",
+                                           src, self.item_path_str(did)));
+                }
+            }
+        })
+    }
 
-trait IntTypeExt {
-    fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx>;
-    fn i64_to_disr(&self, val: i64) -> Option<Disr>;
-    fn u64_to_disr(&self, val: u64) -> Option<Disr>;
-    fn disr_incr(&self, val: Disr) -> Option<Disr>;
-    fn disr_string(&self, val: Disr) -> String;
-    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr;
-}
+    pub fn impl_or_trait_item(&self, id: ast::DefId) -> ImplOrTraitItem<'tcx> {
+        lookup_locally_or_in_crate_store(
+            "impl_or_trait_items", id, &self.impl_or_trait_items,
+            || csearch::get_impl_or_trait_item(self, id))
+    }
 
-impl IntTypeExt for attr::IntType {
-    fn to_ty<'tcx>(&self, cx: &ctxt<'tcx>) -> Ty<'tcx> {
-        match *self {
-            SignedInt(ast::TyI8)      => cx.types.i8,
-            SignedInt(ast::TyI16)     => cx.types.i16,
-            SignedInt(ast::TyI32)     => cx.types.i32,
-            SignedInt(ast::TyI64)     => cx.types.i64,
-            SignedInt(ast::TyIs)   => cx.types.isize,
-            UnsignedInt(ast::TyU8)    => cx.types.u8,
-            UnsignedInt(ast::TyU16)   => cx.types.u16,
-            UnsignedInt(ast::TyU32)   => cx.types.u32,
-            UnsignedInt(ast::TyU64)   => cx.types.u64,
-            UnsignedInt(ast::TyUs) => cx.types.usize,
-        }
+    pub fn trait_item_def_ids(&self, id: ast::DefId) -> Rc<Vec<ImplOrTraitItemId>> {
+        lookup_locally_or_in_crate_store(
+            "trait_item_def_ids", id, &self.trait_item_def_ids,
+            || Rc::new(csearch::get_trait_item_def_ids(&self.sess.cstore, id)))
     }
 
-    fn i64_to_disr(&self, val: i64) -> Option<Disr> {
-        match *self {
-            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
-            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
-            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
-            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
-            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+    /// Returns the trait-ref corresponding to a given impl, or None if it is
+    /// an inherent impl.
+    pub fn impl_trait_ref(&self, id: ast::DefId) -> Option<TraitRef<'tcx>> {
+        lookup_locally_or_in_crate_store(
+            "impl_trait_refs", id, &self.impl_trait_refs,
+            || csearch::get_impl_trait(self, id))
+    }
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+    /// Returns whether this DefId refers to an impl
+    pub fn is_impl(&self, id: ast::DefId) -> bool {
+        if id.krate == ast::LOCAL_CRATE {
+            if let Some(ast_map::NodeItem(
+                &ast::Item { node: ast::ItemImpl(..), .. })) = self.map.find(id.node) {
+                true
+            } else {
+                false
+            }
+        } else {
+            csearch::is_impl(&self.sess.cstore, id)
         }
     }
 
-    fn u64_to_disr(&self, val: u64) -> Option<Disr> {
-        match *self {
-            SignedInt(ast::TyI8)    => val.to_i8()  .map(|v| v as Disr),
-            SignedInt(ast::TyI16)   => val.to_i16() .map(|v| v as Disr),
-            SignedInt(ast::TyI32)   => val.to_i32() .map(|v| v as Disr),
-            SignedInt(ast::TyI64)   => val.to_i64() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU8)  => val.to_u8()  .map(|v| v as Disr),
-            UnsignedInt(ast::TyU16) => val.to_u16() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU32) => val.to_u32() .map(|v| v as Disr),
-            UnsignedInt(ast::TyU64) => val.to_u64() .map(|v| v as Disr),
+    pub fn trait_ref_to_def_id(&self, tr: &ast::TraitRef) -> ast::DefId {
+        self.def_map.borrow().get(&tr.ref_id).expect("no def-map entry for trait").def_id()
+    }
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+    pub fn try_add_builtin_trait(&self,
+                                 trait_def_id: ast::DefId,
+                                 builtin_bounds: &mut EnumSet<BuiltinBound>)
+                                 -> bool
+    {
+        //! Checks whether `trait_ref` refers to one of the builtin
+        //! traits, like `Send`, and adds the corresponding
+        //! bound to the set `builtin_bounds` if so. Returns true if `trait_ref`
+        //! is a builtin trait.
+
+        match self.lang_items.to_builtin_kind(trait_def_id) {
+            Some(bound) => { builtin_bounds.insert(bound); true }
+            None => false
         }
     }
 
-    fn disr_incr(&self, val: Disr) -> Option<Disr> {
-        macro_rules! add1 {
-            ($e:expr) => { $e.and_then(|v|v.checked_add(1)).map(|v| v as Disr) }
-        }
-        match *self {
-            // SignedInt repr means we *want* to reinterpret the bits
-            // treating the highest bit of Disr as a sign-bit, so
-            // cast to i64 before range-checking.
-            SignedInt(ast::TyI8)    => add1!((val as i64).to_i8()),
-            SignedInt(ast::TyI16)   => add1!((val as i64).to_i16()),
-            SignedInt(ast::TyI32)   => add1!((val as i64).to_i32()),
-            SignedInt(ast::TyI64)   => add1!(Some(val as i64)),
+    pub fn substd_enum_variants(&self,
+                                id: ast::DefId,
+                                substs: &Substs<'tcx>)
+                                -> Vec<Rc<VariantInfo<'tcx>>> {
+        self.enum_variants(id).iter().map(|variant_info| {
+            let substd_args = variant_info.args.iter()
+                .map(|aty| aty.subst(self, substs)).collect::<Vec<_>>();
 
-            UnsignedInt(ast::TyU8)  => add1!(val.to_u8()),
-            UnsignedInt(ast::TyU16) => add1!(val.to_u16()),
-            UnsignedInt(ast::TyU32) => add1!(val.to_u32()),
-            UnsignedInt(ast::TyU64) => add1!(Some(val)),
+            let substd_ctor_ty = variant_info.ctor_ty.subst(self, substs);
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
-        }
+            Rc::new(VariantInfo {
+                args: substd_args,
+                ctor_ty: substd_ctor_ty,
+                ..(**variant_info).clone()
+            })
+        }).collect()
     }
 
-    // This returns a String because (1.) it is only used for
-    // rendering an error message and (2.) a string can represent the
-    // full range from `i64::MIN` through `u64::MAX`.
-    fn disr_string(&self, val: Disr) -> String {
-        match *self {
-            SignedInt(ast::TyI8)    => format!("{}", val as i8 ),
-            SignedInt(ast::TyI16)   => format!("{}", val as i16),
-            SignedInt(ast::TyI32)   => format!("{}", val as i32),
-            SignedInt(ast::TyI64)   => format!("{}", val as i64),
-            UnsignedInt(ast::TyU8)  => format!("{}", val as u8 ),
-            UnsignedInt(ast::TyU16) => format!("{}", val as u16),
-            UnsignedInt(ast::TyU32) => format!("{}", val as u32),
-            UnsignedInt(ast::TyU64) => format!("{}", val as u64),
+    pub fn item_path_str(&self, id: ast::DefId) -> String {
+        self.with_path(id, |path| ast_map::path_to_string(path))
+    }
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+    /* If struct_id names a struct with a dtor. */
+    pub fn ty_dtor(&self, struct_id: DefId) -> DtorKind {
+        match self.destructor_for_type.borrow().get(&struct_id) {
+            Some(&method_def_id) => {
+                let flag = !self.has_attr(struct_id, "unsafe_no_drop_flag");
+
+                TraitDtor(method_def_id, flag)
+            }
+            None => NoDtor,
         }
     }
 
-    fn disr_wrap_incr(&self, val: Option<Disr>) -> Disr {
-        macro_rules! add1 {
-            ($e:expr) => { ($e).wrapping_add(1) as Disr }
-        }
-        let val = val.unwrap_or(ty::INITIAL_DISCRIMINANT_VALUE);
-        match *self {
-            SignedInt(ast::TyI8)    => add1!(val as i8 ),
-            SignedInt(ast::TyI16)   => add1!(val as i16),
-            SignedInt(ast::TyI32)   => add1!(val as i32),
-            SignedInt(ast::TyI64)   => add1!(val as i64),
-            UnsignedInt(ast::TyU8)  => add1!(val as u8 ),
-            UnsignedInt(ast::TyU16) => add1!(val as u16),
-            UnsignedInt(ast::TyU32) => add1!(val as u32),
-            UnsignedInt(ast::TyU64) => add1!(val as u64),
+    pub fn has_dtor(&self, struct_id: DefId) -> bool {
+        self.destructor_for_type.borrow().contains_key(&struct_id)
+    }
 
-            UnsignedInt(ast::TyUs) |
-            SignedInt(ast::TyIs) => unreachable!(),
+    pub fn with_path<T, F>(&self, id: ast::DefId, f: F) -> T where
+        F: FnOnce(ast_map::PathElems) -> T,
+    {
+        if id.krate == ast::LOCAL_CRATE {
+            self.map.with_path(id.node, f)
+        } else {
+            f(csearch::get_item_path(self, id).iter().cloned().chain(LinkedPath::empty()))
         }
     }
-}
 
-/// Returns `(normalized_type, ty)`, where `normalized_type` is the
-/// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8},
-/// and `ty` is the original type (i.e. may include `isize` or
-/// `usize`).
-pub fn enum_repr_type<'tcx>(cx: &ctxt<'tcx>,
-                            opt_hint: Option<&attr::ReprAttr>)
-                            -> (attr::IntType, Ty<'tcx>)
-{
-    let repr_type = match opt_hint {
-        // Feed in the given type
-        Some(&attr::ReprInt(_, int_t)) => int_t,
-        // ... but provide sensible default if none provided
-        //
-        // NB. Historically `fn enum_variants` generate i64 here, while
-        // rustc_typeck::check would generate isize.
-        _ => SignedInt(ast::TyIs),
-    };
-
-    let repr_type_ty = repr_type.to_ty(cx);
-    let repr_type = match repr_type {
-        SignedInt(ast::TyIs) =>
-            SignedInt(cx.sess.target.int_type),
-        UnsignedInt(ast::TyUs) =>
-            UnsignedInt(cx.sess.target.uint_type),
-        other => other
-    };
-
-    (repr_type, repr_type_ty)
-}
-
-fn report_discrim_overflow(cx: &ctxt,
-                           variant_span: Span,
-                           variant_name: &str,
-                           repr_type: attr::IntType,
-                           prev_val: Disr) {
-    let computed_value = repr_type.disr_wrap_incr(Some(prev_val));
-    let computed_value = repr_type.disr_string(computed_value);
-    let prev_val = repr_type.disr_string(prev_val);
-    let repr_type = repr_type.to_ty(cx);
-    span_err!(cx.sess, variant_span, E0370,
-              "enum discriminant overflowed on value after {}: {}; \
-               set explicitly via {} = {} if that is desired outcome",
-              prev_val, repr_type, variant_name, computed_value);
-}
-
-// This computes the discriminant values for the sequence of Variants
-// attached to a particular enum, taking into account the #[repr] (if
-// any) provided via the `opt_hint`.
-fn compute_enum_variants<'tcx>(cx: &ctxt<'tcx>,
-                               vs: &'tcx [P<ast::Variant>],
-                               opt_hint: Option<&attr::ReprAttr>)
-                               -> Vec<Rc<ty::VariantInfo<'tcx>>> {
-    let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
-    let mut prev_disr_val: Option<ty::Disr> = None;
-
-    let (repr_type, repr_type_ty) = ty::enum_repr_type(cx, opt_hint);
-
-    for v in vs {
-        // If the discriminant value is specified explicitly in the
-        // enum, check whether the initialization expression is valid,
-        // otherwise use the last value plus one.
-        let current_disr_val;
-
-        // This closure marks cases where, when an error occurs during
-        // the computation, attempt to assign a (hopefully) fresh
-        // value to avoid spurious error reports downstream.
-        let attempt_fresh_value = move || -> Disr {
-            repr_type.disr_wrap_incr(prev_disr_val)
+    pub fn enum_is_univariant(&self, id: ast::DefId) -> bool {
+        self.enum_variants(id).len() == 1
+    }
+
+    /// Returns `(normalized_type, ty)`, where `normalized_type` is the
+    /// IntType representation of one of {i64,i32,i16,i8,u64,u32,u16,u8},
+    /// and `ty` is the original type (i.e. may include `isize` or
+    /// `usize`).
+    pub fn enum_repr_type(&self, opt_hint: Option<&attr::ReprAttr>)
+                          -> (attr::IntType, Ty<'tcx>) {
+        let repr_type = match opt_hint {
+            // Feed in the given type
+            Some(&attr::ReprInt(_, int_t)) => int_t,
+            // ... but provide sensible default if none provided
+            //
+            // NB. Historically `fn enum_variants` generate i64 here, while
+            // rustc_typeck::check would generate isize.
+            _ => SignedInt(ast::TyIs),
         };
 
-        match v.node.disr_expr {
-            Some(ref e) => {
-                debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
-
-                // check_expr (from check_const pass) doesn't guarantee
-                // that the expression is in a form that eval_const_expr can
-                // handle, so we may still get an internal compiler error
-                //
-                // pnkfelix: The above comment was transcribed from
-                // the version of this code taken from rustc_typeck.
-                // Presumably the implication is that we need to deal
-                // with such ICE's as they arise.
-                //
-                // Since this can be called from `ty::enum_variants`
-                // anyway, best thing is to make `eval_const_expr`
-                // more robust (on case-by-case basis).
-
-                match const_eval::eval_const_expr_partial(cx, &**e, Some(repr_type_ty)) {
-                    Ok(ConstVal::Int(val)) => current_disr_val = val as Disr,
-                    Ok(ConstVal::Uint(val)) => current_disr_val = val as Disr,
-                    Ok(_) => {
-                        let sign_desc = if repr_type.is_signed() { "signed" } else { "unsigned" };
-                        span_err!(cx.sess, e.span, E0079,
-                                  "expected {} integer constant",
-                                  sign_desc);
-                        current_disr_val = attempt_fresh_value();
-                    }
-                    Err(ref err) => {
-                        span_err!(cx.sess, err.span, E0080,
-                                  "constant evaluation error: {}",
-                                  err.description());
-                        current_disr_val = attempt_fresh_value();
+        let repr_type_ty = repr_type.to_ty(self);
+        let repr_type = match repr_type {
+            SignedInt(ast::TyIs) =>
+                SignedInt(self.sess.target.int_type),
+            UnsignedInt(ast::TyUs) =>
+                UnsignedInt(self.sess.target.uint_type),
+            other => other
+        };
+
+        (repr_type, repr_type_ty)
+    }
+
+    fn report_discrim_overflow(&self,
+                               variant_span: Span,
+                               variant_name: &str,
+                               repr_type: attr::IntType,
+                               prev_val: Disr) {
+        let computed_value = repr_type.disr_wrap_incr(Some(prev_val));
+        let computed_value = repr_type.disr_string(computed_value);
+        let prev_val = repr_type.disr_string(prev_val);
+        let repr_type = repr_type.to_ty(self);
+        span_err!(self.sess, variant_span, E0370,
+                  "enum discriminant overflowed on value after {}: {}; \
+                   set explicitly via {} = {} if that is desired outcome",
+                  prev_val, repr_type, variant_name, computed_value);
+    }
+
+    // This computes the discriminant values for the sequence of Variants
+    // attached to a particular enum, taking into account the #[repr] (if
+    // any) provided via the `opt_hint`.
+    fn compute_enum_variants(&self,
+                             vs: &'tcx [P<ast::Variant>],
+                             opt_hint: Option<&attr::ReprAttr>)
+                             -> Vec<Rc<ty::VariantInfo<'tcx>>> {
+        let mut variants: Vec<Rc<ty::VariantInfo>> = Vec::new();
+        let mut prev_disr_val: Option<ty::Disr> = None;
+
+        let (repr_type, repr_type_ty) = self.enum_repr_type(opt_hint);
+
+        for v in vs {
+            // If the discriminant value is specified explicitly in the
+            // enum, check whether the initialization expression is valid,
+            // otherwise use the last value plus one.
+            let current_disr_val;
+
+            // This closure marks cases where, when an error occurs during
+            // the computation, attempt to assign a (hopefully) fresh
+            // value to avoid spurious error reports downstream.
+            let attempt_fresh_value = move || -> Disr {
+                repr_type.disr_wrap_incr(prev_disr_val)
+            };
+
+            match v.node.disr_expr {
+                Some(ref e) => {
+                    debug!("disr expr, checking {}", pprust::expr_to_string(&**e));
+
+                    // check_expr (from check_const pass) doesn't guarantee
+                    // that the expression is in a form that eval_const_expr can
+                    // handle, so we may still get an internal compiler error
+                    //
+                    // pnkfelix: The above comment was transcribed from
+                    // the version of this code taken from rustc_typeck.
+                    // Presumably the implication is that we need to deal
+                    // with such ICE's as they arise.
+                    //
+                    // Since this can be called from `ty::enum_variants`
+                    // anyway, best thing is to make `eval_const_expr`
+                    // more robust (on case-by-case basis).
+
+                    match const_eval::eval_const_expr_partial(self, &**e, Some(repr_type_ty)) {
+                        Ok(ConstVal::Int(val)) => current_disr_val = val as Disr,
+                        Ok(ConstVal::Uint(val)) => current_disr_val = val as Disr,
+                        Ok(_) => {
+                            let sign_desc = if repr_type.is_signed() {
+                                "signed"
+                            } else {
+                                "unsigned"
+                            };
+                            span_err!(self.sess, e.span, E0079,
+                                      "expected {} integer constant",
+                                      sign_desc);
+                            current_disr_val = attempt_fresh_value();
+                        }
+                        Err(ref err) => {
+                            span_err!(self.sess, err.span, E0080,
+                                      "constant evaluation error: {}",
+                                      err.description());
+                            current_disr_val = attempt_fresh_value();
+                        }
                     }
-                }
-            },
-            None => {
-                current_disr_val = match prev_disr_val {
-                    Some(prev_disr_val) => {
-                        if let Some(v) = repr_type.disr_incr(prev_disr_val) {
-                            v
-                        } else {
-                            report_discrim_overflow(cx, v.span, v.node.name.as_str(),
-                                                    repr_type, prev_disr_val);
-                            attempt_fresh_value()
+                },
+                None => {
+                    current_disr_val = match prev_disr_val {
+                        Some(prev_disr_val) => {
+                            if let Some(v) = repr_type.disr_incr(prev_disr_val) {
+                                v
+                            } else {
+                                self.report_discrim_overflow(v.span, v.node.name.as_str(),
+                                                             repr_type, prev_disr_val);
+                                attempt_fresh_value()
+                            }
                         }
+                        None => ty::INITIAL_DISCRIMINANT_VALUE
                     }
-                    None => ty::INITIAL_DISCRIMINANT_VALUE
                 }
             }
-        }
 
-        let variant_info = Rc::new(VariantInfo::from_ast_variant(cx, &**v, current_disr_val));
-        prev_disr_val = Some(current_disr_val);
+            let variant_info = Rc::new(VariantInfo::from_ast_variant(self, &**v, current_disr_val));
+            prev_disr_val = Some(current_disr_val);
 
-        variants.push(variant_info);
-    }
+            variants.push(variant_info);
+        }
 
-    return variants;
-}
+        variants
+    }
 
-pub fn enum_variants<'tcx>(cx: &ctxt<'tcx>, id: ast::DefId)
-                           -> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
-    memoized(&cx.enum_var_cache, id, |id: ast::DefId| {
-        if ast::LOCAL_CRATE != id.krate {
-            Rc::new(csearch::get_enum_variants(cx, id))
-        } else {
-            match cx.map.get(id.node) {
-                ast_map::NodeItem(ref item) => {
-                    match item.node {
-                        ast::ItemEnum(ref enum_definition, _) => {
-                            Rc::new(compute_enum_variants(
-                                cx,
-                                &enum_definition.variants,
-                                lookup_repr_hints(cx, id).get(0)))
-                        }
-                        _ => {
-                            cx.sess.bug("enum_variants: id not bound to an enum")
+    pub fn enum_variants(&self, id: ast::DefId) -> Rc<Vec<Rc<VariantInfo<'tcx>>>> {
+        memoized(&self.enum_var_cache, id, |id: ast::DefId| {
+            if ast::LOCAL_CRATE != id.krate {
+                Rc::new(csearch::get_enum_variants(self, id))
+            } else {
+                match self.map.get(id.node) {
+                    ast_map::NodeItem(ref item) => {
+                        match item.node {
+                            ast::ItemEnum(ref enum_definition, _) => {
+                                Rc::new(self.compute_enum_variants(
+                                    &enum_definition.variants,
+                                    self.lookup_repr_hints(id).get(0)))
+                            }
+                            _ => {
+                                self.sess.bug("enum_variants: id not bound to an enum")
+                            }
                         }
                     }
+                    _ => self.sess.bug("enum_variants: id not bound to an enum")
                 }
-                _ => cx.sess.bug("enum_variants: id not bound to an enum")
             }
-        }
-    })
-}
+        })
+    }
 
-// Returns information about the enum variant with the given ID:
-pub fn enum_variant_with_id<'tcx>(cx: &ctxt<'tcx>,
-                                  enum_id: ast::DefId,
-                                  variant_id: ast::DefId)
-                                  -> Rc<VariantInfo<'tcx>> {
-    enum_variants(cx, enum_id).iter()
-                              .find(|variant| variant.id == variant_id)
-                              .expect("enum_variant_with_id(): no variant exists with that ID")
-                              .clone()
-}
+    // Returns information about the enum variant with the given ID:
+    pub fn enum_variant_with_id(&self,
+                                enum_id: ast::DefId,
+                                variant_id: ast::DefId)
+                                -> Rc<VariantInfo<'tcx>> {
+        self.enum_variants(enum_id).iter()
+                                   .find(|variant| variant.id == variant_id)
+                                   .expect("enum_variant_with_id(): no variant exists with that ID")
+                                   .clone()
+    }
 
 
-// If the given item is in an external crate, looks up its type and adds it to
-// the type cache. Returns the type parameters and type.
-pub fn lookup_item_type<'tcx>(cx: &ctxt<'tcx>,
-                              did: ast::DefId)
-                              -> TypeScheme<'tcx> {
-    lookup_locally_or_in_crate_store(
-        "tcache", did, &cx.tcache,
-        || csearch::get_type(cx, did))
-}
+    // If the given item is in an external crate, looks up its type and adds it to
+    // the type cache. Returns the type parameters and type.
+    pub fn lookup_item_type(&self, did: ast::DefId) -> TypeScheme<'tcx> {
+        lookup_locally_or_in_crate_store(
+            "tcache", did, &self.tcache,
+            || csearch::get_type(self, did))
+    }
 
-/// Given the did of a trait, returns its canonical trait ref.
-pub fn lookup_trait_def<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
-                              -> &'tcx TraitDef<'tcx> {
-    lookup_locally_or_in_crate_store(
-        "trait_defs", did, &cx.trait_defs,
-        || cx.arenas.trait_defs.alloc(csearch::get_trait_def(cx, did))
-    )
-}
+    /// Given the did of a trait, returns its canonical trait ref.
+    pub fn lookup_trait_def(&self, did: ast::DefId) -> &'tcx TraitDef<'tcx> {
+        lookup_locally_or_in_crate_store(
+            "trait_defs", did, &self.trait_defs,
+            || self.arenas.trait_defs.alloc(csearch::get_trait_def(self, did))
+        )
+    }
 
-/// Given the did of an item, returns its full set of predicates.
-pub fn lookup_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
-                                -> GenericPredicates<'tcx>
-{
-    lookup_locally_or_in_crate_store(
-        "predicates", did, &cx.predicates,
-        || csearch::get_predicates(cx, did))
-}
+    /// Given the did of an item, returns its full set of predicates.
+    pub fn lookup_predicates(&self, did: ast::DefId) -> GenericPredicates<'tcx> {
+        lookup_locally_or_in_crate_store(
+            "predicates", did, &self.predicates,
+            || csearch::get_predicates(self, did))
+    }
 
-/// Given the did of a trait, returns its superpredicates.
-pub fn lookup_super_predicates<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId)
-                                     -> GenericPredicates<'tcx>
-{
-    lookup_locally_or_in_crate_store(
-        "super_predicates", did, &cx.super_predicates,
-        || csearch::get_super_predicates(cx, did))
-}
+    /// Given the did of a trait, returns its superpredicates.
+    pub fn lookup_super_predicates(&self, did: ast::DefId) -> GenericPredicates<'tcx> {
+        lookup_locally_or_in_crate_store(
+            "super_predicates", did, &self.super_predicates,
+            || csearch::get_super_predicates(self, did))
+    }
 
-/// Get the attributes of a definition.
-pub fn get_attrs<'tcx>(tcx: &'tcx ctxt, did: DefId)
-                       -> Cow<'tcx, [ast::Attribute]> {
-    if is_local(did) {
-        Cow::Borrowed(tcx.map.attrs(did.node))
-    } else {
-        Cow::Owned(csearch::get_item_attrs(&tcx.sess.cstore, did))
+    /// Get the attributes of a definition.
+    pub fn get_attrs(&self, did: DefId) -> Cow<'tcx, [ast::Attribute]> {
+        if is_local(did) {
+            Cow::Borrowed(self.map.attrs(did.node))
+        } else {
+            Cow::Owned(csearch::get_item_attrs(&self.sess.cstore, did))
+        }
     }
-}
 
-/// Determine whether an item is annotated with an attribute
-pub fn has_attr(tcx: &ctxt, did: DefId, attr: &str) -> bool {
-    get_attrs(tcx, did).iter().any(|item| item.check_name(attr))
-}
+    /// Determine whether an item is annotated with an attribute
+    pub fn has_attr(&self, did: DefId, attr: &str) -> bool {
+        self.get_attrs(did).iter().any(|item| item.check_name(attr))
+    }
 
-/// Determine whether an item is annotated with `#[repr(packed)]`
-pub fn lookup_packed(tcx: &ctxt, did: DefId) -> bool {
-    lookup_repr_hints(tcx, did).contains(&attr::ReprPacked)
-}
+    /// Determine whether an item is annotated with `#[repr(packed)]`
+    pub fn lookup_packed(&self, did: DefId) -> bool {
+        self.lookup_repr_hints(did).contains(&attr::ReprPacked)
+    }
 
-/// Determine whether an item is annotated with `#[simd]`
-pub fn lookup_simd(tcx: &ctxt, did: DefId) -> bool {
-    has_attr(tcx, did, "simd")
-}
+    /// Determine whether an item is annotated with `#[simd]`
+    pub fn lookup_simd(&self, did: DefId) -> bool {
+        self.has_attr(did, "simd")
+    }
 
-/// Obtain the representation annotation for a struct definition.
-pub fn lookup_repr_hints(tcx: &ctxt, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
-    memoized(&tcx.repr_hint_cache, did, |did: DefId| {
-        Rc::new(if did.krate == LOCAL_CRATE {
-            get_attrs(tcx, did).iter().flat_map(|meta| {
-                attr::find_repr_attrs(tcx.sess.diagnostic(), meta).into_iter()
-            }).collect()
-        } else {
-            csearch::get_repr_attrs(&tcx.sess.cstore, did)
+    /// Obtain the representation annotation for a struct definition.
+    pub fn lookup_repr_hints(&self, did: DefId) -> Rc<Vec<attr::ReprAttr>> {
+        memoized(&self.repr_hint_cache, did, |did: DefId| {
+            Rc::new(if did.krate == LOCAL_CRATE {
+                self.get_attrs(did).iter().flat_map(|meta| {
+                    attr::find_repr_attrs(self.sess.diagnostic(), meta).into_iter()
+                }).collect()
+            } else {
+                csearch::get_repr_attrs(&self.sess.cstore, did)
+            })
         })
-    })
-}
+    }
 
-// Look up a field ID, whether or not it's local
-pub fn lookup_field_type_unsubstituted<'tcx>(tcx: &ctxt<'tcx>,
-                                             struct_id: DefId,
-                                             id: DefId)
-                                             -> Ty<'tcx> {
-    if id.krate == ast::LOCAL_CRATE {
-        node_id_to_type(tcx, id.node)
-    } else {
-        let mut tcache = tcx.tcache.borrow_mut();
-        tcache.entry(id).or_insert_with(|| csearch::get_field_type(tcx, struct_id, id)).ty
+    // Look up a field ID, whether or not it's local
+    pub fn lookup_field_type_unsubstituted(&self,
+                                           struct_id: DefId,
+                                           id: DefId)
+                                           -> Ty<'tcx> {
+        if id.krate == ast::LOCAL_CRATE {
+            self.node_id_to_type(id.node)
+        } else {
+            let mut tcache = self.tcache.borrow_mut();
+            tcache.entry(id).or_insert_with(|| csearch::get_field_type(self, struct_id, id)).ty
+        }
     }
-}
 
 
-// Look up a field ID, whether or not it's local
-// Takes a list of type substs in case the struct is generic
-pub fn lookup_field_type<'tcx>(tcx: &ctxt<'tcx>,
-                               struct_id: DefId,
-                               id: DefId,
-                               substs: &Substs<'tcx>)
-                               -> Ty<'tcx> {
-    lookup_field_type_unsubstituted(tcx, struct_id, id).subst(tcx, substs)
-}
+    // Look up a field ID, whether or not it's local
+    // Takes a list of type substs in case the struct is generic
+    pub fn lookup_field_type(&self,
+                             struct_id: DefId,
+                             id: DefId,
+                             substs: &Substs<'tcx>)
+                             -> Ty<'tcx> {
+        self.lookup_field_type_unsubstituted(struct_id, id).subst(self, substs)
+    }
 
-// Look up the list of field names and IDs for a given struct.
-// Panics if the id is not bound to a struct.
-pub fn lookup_struct_fields(cx: &ctxt, did: ast::DefId) -> Vec<field_ty> {
-    if did.krate == ast::LOCAL_CRATE {
-        let struct_fields = cx.struct_fields.borrow();
-        match struct_fields.get(&did) {
-            Some(fields) => (**fields).clone(),
-            _ => {
-                cx.sess.bug(
-                    &format!("ID not mapped to struct fields: {}",
-                            cx.map.node_to_string(did.node)));
+    // Look up the list of field names and IDs for a given struct.
+    // Panics if the id is not bound to a struct.
+    pub fn lookup_struct_fields(&self, did: ast::DefId) -> Vec<field_ty> {
+        if did.krate == ast::LOCAL_CRATE {
+            let struct_fields = self.struct_fields.borrow();
+            match struct_fields.get(&did) {
+                Some(fields) => (**fields).clone(),
+                _ => {
+                    self.sess.bug(
+                        &format!("ID not mapped to struct fields: {}",
+                                self.map.node_to_string(did.node)));
+                }
             }
+        } else {
+            csearch::get_struct_fields(&self.sess.cstore, did)
         }
-    } else {
-        csearch::get_struct_fields(&cx.sess.cstore, did)
     }
-}
 
-pub fn is_tuple_struct(cx: &ctxt, did: ast::DefId) -> bool {
-    let fields = lookup_struct_fields(cx, did);
-    !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field)
-}
+    pub fn is_tuple_struct(&self, did: ast::DefId) -> bool {
+        let fields = self.lookup_struct_fields(did);
+        !fields.is_empty() && fields.iter().all(|f| f.name == token::special_names::unnamed_field)
+    }
 
-// Returns a list of fields corresponding to the struct's items. trans uses
-// this. Takes a list of substs with which to instantiate field types.
-pub fn struct_fields<'tcx>(cx: &ctxt<'tcx>, did: ast::DefId, substs: &Substs<'tcx>)
-                           -> Vec<field<'tcx>> {
-    lookup_struct_fields(cx, did).iter().map(|f| {
-       field {
-            name: f.name,
-            mt: mt {
-                ty: lookup_field_type(cx, did, f.id, substs),
-                mutbl: MutImmutable
+    // Returns a list of fields corresponding to the struct's items. trans uses
+    // this. Takes a list of substs with which to instantiate field types.
+    pub fn struct_fields(&self, did: ast::DefId, substs: &Substs<'tcx>)
+                         -> Vec<field<'tcx>> {
+        self.lookup_struct_fields(did).iter().map(|f| {
+           field {
+                name: f.name,
+                mt: mt {
+                    ty: self.lookup_field_type(did, f.id, substs),
+                    mutbl: MutImmutable
+                }
             }
-        }
-    }).collect()
-}
+        }).collect()
+    }
 
-// Returns a list of fields corresponding to the tuple's items. trans uses
-// this.
-pub fn tup_fields<'tcx>(v: &[Ty<'tcx>]) -> Vec<field<'tcx>> {
-    v.iter().enumerate().map(|(i, &f)| {
-       field {
-            name: token::intern(&i.to_string()),
-            mt: mt {
-                ty: f,
-                mutbl: MutImmutable
+    /// Returns the deeply last field of nested structures, or the same type,
+    /// if not a structure at all. Corresponds to the only possible unsized
+    /// field, and its type can be used to determine unsizing strategy.
+    pub fn struct_tail(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
+        while let TyStruct(def_id, substs) = ty.sty {
+            match self.struct_fields(def_id, substs).last() {
+                Some(f) => ty = f.mt.ty,
+                None => break
             }
         }
-    }).collect()
-}
-
-/// Returns the deeply last field of nested structures, or the same type,
-/// if not a structure at all. Corresponds to the only possible unsized
-/// field, and its type can be used to determine unsizing strategy.
-pub fn struct_tail<'tcx>(cx: &ctxt<'tcx>, mut ty: Ty<'tcx>) -> Ty<'tcx> {
-    while let TyStruct(def_id, substs) = ty.sty {
-        match struct_fields(cx, def_id, substs).last() {
-            Some(f) => ty = f.mt.ty,
-            None => break
-        }
+        ty
     }
-    ty
-}
 
-/// Same as applying struct_tail on `source` and `target`, but only
-/// keeps going as long as the two types are instances of the same
-/// structure definitions.
-/// For `(Foo<Foo<T>>, Foo<Trait>)`, the result will be `(Foo<T>, Trait)`,
-/// whereas struct_tail produces `T`, and `Trait`, respectively.
-pub fn struct_lockstep_tails<'tcx>(cx: &ctxt<'tcx>,
-                                   source: Ty<'tcx>,
-                                   target: Ty<'tcx>)
-                                   -> (Ty<'tcx>, Ty<'tcx>) {
-    let (mut a, mut b) = (source, target);
-    while let (&TyStruct(a_did, a_substs), &TyStruct(b_did, b_substs)) = (&a.sty, &b.sty) {
-        if a_did != b_did {
-            continue;
-        }
-        if let Some(a_f) = struct_fields(cx, a_did, a_substs).last() {
-            if let Some(b_f) = struct_fields(cx, b_did, b_substs).last() {
-                a = a_f.mt.ty;
-                b = b_f.mt.ty;
+    /// Same as applying struct_tail on `source` and `target`, but only
+    /// keeps going as long as the two types are instances of the same
+    /// structure definitions.
+    /// For `(Foo<Foo<T>>, Foo<Trait>)`, the result will be `(Foo<T>, Trait)`,
+    /// whereas struct_tail produces `T`, and `Trait`, respectively.
+    pub fn struct_lockstep_tails(&self,
+                                 source: Ty<'tcx>,
+                                 target: Ty<'tcx>)
+                                 -> (Ty<'tcx>, Ty<'tcx>) {
+        let (mut a, mut b) = (source, target);
+        while let (&TyStruct(a_did, a_substs), &TyStruct(b_did, b_substs)) = (&a.sty, &b.sty) {
+            if a_did != b_did {
+                break;
+            }
+            if let Some(a_f) = self.struct_fields(a_did, a_substs).last() {
+                if let Some(b_f) = self.struct_fields(b_did, b_substs).last() {
+                    a = a_f.mt.ty;
+                    b = b_f.mt.ty;
+                } else {
+                    break;
+                }
             } else {
                 break;
             }
-        } else {
-            break;
         }
+        (a, b)
     }
-    (a, b)
-}
 
-#[derive(Copy, Clone)]
-pub struct ClosureUpvar<'tcx> {
-    pub def: def::Def,
-    pub span: Span,
-    pub ty: Ty<'tcx>,
-}
+    // Returns a list of `ClosureUpvar`s for each upvar.
+    pub fn closure_upvars(typer: &Typer<'tcx>,
+                          closure_id: ast::DefId,
+                          substs: &Substs<'tcx>)
+                          -> Option<Vec<ClosureUpvar<'tcx>>>
+    {
+        // Presently an unboxed closure type cannot "escape" out of a
+        // function, so we will only encounter ones that originated in the
+        // local crate or were inlined into it along with some function.
+        // This may change if abstract return types of some sort are
+        // implemented.
+        assert!(closure_id.krate == ast::LOCAL_CRATE);
+        let tcx = typer.tcx();
+        match tcx.freevars.borrow().get(&closure_id.node) {
+            None => Some(vec![]),
+            Some(ref freevars) => {
+                freevars.iter()
+                        .map(|freevar| {
+                            let freevar_def_id = freevar.def.def_id();
+                            let freevar_ty = match typer.node_ty(freevar_def_id.node) {
+                                Ok(t) => { t }
+                                Err(()) => { return None; }
+                            };
+                            let freevar_ty = freevar_ty.subst(tcx, substs);
 
-// Returns a list of `ClosureUpvar`s for each upvar.
-pub fn closure_upvars<'tcx>(typer: &mc::Typer<'tcx>,
-                            closure_id: ast::DefId,
-                            substs: &Substs<'tcx>)
-                            -> Option<Vec<ClosureUpvar<'tcx>>>
-{
-    // Presently an unboxed closure type cannot "escape" out of a
-    // function, so we will only encounter ones that originated in the
-    // local crate or were inlined into it along with some function.
-    // This may change if abstract return types of some sort are
-    // implemented.
-    assert!(closure_id.krate == ast::LOCAL_CRATE);
-    let tcx = typer.tcx();
-    match tcx.freevars.borrow().get(&closure_id.node) {
-        None => Some(vec![]),
-        Some(ref freevars) => {
-            freevars.iter()
-                    .map(|freevar| {
-                        let freevar_def_id = freevar.def.def_id();
-                        let freevar_ty = match typer.node_ty(freevar_def_id.node) {
-                            Ok(t) => { t }
-                            Err(()) => { return None; }
-                        };
-                        let freevar_ty = freevar_ty.subst(tcx, substs);
-
-                        let upvar_id = ty::UpvarId {
-                            var_id: freevar_def_id.node,
-                            closure_expr_id: closure_id.node
-                        };
-
-                        typer.upvar_capture(upvar_id).map(|capture| {
-                            let freevar_ref_ty = match capture {
-                                UpvarCapture::ByValue => {
-                                    freevar_ty
-                                }
-                                UpvarCapture::ByRef(borrow) => {
-                                    mk_rptr(tcx,
-                                            tcx.mk_region(borrow.region),
+                            let upvar_id = ty::UpvarId {
+                                var_id: freevar_def_id.node,
+                                closure_expr_id: closure_id.node
+                            };
+
+                            typer.upvar_capture(upvar_id).map(|capture| {
+                                let freevar_ref_ty = match capture {
+                                    UpvarCapture::ByValue => {
+                                        freevar_ty
+                                    }
+                                    UpvarCapture::ByRef(borrow) => {
+                                        tcx.mk_ref(tcx.mk_region(borrow.region),
                                             ty::mt {
                                                 ty: freevar_ty,
                                                 mutbl: borrow.kind.to_mutbl_lossy(),
                                             })
-                                }
-                            };
+                                    }
+                                };
 
-                            ClosureUpvar {
-                                def: freevar.def,
-                                span: freevar.span,
-                                ty: freevar_ref_ty,
-                            }
+                                ClosureUpvar {
+                                    def: freevar.def,
+                                    span: freevar.span,
+                                    ty: freevar_ref_ty,
+                                }
+                            })
                         })
-                    })
-                    .collect()
-        }
-    }
-}
-
-// Returns the repeat count for a repeating vector expression.
-pub fn eval_repeat_count(tcx: &ctxt, count_expr: &ast::Expr) -> usize {
-    match const_eval::eval_const_expr_partial(tcx, count_expr, Some(tcx.types.usize)) {
-        Ok(val) => {
-            let found = match val {
-                ConstVal::Uint(count) => return count as usize,
-                ConstVal::Int(count) if count >= 0 => return count as usize,
-                ConstVal::Int(_) => "negative integer",
-                ConstVal::Float(_) => "float",
-                ConstVal::Str(_) => "string",
-                ConstVal::Bool(_) => "boolean",
-                ConstVal::Binary(_) => "binary array",
-                ConstVal::Struct(..) => "struct",
-                ConstVal::Tuple(_) => "tuple"
-            };
-            span_err!(tcx.sess, count_expr.span, E0306,
-                "expected positive integer for repeat count, found {}",
-                found);
-        }
-        Err(err) => {
-            let err_description = err.description();
-            let found = match count_expr.node {
-                ast::ExprPath(None, ast::Path {
-                    global: false,
-                    ref segments,
-                    ..
-                }) if segments.len() == 1 =>
-                    format!("{}", "found variable"),
-                _ =>
-                    format!("but {}", err_description),
-            };
-            span_err!(tcx.sess, count_expr.span, E0307,
-                "expected constant integer for repeat count, {}",
-                found);
+                        .collect()
+            }
         }
     }
-    0
-}
 
-// Iterate over a type parameter's bounded traits and any supertraits
-// of those traits, ignoring kinds.
-// Here, the supertraits are the transitive closure of the supertrait
-// relation on the supertraits from each bounded trait's constraint
-// list.
-pub fn each_bound_trait_and_supertraits<'tcx, F>(tcx: &ctxt<'tcx>,
-                                                 bounds: &[PolyTraitRef<'tcx>],
-                                                 mut f: F)
-                                                 -> bool where
-    F: FnMut(PolyTraitRef<'tcx>) -> bool,
-{
-    for bound_trait_ref in traits::transitive_bounds(tcx, bounds) {
-        if !f(bound_trait_ref) {
-            return false;
+    // Returns the repeat count for a repeating vector expression.
+    pub fn eval_repeat_count(&self, count_expr: &ast::Expr) -> usize {
+        match const_eval::eval_const_expr_partial(self, count_expr, Some(self.types.usize)) {
+            Ok(val) => {
+                let found = match val {
+                    ConstVal::Uint(count) => return count as usize,
+                    ConstVal::Int(count) if count >= 0 => return count as usize,
+                    ConstVal::Int(_) => "negative integer",
+                    ConstVal::Float(_) => "float",
+                    ConstVal::Str(_) => "string",
+                    ConstVal::Bool(_) => "boolean",
+                    ConstVal::Binary(_) => "binary array",
+                    ConstVal::Struct(..) => "struct",
+                    ConstVal::Tuple(_) => "tuple"
+                };
+                span_err!(self.sess, count_expr.span, E0306,
+                    "expected positive integer for repeat count, found {}",
+                    found);
+            }
+            Err(err) => {
+                let err_description = err.description();
+                let found = match count_expr.node {
+                    ast::ExprPath(None, ast::Path {
+                        global: false,
+                        ref segments,
+                        ..
+                    }) if segments.len() == 1 =>
+                        format!("{}", "found variable"),
+                    _ =>
+                        format!("but {}", err_description),
+                };
+                span_err!(self.sess, count_expr.span, E0307,
+                    "expected constant integer for repeat count, {}",
+                    found);
+            }
         }
+        0
     }
-    return true;
-}
 
-/// Given a set of predicates that apply to an object type, returns
-/// the region bounds that the (erased) `Self` type must
-/// outlive. Precisely *because* the `Self` type is erased, the
-/// parameter `erased_self_ty` must be supplied to indicate what type
-/// has been used to represent `Self` in the predicates
-/// themselves. This should really be a unique type; `FreshTy(0)` is a
-/// popular choice.
-///
-/// Requires that trait definitions have been processed so that we can
-/// elaborate predicates and walk supertraits.
-pub fn required_region_bounds<'tcx>(tcx: &ctxt<'tcx>,
-                                    erased_self_ty: Ty<'tcx>,
-                                    predicates: Vec<ty::Predicate<'tcx>>)
-                                    -> Vec<ty::Region>
-{
-    debug!("required_region_bounds(erased_self_ty={:?}, predicates={:?})",
-           erased_self_ty,
-           predicates);
-
-    assert!(!erased_self_ty.has_escaping_regions());
-
-    traits::elaborate_predicates(tcx, predicates)
-        .filter_map(|predicate| {
-            match predicate {
-                ty::Predicate::Projection(..) |
-                ty::Predicate::Trait(..) |
-                ty::Predicate::Equate(..) |
-                ty::Predicate::RegionOutlives(..) => {
-                    None
-                }
-                ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => {
-                    // Search for a bound of the form `erased_self_ty
-                    // : 'a`, but be wary of something like `for<'a>
-                    // erased_self_ty : 'a` (we interpret a
-                    // higher-ranked bound like that as 'static,
-                    // though at present the code in `fulfill.rs`
-                    // considers such bounds to be unsatisfiable, so
-                    // it's kind of a moot point since you could never
-                    // construct such an object, but this seems
-                    // correct even if that code changes).
-                    if t == erased_self_ty && !r.has_escaping_regions() {
-                        if r.has_escaping_regions() {
-                            Some(ty::ReStatic)
+    // Iterate over a type parameter's bounded traits and any supertraits
+    // of those traits, ignoring kinds.
+    // Here, the supertraits are the transitive closure of the supertrait
+    // relation on the supertraits from each bounded trait's constraint
+    // list.
+    pub fn each_bound_trait_and_supertraits<F>(&self,
+                                               bounds: &[PolyTraitRef<'tcx>],
+                                               mut f: F)
+                                               -> bool where
+        F: FnMut(PolyTraitRef<'tcx>) -> bool,
+    {
+        for bound_trait_ref in traits::transitive_bounds(self, bounds) {
+            if !f(bound_trait_ref) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /// Given a set of predicates that apply to an object type, returns
+    /// the region bounds that the (erased) `Self` type must
+    /// outlive. Precisely *because* the `Self` type is erased, the
+    /// parameter `erased_self_ty` must be supplied to indicate what type
+    /// has been used to represent `Self` in the predicates
+    /// themselves. This should really be a unique type; `FreshTy(0)` is a
+    /// popular choice.
+    ///
+    /// Requires that trait definitions have been processed so that we can
+    /// elaborate predicates and walk supertraits.
+    pub fn required_region_bounds(&self,
+                                  erased_self_ty: Ty<'tcx>,
+                                  predicates: Vec<ty::Predicate<'tcx>>)
+                                  -> Vec<ty::Region>
+    {
+        debug!("required_region_bounds(erased_self_ty={:?}, predicates={:?})",
+               erased_self_ty,
+               predicates);
+
+        assert!(!erased_self_ty.has_escaping_regions());
+
+        traits::elaborate_predicates(self, predicates)
+            .filter_map(|predicate| {
+                match predicate {
+                    ty::Predicate::Projection(..) |
+                    ty::Predicate::Trait(..) |
+                    ty::Predicate::Equate(..) |
+                    ty::Predicate::RegionOutlives(..) => {
+                        None
+                    }
+                    ty::Predicate::TypeOutlives(ty::Binder(ty::OutlivesPredicate(t, r))) => {
+                        // Search for a bound of the form `erased_self_ty
+                        // : 'a`, but be wary of something like `for<'a>
+                        // erased_self_ty : 'a` (we interpret a
+                        // higher-ranked bound like that as 'static,
+                        // though at present the code in `fulfill.rs`
+                        // considers such bounds to be unsatisfiable, so
+                        // it's kind of a moot point since you could never
+                        // construct such an object, but this seems
+                        // correct even if that code changes).
+                        if t == erased_self_ty && !r.has_escaping_regions() {
+                            if r.has_escaping_regions() {
+                                Some(ty::ReStatic)
+                            } else {
+                                Some(r)
+                            }
                         } else {
-                            Some(r)
+                            None
                         }
-                    } else {
-                        None
                     }
                 }
-            }
-        })
-        .collect()
-}
-
-pub fn item_variances(tcx: &ctxt, item_id: ast::DefId) -> Rc<ItemVariances> {
-    lookup_locally_or_in_crate_store(
-        "item_variance_map", item_id, &tcx.item_variance_map,
-        || Rc::new(csearch::get_item_variances(&tcx.sess.cstore, item_id)))
-}
-
-pub fn trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) -> bool {
-    populate_implementations_for_trait_if_necessary(tcx, trait_def_id);
+            })
+            .collect()
+    }
 
-    let def = lookup_trait_def(tcx, trait_def_id);
-    def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
-}
+    pub fn item_variances(&self, item_id: ast::DefId) -> Rc<ItemVariances> {
+        lookup_locally_or_in_crate_store(
+            "item_variance_map", item_id, &self.item_variance_map,
+            || Rc::new(csearch::get_item_variances(&self.sess.cstore, item_id)))
+    }
 
-/// Records a trait-to-implementation mapping.
-pub fn record_trait_has_default_impl(tcx: &ctxt, trait_def_id: DefId) {
-    let def = lookup_trait_def(tcx, trait_def_id);
-    def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL)
-}
+    pub fn trait_has_default_impl(&self, trait_def_id: DefId) -> bool {
+        self.populate_implementations_for_trait_if_necessary(trait_def_id);
 
-/// Load primitive inherent implementations if necessary
-pub fn populate_implementations_for_primitive_if_necessary(tcx: &ctxt,
-                                                           primitive_def_id: ast::DefId) {
-    if primitive_def_id.krate == LOCAL_CRATE {
-        return
+        let def = self.lookup_trait_def(trait_def_id);
+        def.flags.get().intersects(TraitFlags::HAS_DEFAULT_IMPL)
     }
 
-    if tcx.populated_external_primitive_impls.borrow().contains(&primitive_def_id) {
-        return
+    /// Records a trait-to-implementation mapping.
+    pub fn record_trait_has_default_impl(&self, trait_def_id: DefId) {
+        let def = self.lookup_trait_def(trait_def_id);
+        def.flags.set(def.flags.get() | TraitFlags::HAS_DEFAULT_IMPL)
     }
 
-    debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}",
-           primitive_def_id);
+    /// Load primitive inherent implementations if necessary
+    pub fn populate_implementations_for_primitive_if_necessary(&self,
+                                                               primitive_def_id: ast::DefId) {
+        if primitive_def_id.krate == LOCAL_CRATE {
+            return
+        }
 
-    let impl_items = csearch::get_impl_items(&tcx.sess.cstore, primitive_def_id);
+        if self.populated_external_primitive_impls.borrow().contains(&primitive_def_id) {
+            return
+        }
 
-    // Store the implementation info.
-    tcx.impl_items.borrow_mut().insert(primitive_def_id, impl_items);
-    tcx.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
-}
+        debug!("populate_implementations_for_primitive_if_necessary: searching for {:?}",
+               primitive_def_id);
 
-/// Populates the type context with all the inherent implementations for
-/// the given type if necessary.
-pub fn populate_inherent_implementations_for_type_if_necessary(tcx: &ctxt,
-                                                               type_id: ast::DefId) {
-    if type_id.krate == LOCAL_CRATE {
-        return
-    }
+        let impl_items = csearch::get_impl_items(&self.sess.cstore, primitive_def_id);
 
-    if tcx.populated_external_types.borrow().contains(&type_id) {
-        return
+        // Store the implementation info.
+        self.impl_items.borrow_mut().insert(primitive_def_id, impl_items);
+        self.populated_external_primitive_impls.borrow_mut().insert(primitive_def_id);
     }
 
-    debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}", type_id);
+    /// Populates the type context with all the inherent implementations for
+    /// the given type if necessary.
+    pub fn populate_inherent_implementations_for_type_if_necessary(&self,
+                                                                   type_id: ast::DefId) {
+        if type_id.krate == LOCAL_CRATE {
+            return
+        }
+
+        if self.populated_external_types.borrow().contains(&type_id) {
+            return
+        }
 
-    let mut inherent_impls = Vec::new();
-    csearch::each_inherent_implementation_for_type(&tcx.sess.cstore, type_id, |impl_def_id| {
-        // Record the implementation.
-        inherent_impls.push(impl_def_id);
+        debug!("populate_inherent_implementations_for_type_if_necessary: searching for {:?}",
+               type_id);
 
-        // Store the implementation info.
-        let impl_items = csearch::get_impl_items(&tcx.sess.cstore, impl_def_id);
-        tcx.impl_items.borrow_mut().insert(impl_def_id, impl_items);
-    });
+        let mut inherent_impls = Vec::new();
+        csearch::each_inherent_implementation_for_type(&self.sess.cstore, type_id, |impl_def_id| {
+            // Record the implementation.
+            inherent_impls.push(impl_def_id);
 
-    tcx.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
-    tcx.populated_external_types.borrow_mut().insert(type_id);
-}
+            // Store the implementation info.
+            let impl_items = csearch::get_impl_items(&self.sess.cstore, impl_def_id);
+            self.impl_items.borrow_mut().insert(impl_def_id, impl_items);
+        });
 
-/// Populates the type context with all the implementations for the given
-/// trait if necessary.
-pub fn populate_implementations_for_trait_if_necessary(tcx: &ctxt, trait_id: ast::DefId) {
-    if trait_id.krate == LOCAL_CRATE {
-        return
+        self.inherent_impls.borrow_mut().insert(type_id, Rc::new(inherent_impls));
+        self.populated_external_types.borrow_mut().insert(type_id);
     }
 
-    let def = lookup_trait_def(tcx, trait_id);
-    if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
-        return;
-    }
+    /// Populates the type context with all the implementations for the given
+    /// trait if necessary.
+    pub fn populate_implementations_for_trait_if_necessary(&self, trait_id: ast::DefId) {
+        if trait_id.krate == LOCAL_CRATE {
+            return
+        }
 
-    debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def);
+        let def = self.lookup_trait_def(trait_id);
+        if def.flags.get().intersects(TraitFlags::IMPLS_VALID) {
+            return;
+        }
 
-    if csearch::is_defaulted_trait(&tcx.sess.cstore, trait_id) {
-        record_trait_has_default_impl(tcx, trait_id);
-    }
+        debug!("populate_implementations_for_trait_if_necessary: searching for {:?}", def);
+
+        if csearch::is_defaulted_trait(&self.sess.cstore, trait_id) {
+            self.record_trait_has_default_impl(trait_id);
+        }
 
-    csearch::each_implementation_for_trait(&tcx.sess.cstore, trait_id, |implementation_def_id| {
-        let impl_items = csearch::get_impl_items(&tcx.sess.cstore, implementation_def_id);
-        let trait_ref = impl_trait_ref(tcx, implementation_def_id).unwrap();
-        // Record the trait->implementation mapping.
-        def.record_impl(tcx, implementation_def_id, trait_ref);
+        csearch::each_implementation_for_trait(&self.sess.cstore, trait_id, |impl_def_id| {
+            let impl_items = csearch::get_impl_items(&self.sess.cstore, impl_def_id);
+            let trait_ref = self.impl_trait_ref(impl_def_id).unwrap();
+            // Record the trait->implementation mapping.
+            def.record_impl(self, impl_def_id, trait_ref);
 
-        // For any methods that use a default implementation, add them to
-        // the map. This is a bit unfortunate.
-        for impl_item_def_id in &impl_items {
-            let method_def_id = impl_item_def_id.def_id();
-            match impl_or_trait_item(tcx, method_def_id) {
-                MethodTraitItem(method) => {
-                    if let Some(source) = method.provided_source {
-                        tcx.provided_method_sources
-                            .borrow_mut()
-                            .insert(method_def_id, source);
+            // For any methods that use a default implementation, add them to
+            // the map. This is a bit unfortunate.
+            for impl_item_def_id in &impl_items {
+                let method_def_id = impl_item_def_id.def_id();
+                match self.impl_or_trait_item(method_def_id) {
+                    MethodTraitItem(method) => {
+                        if let Some(source) = method.provided_source {
+                            self.provided_method_sources
+                                .borrow_mut()
+                                .insert(method_def_id, source);
+                        }
                     }
+                    _ => {}
                 }
-                _ => {}
             }
-        }
 
-        // Store the implementation info.
-        tcx.impl_items.borrow_mut().insert(implementation_def_id, impl_items);
-    });
-
-    def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
-}
+            // Store the implementation info.
+            self.impl_items.borrow_mut().insert(impl_def_id, impl_items);
+        });
 
-/// Given the def_id of an impl, return the def_id of the trait it implements.
-/// If it implements no trait, return `None`.
-pub fn trait_id_of_impl(tcx: &ctxt,
-                        def_id: ast::DefId)
-                        -> Option<ast::DefId> {
-    ty::impl_trait_ref(tcx, def_id).map(|tr| tr.def_id)
-}
+        def.flags.set(def.flags.get() | TraitFlags::IMPLS_VALID);
+    }
 
-/// If the given def ID describes a method belonging to an impl, return the
-/// ID of the impl that the method belongs to. Otherwise, return `None`.
-pub fn impl_of_method(tcx: &ctxt, def_id: ast::DefId)
-                       -> Option<ast::DefId> {
-    if def_id.krate != LOCAL_CRATE {
-        return match csearch::get_impl_or_trait_item(tcx,
-                                                     def_id).container() {
-            TraitContainer(_) => None,
-            ImplContainer(def_id) => Some(def_id),
-        };
+    /// Given the def_id of an impl, return the def_id of the trait it implements.
+    /// If it implements no trait, return `None`.
+    pub fn trait_id_of_impl(&self, def_id: ast::DefId) -> Option<ast::DefId> {
+        self.impl_trait_ref(def_id).map(|tr| tr.def_id)
     }
-    match tcx.impl_or_trait_items.borrow().get(&def_id).cloned() {
-        Some(trait_item) => {
-            match trait_item.container() {
+
+    /// If the given def ID describes a method belonging to an impl, return the
+    /// ID of the impl that the method belongs to. Otherwise, return `None`.
+    pub fn impl_of_method(&self, def_id: ast::DefId) -> Option<ast::DefId> {
+        if def_id.krate != LOCAL_CRATE {
+            return match csearch::get_impl_or_trait_item(self,
+                                                         def_id).container() {
                 TraitContainer(_) => None,
                 ImplContainer(def_id) => Some(def_id),
-            }
+            };
         }
-        None => None
-    }
-}
-
-/// If the given def ID describes an item belonging to a trait (either a
-/// default method or an implementation of a trait method), return the ID of
-/// the trait that the method belongs to. Otherwise, return `None`.
-pub fn trait_of_item(tcx: &ctxt, def_id: ast::DefId) -> Option<ast::DefId> {
-    if def_id.krate != LOCAL_CRATE {
-        return csearch::get_trait_of_item(&tcx.sess.cstore, def_id, tcx);
-    }
-    match tcx.impl_or_trait_items.borrow().get(&def_id).cloned() {
-        Some(impl_or_trait_item) => {
-            match impl_or_trait_item.container() {
-                TraitContainer(def_id) => Some(def_id),
-                ImplContainer(def_id) => trait_id_of_impl(tcx, def_id),
+        match self.impl_or_trait_items.borrow().get(&def_id).cloned() {
+            Some(trait_item) => {
+                match trait_item.container() {
+                    TraitContainer(_) => None,
+                    ImplContainer(def_id) => Some(def_id),
+                }
             }
+            None => None
         }
-        None => None
     }
-}
 
-/// If the given def ID describes an item belonging to a trait, (either a
-/// default method or an implementation of a trait method), return the ID of
-/// the method inside trait definition (this means that if the given def ID
-/// is already that of the original trait method, then the return value is
-/// the same).
-/// Otherwise, return `None`.
-pub fn trait_item_of_item(tcx: &ctxt, def_id: ast::DefId)
-                          -> Option<ImplOrTraitItemId> {
-    let impl_item = match tcx.impl_or_trait_items.borrow().get(&def_id) {
-        Some(m) => m.clone(),
-        None => return None,
-    };
-    let name = impl_item.name();
-    match trait_of_item(tcx, def_id) {
-        Some(trait_did) => {
-            let trait_items = ty::trait_items(tcx, trait_did);
-            trait_items.iter()
-                .position(|m| m.name() == name)
-                .map(|idx| ty::trait_item(tcx, trait_did, idx).id())
+    /// If the given def ID describes an item belonging to a trait (either a
+    /// default method or an implementation of a trait method), return the ID of
+    /// the trait that the method belongs to. Otherwise, return `None`.
+    pub fn trait_of_item(&self, def_id: ast::DefId) -> Option<ast::DefId> {
+        if def_id.krate != LOCAL_CRATE {
+            return csearch::get_trait_of_item(&self.sess.cstore, def_id, self);
         }
-        None => None
-    }
-}
-
-/// Creates a hash of the type `Ty` which will be the same no matter what crate
-/// context it's calculated within. This is used by the `type_id` intrinsic.
-pub fn hash_crate_independent<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh) -> u64 {
-    let mut state = SipHasher::new();
-    helper(tcx, ty, svh, &mut state);
-    return state.finish();
-
-    fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh,
-                    state: &mut SipHasher) {
-        macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } }
-        macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
-
-        let region = |state: &mut SipHasher, r: Region| {
-            match r {
-                ReStatic => {}
-                ReLateBound(db, BrAnon(i)) => {
-                    db.hash(state);
-                    i.hash(state);
-                }
-                ReEmpty |
-                ReEarlyBound(..) |
-                ReLateBound(..) |
-                ReFree(..) |
-                ReScope(..) |
-                ReInfer(..) => {
-                    tcx.sess.bug("unexpected region found when hashing a type")
+        match self.impl_or_trait_items.borrow().get(&def_id).cloned() {
+            Some(impl_or_trait_item) => {
+                match impl_or_trait_item.container() {
+                    TraitContainer(def_id) => Some(def_id),
+                    ImplContainer(def_id) => self.trait_id_of_impl(def_id),
                 }
             }
+            None => None
+        }
+    }
+
+    /// If the given def ID describes an item belonging to a trait, (either a
+    /// default method or an implementation of a trait method), return the ID of
+    /// the method inside trait definition (this means that if the given def ID
+    /// is already that of the original trait method, then the return value is
+    /// the same).
+    /// Otherwise, return `None`.
+    pub fn trait_item_of_item(&self, def_id: ast::DefId) -> Option<ImplOrTraitItemId> {
+        let impl_item = match self.impl_or_trait_items.borrow().get(&def_id) {
+            Some(m) => m.clone(),
+            None => return None,
         };
-        let did = |state: &mut SipHasher, did: DefId| {
-            let h = if ast_util::is_local(did) {
-                svh.clone()
-            } else {
-                tcx.sess.cstore.get_crate_hash(did.krate)
-            };
-            h.as_str().hash(state);
-            did.node.hash(state);
-        };
-        let mt = |state: &mut SipHasher, mt: mt| {
-            mt.mutbl.hash(state);
-        };
-        let fn_sig = |state: &mut SipHasher, sig: &Binder<FnSig<'tcx>>| {
-            let sig = anonymize_late_bound_regions(tcx, sig).0;
-            for a in &sig.inputs { helper(tcx, *a, svh, state); }
-            if let ty::FnConverging(output) = sig.output {
-                helper(tcx, output, svh, state);
-            }
-        };
-        maybe_walk_ty(ty, |ty| {
-            match ty.sty {
-                TyBool => byte!(2),
-                TyChar => byte!(3),
-                TyInt(i) => {
-                    byte!(4);
-                    hash!(i);
-                }
-                TyUint(u) => {
-                    byte!(5);
-                    hash!(u);
-                }
-                TyFloat(f) => {
-                    byte!(6);
-                    hash!(f);
-                }
-                TyStr => {
-                    byte!(7);
-                }
-                TyEnum(d, _) => {
-                    byte!(8);
-                    did(state, d);
-                }
-                TyBox(_) => {
-                    byte!(9);
-                }
-                TyArray(_, n) => {
-                    byte!(10);
-                    n.hash(state);
-                }
-                TySlice(_) => {
-                    byte!(11);
-                }
-                TyRawPtr(m) => {
-                    byte!(12);
-                    mt(state, m);
-                }
-                TyRef(r, m) => {
-                    byte!(13);
-                    region(state, *r);
-                    mt(state, m);
+        let name = impl_item.name();
+        match self.trait_of_item(def_id) {
+            Some(trait_did) => {
+                let trait_items = self.trait_items(trait_did);
+                trait_items.iter()
+                    .position(|m| m.name() == name)
+                    .map(|idx| self.trait_item(trait_did, idx).id())
+            }
+            None => None
+        }
+    }
+
+    /// Creates a hash of the type `Ty` which will be the same no matter what crate
+    /// context it's calculated within. This is used by the `type_id` intrinsic.
+    pub fn hash_crate_independent(&self, ty: Ty<'tcx>, svh: &Svh) -> u64 {
+        let mut state = SipHasher::new();
+        helper(self, ty, svh, &mut state);
+        return state.finish();
+
+        fn helper<'tcx>(tcx: &ctxt<'tcx>, ty: Ty<'tcx>, svh: &Svh,
+                        state: &mut SipHasher) {
+            macro_rules! byte { ($b:expr) => { ($b as u8).hash(state) } }
+            macro_rules! hash { ($e:expr) => { $e.hash(state) }  }
+
+            let region = |state: &mut SipHasher, r: Region| {
+                match r {
+                    ReStatic => {}
+                    ReLateBound(db, BrAnon(i)) => {
+                        db.hash(state);
+                        i.hash(state);
+                    }
+                    ReEmpty |
+                    ReEarlyBound(..) |
+                    ReLateBound(..) |
+                    ReFree(..) |
+                    ReScope(..) |
+                    ReInfer(..) => {
+                        tcx.sess.bug("unexpected region found when hashing a type")
+                    }
                 }
-                TyBareFn(opt_def_id, ref b) => {
-                    byte!(14);
-                    hash!(opt_def_id);
-                    hash!(b.unsafety);
-                    hash!(b.abi);
-                    fn_sig(state, &b.sig);
-                    return false;
+            };
+            let did = |state: &mut SipHasher, did: DefId| {
+                let h = if ast_util::is_local(did) {
+                    svh.clone()
+                } else {
+                    tcx.sess.cstore.get_crate_hash(did.krate)
+                };
+                h.as_str().hash(state);
+                did.node.hash(state);
+            };
+            let mt = |state: &mut SipHasher, mt: mt| {
+                mt.mutbl.hash(state);
+            };
+            let fn_sig = |state: &mut SipHasher, sig: &Binder<FnSig<'tcx>>| {
+                let sig = tcx.anonymize_late_bound_regions(sig).0;
+                for a in &sig.inputs { helper(tcx, *a, svh, state); }
+                if let ty::FnConverging(output) = sig.output {
+                    helper(tcx, output, svh, state);
                 }
-                TyTrait(ref data) => {
-                    byte!(17);
-                    did(state, data.principal_def_id());
-                    hash!(data.bounds);
-
-                    let principal = anonymize_late_bound_regions(tcx, &data.principal).0;
-                    for subty in &principal.substs.types {
-                        helper(tcx, subty, svh, state);
+            };
+            ty.maybe_walk(|ty| {
+                match ty.sty {
+                    TyBool => byte!(2),
+                    TyChar => byte!(3),
+                    TyInt(i) => {
+                        byte!(4);
+                        hash!(i);
+                    }
+                    TyUint(u) => {
+                        byte!(5);
+                        hash!(u);
+                    }
+                    TyFloat(f) => {
+                        byte!(6);
+                        hash!(f);
+                    }
+                    TyStr => {
+                        byte!(7);
+                    }
+                    TyEnum(d, _) => {
+                        byte!(8);
+                        did(state, d);
+                    }
+                    TyBox(_) => {
+                        byte!(9);
+                    }
+                    TyArray(_, n) => {
+                        byte!(10);
+                        n.hash(state);
+                    }
+                    TySlice(_) => {
+                        byte!(11);
+                    }
+                    TyRawPtr(m) => {
+                        byte!(12);
+                        mt(state, m);
                     }
+                    TyRef(r, m) => {
+                        byte!(13);
+                        region(state, *r);
+                        mt(state, m);
+                    }
+                    TyBareFn(opt_def_id, ref b) => {
+                        byte!(14);
+                        hash!(opt_def_id);
+                        hash!(b.unsafety);
+                        hash!(b.abi);
+                        fn_sig(state, &b.sig);
+                        return false;
+                    }
+                    TyTrait(ref data) => {
+                        byte!(17);
+                        did(state, data.principal_def_id());
+                        hash!(data.bounds);
+
+                        let principal = tcx.anonymize_late_bound_regions(&data.principal).0;
+                        for subty in &principal.substs.types {
+                            helper(tcx, subty, svh, state);
+                        }
 
-                    return false;
-                }
-                TyStruct(d, _) => {
-                    byte!(18);
-                    did(state, d);
-                }
-                TyTuple(ref inner) => {
-                    byte!(19);
-                    hash!(inner.len());
-                }
-                TyParam(p) => {
-                    byte!(20);
-                    hash!(p.space);
-                    hash!(p.idx);
-                    hash!(token::get_name(p.name));
-                }
-                TyInfer(_) => unreachable!(),
-                TyError => byte!(21),
-                TyClosure(d, _) => {
-                    byte!(22);
-                    did(state, d);
-                }
-                TyProjection(ref data) => {
-                    byte!(23);
-                    did(state, data.trait_ref.def_id);
-                    hash!(token::get_name(data.item_name));
+                        return false;
+                    }
+                    TyStruct(d, _) => {
+                        byte!(18);
+                        did(state, d);
+                    }
+                    TyTuple(ref inner) => {
+                        byte!(19);
+                        hash!(inner.len());
+                    }
+                    TyParam(p) => {
+                        byte!(20);
+                        hash!(p.space);
+                        hash!(p.idx);
+                        hash!(token::get_name(p.name));
+                    }
+                    TyInfer(_) => unreachable!(),
+                    TyError => byte!(21),
+                    TyClosure(d, _) => {
+                        byte!(22);
+                        did(state, d);
+                    }
+                    TyProjection(ref data) => {
+                        byte!(23);
+                        did(state, data.trait_ref.def_id);
+                        hash!(token::get_name(data.item_name));
+                    }
                 }
-            }
-            true
-        });
-    }
-}
-
-impl fmt::Debug for Variance {
-    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
-        f.write_str(match *self {
-            Covariant => "+",
-            Contravariant => "-",
-            Invariant => "o",
-            Bivariant => "*",
-        })
-    }
-}
-
-/// Construct a parameter environment suitable for static contexts or other contexts where there
-/// are no free type/lifetime parameters in scope.
-pub fn empty_parameter_environment<'a,'tcx>(cx: &'a ctxt<'tcx>) -> ParameterEnvironment<'a,'tcx> {
-    ty::ParameterEnvironment { tcx: cx,
-                               free_substs: Substs::empty(),
-                               caller_bounds: Vec::new(),
-                               implicit_region_bound: ty::ReEmpty,
-                               selection_cache: traits::SelectionCache::new(), }
-}
-
-/// Constructs and returns a substitution that can be applied to move from
-/// the "outer" view of a type or method to the "inner" view.
-/// In general, this means converting from bound parameters to
-/// free parameters. Since we currently represent bound/free type
-/// parameters in the same way, this only has an effect on regions.
-pub fn construct_free_substs<'a,'tcx>(
-    tcx: &'a ctxt<'tcx>,
-    generics: &Generics<'tcx>,
-    free_id: ast::NodeId)
-    -> Substs<'tcx>
-{
-    // map T => T
-    let mut types = VecPerParamSpace::empty();
-    push_types_from_defs(tcx, &mut types, generics.types.as_slice());
-
-    let free_id_outlive = region::DestructionScopeData::new(free_id);
-
-    // map bound 'a => free 'a
-    let mut regions = VecPerParamSpace::empty();
-    push_region_params(&mut regions, free_id_outlive, generics.regions.as_slice());
+                true
+            });
+        }
+    }
+
+    /// Construct a parameter environment suitable for static contexts or other contexts where there
+    /// are no free type/lifetime parameters in scope.
+    pub fn empty_parameter_environment<'a>(&'a self) -> ParameterEnvironment<'a,'tcx> {
+        ty::ParameterEnvironment { tcx: self,
+                                   free_substs: Substs::empty(),
+                                   caller_bounds: Vec::new(),
+                                   implicit_region_bound: ty::ReEmpty,
+                                   selection_cache: traits::SelectionCache::new(), }
+    }
+
+    /// Constructs and returns a substitution that can be applied to move from
+    /// the "outer" view of a type or method to the "inner" view.
+    /// In general, this means converting from bound parameters to
+    /// free parameters. Since we currently represent bound/free type
+    /// parameters in the same way, this only has an effect on regions.
+    pub fn construct_free_substs(&self, generics: &Generics<'tcx>,
+                                 free_id: ast::NodeId) -> Substs<'tcx> {
+        // map T => T
+        let mut types = VecPerParamSpace::empty();
+        for def in generics.types.as_slice() {
+            debug!("construct_parameter_environment(): push_types_from_defs: def={:?}",
+                    def);
+            types.push(def.space, self.mk_param_from_def(def));
+        }
 
-    return Substs {
-        types: types,
-        regions: subst::NonerasedRegions(regions)
-    };
+        let free_id_outlive = region::DestructionScopeData::new(free_id);
 
-    fn push_region_params(regions: &mut VecPerParamSpace<ty::Region>,
-                          all_outlive_extent: region::DestructionScopeData,
-                          region_params: &[RegionParameterDef])
-    {
-        for r in region_params {
-            regions.push(r.space, ty::free_region_from_def(all_outlive_extent, r));
+        // map bound 'a => free 'a
+        let mut regions = VecPerParamSpace::empty();
+        for def in generics.regions.as_slice() {
+            let region =
+                ReFree(FreeRegion { scope: free_id_outlive,
+                                    bound_region: BrNamed(def.def_id, def.name) });
+            debug!("push_region_params {:?}", region);
+            regions.push(def.space, region);
         }
-    }
 
-    fn push_types_from_defs<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                  types: &mut VecPerParamSpace<Ty<'tcx>>,
-                                  defs: &[TypeParameterDef<'tcx>]) {
-        for def in defs {
-            debug!("construct_parameter_environment(): push_types_from_defs: def={:?}",
-                   def);
-            let ty = ty::mk_param_from_def(tcx, def);
-            types.push(def.space, ty);
-       }
+        Substs {
+            types: types,
+            regions: subst::NonerasedRegions(regions)
+        }
     }
-}
-
-/// See `ParameterEnvironment` struct def'n for details
-pub fn construct_parameter_environment<'a,'tcx>(
-    tcx: &'a ctxt<'tcx>,
-    span: Span,
-    generics: &ty::Generics<'tcx>,
-    generic_predicates: &ty::GenericPredicates<'tcx>,
-    free_id: ast::NodeId)
-    -> ParameterEnvironment<'a, 'tcx>
-{
-    //
-    // Construct the free substs.
-    //
-
-    let free_substs = construct_free_substs(tcx, generics, free_id);
-    let free_id_outlive = region::DestructionScopeData::new(free_id);
-
-    //
-    // Compute the bounds on Self and the type parameters.
-    //
 
-    let bounds = generic_predicates.instantiate(tcx, &free_substs);
-    let bounds = liberate_late_bound_regions(tcx, free_id_outlive, &ty::Binder(bounds));
-    let predicates = bounds.predicates.into_vec();
+    /// See `ParameterEnvironment` struct def'n for details
+    pub fn construct_parameter_environment<'a>(&'a self,
+                                               span: Span,
+                                               generics: &ty::Generics<'tcx>,
+                                               generic_predicates: &ty::GenericPredicates<'tcx>,
+                                               free_id: ast::NodeId)
+                                               -> ParameterEnvironment<'a, 'tcx>
+    {
+        //
+        // Construct the free substs.
+        //
 
-    debug!("construct_parameter_environment: free_id={:?} free_subst={:?} predicates={:?}",
-           free_id,
-           free_substs,
-           predicates);
+        let free_substs = self.construct_free_substs(generics, free_id);
+        let free_id_outlive = region::DestructionScopeData::new(free_id);
 
-    //
-    // Finally, we have to normalize the bounds in the environment, in
-    // case they contain any associated type projections. This process
-    // can yield errors if the put in illegal associated types, like
-    // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
-    // report these errors right here; this doesn't actually feel
-    // right to me, because constructing the environment feels like a
-    // kind of a "idempotent" action, but I'm not sure where would be
-    // a better place. In practice, we construct environments for
-    // every fn once during type checking, and we'll abort if there
-    // are any errors at that point, so after type checking you can be
-    // sure that this will succeed without errors anyway.
-    //
-
-    let unnormalized_env = ty::ParameterEnvironment {
-        tcx: tcx,
-        free_substs: free_substs,
-        implicit_region_bound: ty::ReScope(free_id_outlive.to_code_extent()),
-        caller_bounds: predicates,
-        selection_cache: traits::SelectionCache::new(),
-    };
+        //
+        // Compute the bounds on Self and the type parameters.
+        //
 
-    let cause = traits::ObligationCause::misc(span, free_id);
-    traits::normalize_param_env_or_error(unnormalized_env, cause)
-}
+        let bounds = generic_predicates.instantiate(self, &free_substs);
+        let bounds = self.liberate_late_bound_regions(free_id_outlive, &ty::Binder(bounds));
+        let predicates = bounds.predicates.into_vec();
 
-impl BorrowKind {
-    pub fn from_mutbl(m: ast::Mutability) -> BorrowKind {
-        match m {
-            ast::MutMutable => MutBorrow,
-            ast::MutImmutable => ImmBorrow,
-        }
-    }
+        debug!("construct_parameter_environment: free_id={:?} free_subst={:?} predicates={:?}",
+               free_id,
+               free_substs,
+               predicates);
 
-    /// Returns a mutability `m` such that an `&m T` pointer could be used to obtain this borrow
-    /// kind. Because borrow kinds are richer than mutabilities, we sometimes have to pick a
-    /// mutability that is stronger than necessary so that it at least *would permit* the borrow in
-    /// question.
-    pub fn to_mutbl_lossy(self) -> ast::Mutability {
-        match self {
-            MutBorrow => ast::MutMutable,
-            ImmBorrow => ast::MutImmutable,
+        //
+        // Finally, we have to normalize the bounds in the environment, in
+        // case they contain any associated type projections. This process
+        // can yield errors if the put in illegal associated types, like
+        // `<i32 as Foo>::Bar` where `i32` does not implement `Foo`. We
+        // report these errors right here; this doesn't actually feel
+        // right to me, because constructing the environment feels like a
+        // kind of a "idempotent" action, but I'm not sure where would be
+        // a better place. In practice, we construct environments for
+        // every fn once during type checking, and we'll abort if there
+        // are any errors at that point, so after type checking you can be
+        // sure that this will succeed without errors anyway.
+        //
 
-            // We have no type corresponding to a unique imm borrow, so
-            // use `&mut`. It gives all the capabilities of an `&uniq`
-            // and hence is a safe "over approximation".
-            UniqueImmBorrow => ast::MutMutable,
-        }
-    }
+        let unnormalized_env = ty::ParameterEnvironment {
+            tcx: self,
+            free_substs: free_substs,
+            implicit_region_bound: ty::ReScope(free_id_outlive.to_code_extent()),
+            caller_bounds: predicates,
+            selection_cache: traits::SelectionCache::new(),
+        };
 
-    pub fn to_user_str(&self) -> &'static str {
-        match *self {
-            MutBorrow => "mutable",
-            ImmBorrow => "immutable",
-            UniqueImmBorrow => "uniquely immutable",
-        }
+        let cause = traits::ObligationCause::misc(span, free_id);
+        traits::normalize_param_env_or_error(unnormalized_env, cause)
     }
-}
 
-impl<'tcx> ctxt<'tcx> {
     pub fn is_method_call(&self, expr_id: ast::NodeId) -> bool {
         self.method_map.borrow().contains_key(&MethodCall::expr(expr_id))
     }
@@ -6956,13 +6679,13 @@ impl<'tcx> ctxt<'tcx> {
     }
 }
 
-impl<'a,'tcx> mc::Typer<'tcx> for ParameterEnvironment<'a,'tcx> {
+impl<'a,'tcx> Typer<'tcx> for ParameterEnvironment<'a,'tcx> {
     fn node_ty(&self, id: ast::NodeId) -> mc::McResult<Ty<'tcx>> {
-        Ok(ty::node_id_to_type(self.tcx, id))
+        Ok(self.tcx.node_id_to_type(id))
     }
 
     fn expr_ty_adjusted(&self, expr: &ast::Expr) -> mc::McResult<Ty<'tcx>> {
-        Ok(ty::expr_ty_adjusted(self.tcx, expr))
+        Ok(self.tcx.expr_ty_adjusted(expr))
     }
 
     fn node_method_ty(&self, method_call: ty::MethodCall) -> Option<Ty<'tcx>> {
@@ -6991,8 +6714,8 @@ impl<'a,'tcx> mc::Typer<'tcx> for ParameterEnvironment<'a,'tcx> {
         self.tcx.upvar_capture(upvar_id)
     }
 
-    fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
-        type_moves_by_default(self, span, ty)
+    fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
+        ty.moves_by_default(self, span)
     }
 }
 
@@ -7019,9 +6742,8 @@ impl<'a,'tcx> ClosureTyper<'tcx> for ty::ParameterEnvironment<'a,'tcx> {
     fn closure_upvars(&self,
                       def_id: ast::DefId,
                       substs: &Substs<'tcx>)
-                      -> Option<Vec<ClosureUpvar<'tcx>>>
-    {
-        closure_upvars(self, def_id, substs)
+                      -> Option<Vec<ClosureUpvar<'tcx>>> {
+        ctxt::closure_upvars(self, def_id, substs)
     }
 }
 
@@ -7035,54 +6757,55 @@ pub enum ExplicitSelfCategory {
     ByBoxExplicitSelfCategory,
 }
 
-/// Pushes all the lifetimes in the given type onto the given list. A
-/// "lifetime in a type" is a lifetime specified by a reference or a lifetime
-/// in a list of type substitutions. This does *not* traverse into nominal
-/// types, nor does it resolve fictitious types.
-pub fn accumulate_lifetimes_in_type(accumulator: &mut Vec<ty::Region>,
-                                    ty: Ty) {
-    walk_ty(ty, |ty| {
-        match ty.sty {
-            TyRef(region, _) => {
-                accumulator.push(*region)
-            }
-            TyTrait(ref t) => {
-                accumulator.push_all(t.principal.0.substs.regions().as_slice());
-            }
-            TyEnum(_, substs) |
-            TyStruct(_, substs) => {
-                accum_substs(accumulator, substs);
-            }
-            TyClosure(_, substs) => {
-                accum_substs(accumulator, substs);
-            }
-            TyBool |
-            TyChar |
-            TyInt(_) |
-            TyUint(_) |
-            TyFloat(_) |
-            TyBox(_) |
-            TyStr |
-            TyArray(_, _) |
-            TySlice(_) |
-            TyRawPtr(_) |
-            TyBareFn(..) |
-            TyTuple(_) |
-            TyProjection(_) |
-            TyParam(_) |
-            TyInfer(_) |
-            TyError => {
-            }
-        }
-    });
-
-    fn accum_substs(accumulator: &mut Vec<Region>, substs: &Substs) {
-        match substs.regions {
-            subst::ErasedRegions => {}
-            subst::NonerasedRegions(ref regions) => {
-                for region in regions {
+impl<'tcx> TyS<'tcx> {
+    /// Pushes all the lifetimes in the given type onto the given list. A
+    /// "lifetime in a type" is a lifetime specified by a reference or a lifetime
+    /// in a list of type substitutions. This does *not* traverse into nominal
+    /// types, nor does it resolve fictitious types.
+    pub fn accumulate_lifetimes_in_type(&self, accumulator: &mut Vec<ty::Region>) {
+        for ty in self.walk() {
+            match ty.sty {
+                TyRef(region, _) => {
                     accumulator.push(*region)
                 }
+                TyTrait(ref t) => {
+                    accumulator.push_all(t.principal.0.substs.regions().as_slice());
+                }
+                TyEnum(_, substs) |
+                TyStruct(_, substs) => {
+                    accum_substs(accumulator, substs);
+                }
+                TyClosure(_, substs) => {
+                    accum_substs(accumulator, substs);
+                }
+                TyBool |
+                TyChar |
+                TyInt(_) |
+                TyUint(_) |
+                TyFloat(_) |
+                TyBox(_) |
+                TyStr |
+                TyArray(_, _) |
+                TySlice(_) |
+                TyRawPtr(_) |
+                TyBareFn(..) |
+                TyTuple(_) |
+                TyProjection(_) |
+                TyParam(_) |
+                TyInfer(_) |
+                TyError => {
+                }
+            }
+        }
+
+        fn accum_substs(accumulator: &mut Vec<Region>, substs: &Substs) {
+            match substs.regions {
+                subst::ErasedRegions => {}
+                subst::NonerasedRegions(ref regions) => {
+                    for region in regions {
+                        accumulator.push(*region)
+                    }
+                }
             }
         }
     }
@@ -7109,15 +6832,6 @@ pub type TraitMap = NodeMap<Vec<DefId>>;
 // imported.
 pub type GlobMap = HashMap<NodeId, HashSet<Name>>;
 
-pub fn with_freevars<T, F>(tcx: &ty::ctxt, fid: ast::NodeId, f: F) -> T where
-    F: FnOnce(&[Freevar]) -> T,
-{
-    match tcx.freevars.borrow().get(&fid) {
-        None => f(&[]),
-        Some(d) => f(&d[..])
-    }
-}
-
 impl<'tcx> AutoAdjustment<'tcx> {
     pub fn is_identity(&self) -> bool {
         match *self {
@@ -7134,106 +6848,123 @@ impl<'tcx> AutoDerefRef<'tcx> {
     }
 }
 
-/// Replace any late-bound regions bound in `value` with free variants attached to scope-id
-/// `scope_id`.
-pub fn liberate_late_bound_regions<'tcx, T>(
-    tcx: &ty::ctxt<'tcx>,
-    all_outlive_scope: region::DestructionScopeData,
-    value: &Binder<T>)
-    -> T
-    where T : TypeFoldable<'tcx>
-{
-    ty_fold::replace_late_bound_regions(
-        tcx, value,
-        |br| ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, bound_region: br})).0
-}
+impl<'tcx> ctxt<'tcx> {
+    pub fn with_freevars<T, F>(&self, fid: ast::NodeId, f: F) -> T where
+        F: FnOnce(&[Freevar]) -> T,
+    {
+        match self.freevars.borrow().get(&fid) {
+            None => f(&[]),
+            Some(d) => f(&d[..])
+        }
+    }
 
-pub fn count_late_bound_regions<'tcx, T>(
-    tcx: &ty::ctxt<'tcx>,
-    value: &Binder<T>)
-    -> usize
-    where T : TypeFoldable<'tcx>
-{
-    let (_, skol_map) = ty_fold::replace_late_bound_regions(tcx, value, |_| ty::ReStatic);
-    skol_map.len()
-}
+    /// Replace any late-bound regions bound in `value` with free variants attached to scope-id
+    /// `scope_id`.
+    pub fn liberate_late_bound_regions<T>(&self,
+        all_outlive_scope: region::DestructionScopeData,
+        value: &Binder<T>)
+        -> T
+        where T : TypeFoldable<'tcx>
+    {
+        ty_fold::replace_late_bound_regions(
+            self, value,
+            |br| ty::ReFree(ty::FreeRegion{scope: all_outlive_scope, bound_region: br})).0
+    }
 
-pub fn binds_late_bound_regions<'tcx, T>(
-    tcx: &ty::ctxt<'tcx>,
-    value: &Binder<T>)
-    -> bool
-    where T : TypeFoldable<'tcx>
-{
-    count_late_bound_regions(tcx, value) > 0
-}
+    pub fn count_late_bound_regions<T>(&self, value: &Binder<T>) -> usize
+        where T : TypeFoldable<'tcx>
+    {
+        let (_, skol_map) = ty_fold::replace_late_bound_regions(self, value, |_| ty::ReStatic);
+        skol_map.len()
+    }
 
-/// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
-/// becomes `for<'a,'b> Foo`.
-pub fn flatten_late_bound_regions<'tcx, T>(
-    tcx: &ty::ctxt<'tcx>,
-    bound2_value: &Binder<Binder<T>>)
-    -> Binder<T>
-    where T: TypeFoldable<'tcx>
-{
-    let bound0_value = bound2_value.skip_binder().skip_binder();
-    let value = ty_fold::fold_regions(tcx, bound0_value, |region, current_depth| {
-        match region {
-            ty::ReLateBound(debruijn, br) if debruijn.depth >= current_depth => {
-                // should be true if no escaping regions from bound2_value
-                assert!(debruijn.depth - current_depth <= 1);
-                ty::ReLateBound(DebruijnIndex::new(current_depth), br)
-            }
-            _ => {
-                region
+    pub fn binds_late_bound_regions<T>(&self, value: &Binder<T>) -> bool
+        where T : TypeFoldable<'tcx>
+    {
+        self.count_late_bound_regions(value) > 0
+    }
+
+    /// Flattens two binding levels into one. So `for<'a> for<'b> Foo`
+    /// becomes `for<'a,'b> Foo`.
+    pub fn flatten_late_bound_regions<T>(&self, bound2_value: &Binder<Binder<T>>)
+                                         -> Binder<T>
+        where T: TypeFoldable<'tcx>
+    {
+        let bound0_value = bound2_value.skip_binder().skip_binder();
+        let value = ty_fold::fold_regions(self, bound0_value, |region, current_depth| {
+            match region {
+                ty::ReLateBound(debruijn, br) if debruijn.depth >= current_depth => {
+                    // should be true if no escaping regions from bound2_value
+                    assert!(debruijn.depth - current_depth <= 1);
+                    ty::ReLateBound(DebruijnIndex::new(current_depth), br)
+                }
+                _ => {
+                    region
+                }
             }
+        });
+        Binder(value)
+    }
+
+    pub fn no_late_bound_regions<T>(&self, value: &Binder<T>) -> Option<T>
+        where T : TypeFoldable<'tcx>
+    {
+        if self.binds_late_bound_regions(value) {
+            None
+        } else {
+            Some(value.0.clone())
         }
-    });
-    Binder(value)
-}
+    }
 
-pub fn no_late_bound_regions<'tcx, T>(
-    tcx: &ty::ctxt<'tcx>,
-    value: &Binder<T>)
-    -> Option<T>
-    where T : TypeFoldable<'tcx>
-{
-    if binds_late_bound_regions(tcx, value) {
-        None
-    } else {
-        Some(value.0.clone())
+    /// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
+    /// method lookup and a few other places where precise region relationships are not required.
+    pub fn erase_late_bound_regions<T>(&self, value: &Binder<T>) -> T
+        where T : TypeFoldable<'tcx>
+    {
+        ty_fold::replace_late_bound_regions(self, value, |_| ty::ReStatic).0
     }
-}
 
-/// Replace any late-bound regions bound in `value` with `'static`. Useful in trans but also
-/// method lookup and a few other places where precise region relationships are not required.
-pub fn erase_late_bound_regions<'tcx, T>(
-    tcx: &ty::ctxt<'tcx>,
-    value: &Binder<T>)
-    -> T
-    where T : TypeFoldable<'tcx>
-{
-    ty_fold::replace_late_bound_regions(tcx, value, |_| ty::ReStatic).0
-}
+    /// Rewrite any late-bound regions so that they are anonymous.  Region numbers are
+    /// assigned starting at 1 and increasing monotonically in the order traversed
+    /// by the fold operation.
+    ///
+    /// The chief purpose of this function is to canonicalize regions so that two
+    /// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
+    /// structurally identical.  For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
+    /// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
+    pub fn anonymize_late_bound_regions<T>(&self, sig: &Binder<T>) -> Binder<T>
+        where T : TypeFoldable<'tcx>,
+    {
+        let mut counter = 0;
+        ty::Binder(ty_fold::replace_late_bound_regions(self, sig, |_| {
+            counter += 1;
+            ReLateBound(ty::DebruijnIndex::new(1), BrAnon(counter))
+        }).0)
+    }
 
-/// Rewrite any late-bound regions so that they are anonymous.  Region numbers are
-/// assigned starting at 1 and increasing monotonically in the order traversed
-/// by the fold operation.
-///
-/// The chief purpose of this function is to canonicalize regions so that two
-/// `FnSig`s or `TraitRef`s which are equivalent up to region naming will become
-/// structurally identical.  For example, `for<'a, 'b> fn(&'a isize, &'b isize)` and
-/// `for<'a, 'b> fn(&'b isize, &'a isize)` will become identical after anonymization.
-pub fn anonymize_late_bound_regions<'tcx, T>(
-    tcx: &ctxt<'tcx>,
-    sig: &Binder<T>)
-    -> Binder<T>
-    where T : TypeFoldable<'tcx>,
-{
-    let mut counter = 0;
-    ty::Binder(ty_fold::replace_late_bound_regions(tcx, sig, |_| {
-        counter += 1;
-        ReLateBound(ty::DebruijnIndex::new(1), BrAnon(counter))
-    }).0)
+    pub fn make_substs_for_receiver_types(&self,
+                                          trait_ref: &ty::TraitRef<'tcx>,
+                                          method: &ty::Method<'tcx>)
+                                          -> subst::Substs<'tcx>
+    {
+        /*!
+         * Substitutes the values for the receiver's type parameters
+         * that are found in method, leaving the method's type parameters
+         * intact.
+         */
+
+        let meth_tps: Vec<Ty> =
+            method.generics.types.get_slice(subst::FnSpace)
+                  .iter()
+                  .map(|def| self.mk_param_from_def(def))
+                  .collect();
+        let meth_regions: Vec<ty::Region> =
+            method.generics.regions.get_slice(subst::FnSpace)
+                  .iter()
+                  .map(|def| def.to_early_bound_region())
+                  .collect();
+        trait_ref.substs.clone().with_method(meth_tps, meth_regions)
+    }
 }
 
 impl DebruijnIndex {
@@ -7290,83 +7021,33 @@ impl<'tcx> fmt::Debug for ty::Predicate<'tcx> {
     }
 }
 
-pub fn make_substs_for_receiver_types<'tcx>(tcx: &ty::ctxt<'tcx>,
-                                            trait_ref: &ty::TraitRef<'tcx>,
-                                            method: &ty::Method<'tcx>)
-                                            -> subst::Substs<'tcx>
-{
-    /*!
-     * Substitutes the values for the receiver's type parameters
-     * that are found in method, leaving the method's type parameters
-     * intact.
-     */
-
-    let meth_tps: Vec<Ty> =
-        method.generics.types.get_slice(subst::FnSpace)
-              .iter()
-              .map(|def| ty::mk_param_from_def(tcx, def))
-              .collect();
-    let meth_regions: Vec<ty::Region> =
-        method.generics.regions.get_slice(subst::FnSpace)
-              .iter()
-              .map(|def| def.to_early_bound_region())
-              .collect();
-    trait_ref.substs.clone().with_method(meth_tps, meth_regions)
-}
-
-#[derive(Copy, Clone)]
-pub enum CopyImplementationError {
-    FieldDoesNotImplementCopy(ast::Name),
-    VariantDoesNotImplementCopy(ast::Name),
-    TypeIsStructural,
-    TypeHasDestructor,
-}
-
-pub fn can_type_implement_copy<'a,'tcx>(param_env: &ParameterEnvironment<'a, 'tcx>,
-                                        span: Span,
-                                        self_type: Ty<'tcx>)
-                                        -> Result<(),CopyImplementationError>
-{
-    let tcx = param_env.tcx;
-
-    let did = match self_type.sty {
-        ty::TyStruct(struct_did, substs) => {
-            let fields = ty::struct_fields(tcx, struct_did, substs);
-            for field in &fields {
-                if type_moves_by_default(param_env, span, field.mt.ty) {
-                    return Err(FieldDoesNotImplementCopy(field.name))
-                }
-            }
-            struct_did
-        }
-        ty::TyEnum(enum_did, substs) => {
-            let enum_variants = ty::enum_variants(tcx, enum_did);
-            for variant in enum_variants.iter() {
-                for variant_arg_type in &variant.args {
-                    let substd_arg_type =
-                        variant_arg_type.subst(tcx, substs);
-                    if type_moves_by_default(param_env, span, substd_arg_type) {
-                        return Err(VariantDoesNotImplementCopy(variant.name))
-                    }
-                }
-            }
-            enum_did
-        }
-        _ => return Err(TypeIsStructural),
-    };
-
-    if ty::has_dtor(tcx, did) {
-        return Err(TypeHasDestructor)
-    }
-
-    Ok(())
-}
-
-// FIXME(#20298) -- all of these types basically walk various
+// FIXME(#20298) -- all of these traits basically walk various
 // structures to test whether types/regions are reachable with various
 // properties. It should be possible to express them in terms of one
 // common "walker" trait or something.
 
+/// An "escaping region" is a bound region whose binder is not part of `t`.
+///
+/// So, for example, consider a type like the following, which has two binders:
+///
+///    for<'a> fn(x: for<'b> fn(&'a isize, &'b isize))
+///    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ outer scope
+///                  ^~~~~~~~~~~~~~~~~~~~~~~~~~~~  inner scope
+///
+/// This type has *bound regions* (`'a`, `'b`), but it does not have escaping regions, because the
+/// binders of both `'a` and `'b` are part of the type itself. However, if we consider the *inner
+/// fn type*, that type has an escaping region: `'a`.
+///
+/// Note that what I'm calling an "escaping region" is often just called a "free region". However,
+/// we already use the term "free region". It refers to the regions that we use to represent bound
+/// regions on a fn definition while we are typechecking its body.
+///
+/// To clarify, conceptually there is no particular difference between an "escaping" region and a
+/// "free" region. However, there is a big difference in practice. Basically, when "entering" a
+/// binding level, one is generally required to do some sort of processing to a bound region, such
+/// as replacing it with a fresh/skolemized region, or making an entry in the environment to
+/// represent the scope to which it is attached, etc. An escaping region represents a bound region
+/// for which this processing has not yet been done.
 pub trait RegionEscape {
     fn has_escaping_regions(&self) -> bool {
         self.has_regions_escaping_depth(0)
@@ -7377,7 +7058,7 @@ pub trait RegionEscape {
 
 impl<'tcx> RegionEscape for Ty<'tcx> {
     fn has_regions_escaping_depth(&self, depth: u32) -> bool {
-        ty::type_escapes_depth(*self, depth)
+        self.region_depth > depth
     }
 }
 
@@ -7491,237 +7172,221 @@ impl<'tcx> RegionEscape for ProjectionTy<'tcx> {
     }
 }
 
-pub trait HasProjectionTypes {
-    fn has_projection_types(&self) -> bool;
-}
-
-impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for Vec<T> {
+pub trait HasTypeFlags {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool;
     fn has_projection_types(&self) -> bool {
-        self.iter().any(|p| p.has_projection_types())
+        self.has_type_flags(TypeFlags::HAS_PROJECTION)
     }
-}
-
-impl<'tcx,T:HasProjectionTypes> HasProjectionTypes for VecPerParamSpace<T> {
-    fn has_projection_types(&self) -> bool {
-        self.iter().any(|p| p.has_projection_types())
+    fn references_error(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_TY_ERR)
     }
-}
-
-impl<'tcx> HasProjectionTypes for ClosureTy<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.sig.has_projection_types()
+    fn has_param_types(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_PARAMS)
     }
-}
-
-impl<'tcx> HasProjectionTypes for ClosureUpvar<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.ty.has_projection_types()
+    fn has_self_ty(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_SELF)
     }
-}
-
-impl<'tcx> HasProjectionTypes for ty::InstantiatedPredicates<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.predicates.has_projection_types()
+    fn has_infer_types(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_TY_INFER)
     }
-}
-
-impl<'tcx> HasProjectionTypes for Predicate<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        match *self {
-            Predicate::Trait(ref data) => data.has_projection_types(),
-            Predicate::Equate(ref data) => data.has_projection_types(),
-            Predicate::RegionOutlives(ref data) => data.has_projection_types(),
-            Predicate::TypeOutlives(ref data) => data.has_projection_types(),
-            Predicate::Projection(ref data) => data.has_projection_types(),
-        }
+    fn needs_infer(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_TY_INFER | TypeFlags::HAS_RE_INFER)
     }
-}
-
-impl<'tcx> HasProjectionTypes for TraitPredicate<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.trait_ref.has_projection_types()
+    fn needs_subst(&self) -> bool {
+        self.has_type_flags(TypeFlags::NEEDS_SUBST)
     }
-}
-
-impl<'tcx> HasProjectionTypes for EquatePredicate<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.0.has_projection_types() || self.1.has_projection_types()
+    fn has_closure_types(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_TY_CLOSURE)
     }
-}
-
-impl HasProjectionTypes for Region {
-    fn has_projection_types(&self) -> bool {
-        false
+    fn has_erasable_regions(&self) -> bool {
+        self.has_type_flags(TypeFlags::HAS_RE_EARLY_BOUND |
+                            TypeFlags::HAS_RE_INFER |
+                            TypeFlags::HAS_FREE_REGIONS)
     }
-}
-
-impl<T:HasProjectionTypes,U:HasProjectionTypes> HasProjectionTypes for OutlivesPredicate<T,U> {
-    fn has_projection_types(&self) -> bool {
-        self.0.has_projection_types() || self.1.has_projection_types()
+    /// Indicates whether this value references only 'global'
+    /// types/lifetimes that are the same regardless of what fn we are
+    /// in. This is used for caching. Errs on the side of returning
+    /// false.
+    fn is_global(&self) -> bool {
+        !self.has_type_flags(TypeFlags::HAS_LOCAL_NAMES)
     }
 }
 
-impl<'tcx> HasProjectionTypes for ProjectionPredicate<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.projection_ty.has_projection_types() || self.ty.has_projection_types()
+impl<'tcx,T:HasTypeFlags> HasTypeFlags for Vec<T> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self[..].has_type_flags(flags)
     }
 }
 
-impl<'tcx> HasProjectionTypes for ProjectionTy<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.trait_ref.has_projection_types()
+impl<'tcx,T:HasTypeFlags> HasTypeFlags for [T] {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.iter().any(|p| p.has_type_flags(flags))
     }
 }
 
-impl<'tcx> HasProjectionTypes for Ty<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        ty::type_has_projection(*self)
+impl<'tcx,T:HasTypeFlags> HasTypeFlags for VecPerParamSpace<T> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.iter().any(|p| p.has_type_flags(flags))
     }
 }
 
-impl<'tcx> HasProjectionTypes for TraitRef<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.substs.has_projection_types()
+impl<'tcx> HasTypeFlags for ClosureTy<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.sig.has_type_flags(flags)
     }
 }
 
-impl<'tcx> HasProjectionTypes for subst::Substs<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.types.iter().any(|t| t.has_projection_types())
+impl<'tcx> HasTypeFlags for ClosureUpvar<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.ty.has_type_flags(flags)
     }
 }
 
-impl<'tcx,T> HasProjectionTypes for Option<T>
-    where T : HasProjectionTypes
-{
-    fn has_projection_types(&self) -> bool {
-        self.iter().any(|t| t.has_projection_types())
+impl<'tcx> HasTypeFlags for ty::InstantiatedPredicates<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.predicates.has_type_flags(flags)
     }
 }
 
-impl<'tcx,T> HasProjectionTypes for Rc<T>
-    where T : HasProjectionTypes
-{
-    fn has_projection_types(&self) -> bool {
-        (**self).has_projection_types()
+impl<'tcx> HasTypeFlags for Predicate<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        match *self {
+            Predicate::Trait(ref data) => data.has_type_flags(flags),
+            Predicate::Equate(ref data) => data.has_type_flags(flags),
+            Predicate::RegionOutlives(ref data) => data.has_type_flags(flags),
+            Predicate::TypeOutlives(ref data) => data.has_type_flags(flags),
+            Predicate::Projection(ref data) => data.has_type_flags(flags),
+        }
     }
 }
 
-impl<'tcx,T> HasProjectionTypes for Box<T>
-    where T : HasProjectionTypes
-{
-    fn has_projection_types(&self) -> bool {
-        (**self).has_projection_types()
+impl<'tcx> HasTypeFlags for TraitPredicate<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.trait_ref.has_type_flags(flags)
     }
 }
 
-impl<T> HasProjectionTypes for Binder<T>
-    where T : HasProjectionTypes
-{
-    fn has_projection_types(&self) -> bool {
-        self.0.has_projection_types()
+impl<'tcx> HasTypeFlags for EquatePredicate<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.0.has_type_flags(flags) || self.1.has_type_flags(flags)
     }
 }
 
-impl<'tcx> HasProjectionTypes for FnOutput<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        match *self {
-            FnConverging(t) => t.has_projection_types(),
-            FnDiverging => false,
+impl HasTypeFlags for Region {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        if flags.intersects(TypeFlags::HAS_LOCAL_NAMES) {
+            // does this represent a region that cannot be named in a global
+            // way? used in fulfillment caching.
+            match *self {
+                ty::ReStatic | ty::ReEmpty => {}
+                _ => return true
+            }
         }
+        if flags.intersects(TypeFlags::HAS_RE_INFER) {
+            if let ty::ReInfer(_) = *self {
+                return true;
+            }
+        }
+        false
     }
 }
 
-impl<'tcx> HasProjectionTypes for FnSig<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.inputs.iter().any(|t| t.has_projection_types()) ||
-            self.output.has_projection_types()
+impl<T:HasTypeFlags,U:HasTypeFlags> HasTypeFlags for OutlivesPredicate<T,U> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.0.has_type_flags(flags) || self.1.has_type_flags(flags)
     }
 }
 
-impl<'tcx> HasProjectionTypes for field<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.mt.ty.has_projection_types()
+impl<'tcx> HasTypeFlags for ProjectionPredicate<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.projection_ty.has_type_flags(flags) || self.ty.has_type_flags(flags)
     }
 }
 
-impl<'tcx> HasProjectionTypes for BareFnTy<'tcx> {
-    fn has_projection_types(&self) -> bool {
-        self.sig.has_projection_types()
+impl<'tcx> HasTypeFlags for ProjectionTy<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.trait_ref.has_type_flags(flags)
     }
 }
 
-pub trait ReferencesError {
-    fn references_error(&self) -> bool;
+impl<'tcx> HasTypeFlags for Ty<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.flags.get().intersects(flags)
+    }
 }
 
-impl<T:ReferencesError> ReferencesError for Binder<T> {
-    fn references_error(&self) -> bool {
-        self.0.references_error()
+impl<'tcx> HasTypeFlags for TraitRef<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.substs.has_type_flags(flags)
     }
 }
 
-impl<T:ReferencesError> ReferencesError for Rc<T> {
-    fn references_error(&self) -> bool {
-        (&**self).references_error()
+impl<'tcx> HasTypeFlags for subst::Substs<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.types.has_type_flags(flags) || match self.regions {
+            subst::ErasedRegions => false,
+            subst::NonerasedRegions(ref r) => r.has_type_flags(flags)
+        }
     }
 }
 
-impl<'tcx> ReferencesError for TraitPredicate<'tcx> {
-    fn references_error(&self) -> bool {
-        self.trait_ref.references_error()
+impl<'tcx,T> HasTypeFlags for Option<T>
+    where T : HasTypeFlags
+{
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.iter().any(|t| t.has_type_flags(flags))
     }
 }
 
-impl<'tcx> ReferencesError for ProjectionPredicate<'tcx> {
-    fn references_error(&self) -> bool {
-        self.projection_ty.trait_ref.references_error() || self.ty.references_error()
+impl<'tcx,T> HasTypeFlags for Rc<T>
+    where T : HasTypeFlags
+{
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        (**self).has_type_flags(flags)
     }
 }
 
-impl<'tcx> ReferencesError for TraitRef<'tcx> {
-    fn references_error(&self) -> bool {
-        self.input_types().iter().any(|t| t.references_error())
+impl<'tcx,T> HasTypeFlags for Box<T>
+    where T : HasTypeFlags
+{
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        (**self).has_type_flags(flags)
     }
 }
 
-impl<'tcx> ReferencesError for Ty<'tcx> {
-    fn references_error(&self) -> bool {
-        type_is_error(*self)
+impl<T> HasTypeFlags for Binder<T>
+    where T : HasTypeFlags
+{
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.0.has_type_flags(flags)
     }
 }
 
-impl<'tcx> ReferencesError for Predicate<'tcx> {
-    fn references_error(&self) -> bool {
+impl<'tcx> HasTypeFlags for FnOutput<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
         match *self {
-            Predicate::Trait(ref data) => data.references_error(),
-            Predicate::Equate(ref data) => data.references_error(),
-            Predicate::RegionOutlives(ref data) => data.references_error(),
-            Predicate::TypeOutlives(ref data) => data.references_error(),
-            Predicate::Projection(ref data) => data.references_error(),
+            FnConverging(t) => t.has_type_flags(flags),
+            FnDiverging => false,
         }
     }
 }
 
-impl<A,B> ReferencesError for OutlivesPredicate<A,B>
-    where A : ReferencesError, B : ReferencesError
-{
-    fn references_error(&self) -> bool {
-        self.0.references_error() || self.1.references_error()
+impl<'tcx> HasTypeFlags for FnSig<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.inputs.iter().any(|t| t.has_type_flags(flags)) ||
+            self.output.has_type_flags(flags)
     }
 }
 
-impl<'tcx> ReferencesError for EquatePredicate<'tcx>
-{
-    fn references_error(&self) -> bool {
-        self.0.references_error() || self.1.references_error()
+impl<'tcx> HasTypeFlags for field<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.mt.ty.has_type_flags(flags)
     }
 }
 
-impl ReferencesError for Region
-{
-    fn references_error(&self) -> bool {
-        false
+impl<'tcx> HasTypeFlags for BareFnTy<'tcx> {
+    fn has_type_flags(&self, flags: TypeFlags) -> bool {
+        self.sig.has_type_flags(flags)
     }
 }
 
diff --git a/src/librustc/middle/ty_fold.rs b/src/librustc/middle/ty_fold.rs
index fe89ca751e7..012f5216ed7 100644
--- a/src/librustc/middle/ty_fold.rs
+++ b/src/librustc/middle/ty_fold.rs
@@ -36,7 +36,7 @@
 
 use middle::subst;
 use middle::subst::VecPerParamSpace;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags, RegionEscape};
 use middle::traits;
 
 use std::fmt;
@@ -641,7 +641,7 @@ pub fn super_fold_ty<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
             ty.sty.clone()
         }
     };
-    ty::mk_t(this.tcx(), sty)
+    this.tcx().mk_ty(sty)
 }
 
 pub fn super_fold_substs<'tcx, T: TypeFolder<'tcx>>(this: &mut T,
@@ -896,7 +896,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionReplacer<'a, 'tcx>
     }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty::type_escapes_depth(t, self.current_depth-1) {
+        if !t.has_regions_escaping_depth(self.current_depth-1) {
             return t;
         }
 
@@ -946,7 +946,7 @@ impl<'a, 'tcx> TypeFolder<'tcx> for RegionEraser<'a, 'tcx> {
     fn tcx(&self) -> &ty::ctxt<'tcx> { self.tcx }
 
     fn fold_ty(&mut self, t: Ty<'tcx>) -> Ty<'tcx> {
-        if !ty::type_has_erasable_regions(t) {
+        if !t.has_erasable_regions() {
             return t;
         }
 
diff --git a/src/librustc/middle/ty_relate/mod.rs b/src/librustc/middle/ty_relate/mod.rs
index b8c212fe3f2..4e88e23377d 100644
--- a/src/librustc/middle/ty_relate/mod.rs
+++ b/src/librustc/middle/ty_relate/mod.rs
@@ -113,7 +113,7 @@ fn relate_item_substs<'a,'tcx:'a,R>(relation: &mut R,
 
     let variances;
     let opt_variances = if relation.tcx().variance_computed.get() {
-        variances = ty::item_variances(relation.tcx(), item_def_id);
+        variances = relation.tcx().item_variances(item_def_id);
         Some(&*variances)
     } else {
         None
@@ -469,21 +469,21 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
             if a_id == b_id =>
         {
             let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs));
-            Ok(ty::mk_enum(tcx, a_id, tcx.mk_substs(substs)))
+            Ok(tcx.mk_enum(a_id, tcx.mk_substs(substs)))
         }
 
         (&ty::TyTrait(ref a_), &ty::TyTrait(ref b_)) =>
         {
             let principal = try!(relation.relate(&a_.principal, &b_.principal));
             let bounds = try!(relation.relate(&a_.bounds, &b_.bounds));
-            Ok(ty::mk_trait(tcx, principal, bounds))
+            Ok(tcx.mk_trait(principal, bounds))
         }
 
         (&ty::TyStruct(a_id, a_substs), &ty::TyStruct(b_id, b_substs))
             if a_id == b_id =>
         {
             let substs = try!(relate_item_substs(relation, a_id, a_substs, b_substs));
-            Ok(ty::mk_struct(tcx, a_id, tcx.mk_substs(substs)))
+            Ok(tcx.mk_struct(a_id, tcx.mk_substs(substs)))
         }
 
         (&ty::TyClosure(a_id, a_substs),
@@ -494,33 +494,33 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
             // the (anonymous) type of the same closure expression. So
             // all of their regions should be equated.
             let substs = try!(relate_substs(relation, None, a_substs, b_substs));
-            Ok(ty::mk_closure(tcx, a_id, tcx.mk_substs(substs)))
+            Ok(tcx.mk_closure(a_id, tcx.mk_substs(substs)))
         }
 
         (&ty::TyBox(a_inner), &ty::TyBox(b_inner)) =>
         {
             let typ = try!(relation.relate(&a_inner, &b_inner));
-            Ok(ty::mk_uniq(tcx, typ))
+            Ok(tcx.mk_box(typ))
         }
 
         (&ty::TyRawPtr(ref a_mt), &ty::TyRawPtr(ref b_mt)) =>
         {
             let mt = try!(relation.relate(a_mt, b_mt));
-            Ok(ty::mk_ptr(tcx, mt))
+            Ok(tcx.mk_ptr(mt))
         }
 
         (&ty::TyRef(a_r, ref a_mt), &ty::TyRef(b_r, ref b_mt)) =>
         {
             let r = try!(relation.relate_with_variance(ty::Contravariant, a_r, b_r));
             let mt = try!(relation.relate(a_mt, b_mt));
-            Ok(ty::mk_rptr(tcx, tcx.mk_region(r), mt))
+            Ok(tcx.mk_ref(tcx.mk_region(r), mt))
         }
 
         (&ty::TyArray(a_t, sz_a), &ty::TyArray(b_t, sz_b)) =>
         {
             let t = try!(relation.relate(&a_t, &b_t));
             if sz_a == sz_b {
-                Ok(ty::mk_vec(tcx, t, Some(sz_a)))
+                Ok(tcx.mk_array(t, sz_a))
             } else {
                 Err(ty::terr_fixed_array_size(expected_found(relation, &sz_a, &sz_b)))
             }
@@ -529,7 +529,7 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
         (&ty::TySlice(a_t), &ty::TySlice(b_t)) =>
         {
             let t = try!(relation.relate(&a_t, &b_t));
-            Ok(ty::mk_vec(tcx, t, None))
+            Ok(tcx.mk_slice(t))
         }
 
         (&ty::TyTuple(ref as_), &ty::TyTuple(ref bs)) =>
@@ -538,7 +538,7 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
                 let ts = try!(as_.iter().zip(bs)
                                  .map(|(a, b)| relation.relate(a, b))
                                  .collect::<Result<_, _>>());
-                Ok(ty::mk_tup(tcx, ts))
+                Ok(tcx.mk_tup(ts))
             } else if !(as_.is_empty() || bs.is_empty()) {
                 Err(ty::terr_tuple_size(
                     expected_found(relation, &as_.len(), &bs.len())))
@@ -551,13 +551,13 @@ pub fn super_relate_tys<'a,'tcx:'a,R>(relation: &mut R,
             if a_opt_def_id == b_opt_def_id =>
         {
             let fty = try!(relation.relate(a_fty, b_fty));
-            Ok(ty::mk_bare_fn(tcx, a_opt_def_id, tcx.mk_bare_fn(fty)))
+            Ok(tcx.mk_fn(a_opt_def_id, tcx.mk_bare_fn(fty)))
         }
 
         (&ty::TyProjection(ref a_data), &ty::TyProjection(ref b_data)) =>
         {
             let projection_ty = try!(relation.relate(a_data, b_data));
-            Ok(ty::mk_projection(tcx, projection_ty.trait_ref, projection_ty.item_name))
+            Ok(tcx.mk_projection(projection_ty.trait_ref, projection_ty.item_name))
         }
 
         _ =>
diff --git a/src/librustc/util/ppaux.rs b/src/librustc/util/ppaux.rs
index 0ae089df50d..dcdf457965e 100644
--- a/src/librustc/util/ppaux.rs
+++ b/src/librustc/util/ppaux.rs
@@ -14,13 +14,12 @@ use middle::ty::{BoundRegion, BrAnon, BrNamed};
 use middle::ty::{ReEarlyBound, BrFresh, ctxt};
 use middle::ty::{ReFree, ReScope, ReInfer, ReStatic, Region, ReEmpty};
 use middle::ty::{ReSkolemized, ReVar, BrEnv};
-use middle::ty::{mt, Ty};
 use middle::ty::{TyBool, TyChar, TyStruct, TyEnum};
 use middle::ty::{TyError, TyStr, TyArray, TySlice, TyFloat, TyBareFn};
 use middle::ty::{TyParam, TyRawPtr, TyRef, TyTuple};
 use middle::ty::TyClosure;
 use middle::ty::{TyBox, TyTrait, TyInt, TyUint, TyInfer};
-use middle::ty;
+use middle::ty::{self, mt, Ty, HasTypeFlags};
 use middle::ty_fold::{self, TypeFoldable};
 
 use std::fmt;
@@ -52,7 +51,7 @@ fn fn_sig(f: &mut fmt::Formatter,
 
     match output {
         ty::FnConverging(ty) => {
-            if !ty::type_is_nil(ty) {
+            if !ty.is_nil() {
                 try!(write!(f, " -> {}", ty));
             }
             Ok(())
@@ -72,7 +71,7 @@ fn parameterized<GG>(f: &mut fmt::Formatter,
     where GG: for<'tcx> FnOnce(&ty::ctxt<'tcx>) -> ty::Generics<'tcx>
 {
     let (fn_trait_kind, verbose) = try!(ty::tls::with(|tcx| {
-        try!(write!(f, "{}", ty::item_path_str(tcx, did)));
+        try!(write!(f, "{}", tcx.item_path_str(did)));
         Ok((tcx.lang_items.fn_trait_kind(did), tcx.sess.verbose()))
     }));
 
@@ -155,7 +154,7 @@ fn parameterized<GG>(f: &mut fmt::Formatter,
             ty_params.iter().zip(tps).rev().take_while(|&(def, &actual)| {
                 match def.default {
                     Some(default) => {
-                        if !has_self && ty::type_has_self(default) {
+                        if !has_self && default.has_self_ty() {
                             // In an object type, there is no `Self`, and
                             // thus if the default value references Self,
                             // the user will be required to give an
@@ -266,7 +265,7 @@ impl<'tcx> fmt::Display for TraitAndProjections<'tcx> {
         parameterized(f, trait_ref.substs,
                       trait_ref.def_id,
                       projection_bounds,
-                      |tcx| ty::lookup_trait_def(tcx, trait_ref.def_id).generics.clone())
+                      |tcx| tcx.lookup_trait_def(trait_ref.def_id).generics.clone())
     }
 }
 
@@ -617,7 +616,7 @@ impl fmt::Display for ty::Binder<ty::OutlivesPredicate<ty::Region, ty::Region>>
 impl<'tcx> fmt::Display for ty::TraitRef<'tcx> {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         parameterized(f, self.substs, self.def_id, &[],
-                      |tcx| ty::lookup_trait_def(tcx, self.def_id).generics.clone())
+                      |tcx| tcx.lookup_trait_def(self.def_id).generics.clone())
     }
 }
 
@@ -672,7 +671,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
 
                 if let Some(def_id) = opt_def_id {
                     try!(write!(f, " {{{}}}", ty::tls::with(|tcx| {
-                        ty::item_path_str(tcx, def_id)
+                        tcx.item_path_str(def_id)
                     })));
                 }
                 Ok(())
@@ -682,7 +681,7 @@ impl<'tcx> fmt::Display for ty::TypeVariants<'tcx> {
             TyParam(ref param_ty) => write!(f, "{}", param_ty),
             TyEnum(did, substs) | TyStruct(did, substs) => {
                 parameterized(f, substs, did, &[],
-                              |tcx| ty::lookup_item_type(tcx, did).generics)
+                              |tcx| tcx.lookup_item_type(did).generics)
             }
             TyTrait(ref data) => write!(f, "{}", data),
             ty::TyProjection(ref data) => write!(f, "{}", data),
@@ -721,7 +720,7 @@ impl fmt::Debug for ty::UpvarId {
     fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
         write!(f, "UpvarId({};`{}`;{})",
                self.var_id,
-               ty::tls::with(|tcx| ty::local_var_name_str(tcx, self.var_id)),
+               ty::tls::with(|tcx| tcx.local_var_name_str(self.var_id)),
                self.closure_expr_id)
     }
 }
diff --git a/src/librustc_borrowck/borrowck/check_loans.rs b/src/librustc_borrowck/borrowck/check_loans.rs
index 49933441cf0..9d4fb4c994d 100644
--- a/src/librustc_borrowck/borrowck/check_loans.rs
+++ b/src/librustc_borrowck/borrowck/check_loans.rs
@@ -752,7 +752,7 @@ impl<'a, 'tcx> CheckLoanCtxt<'a, 'tcx> {
             LpExtend(ref lp_base, _, LpInterior(InteriorField(_))) => {
                 match lp_base.to_type().sty {
                     ty::TyStruct(def_id, _) | ty::TyEnum(def_id, _) => {
-                        if ty::has_dtor(self.tcx(), def_id) {
+                        if self.tcx().has_dtor(def_id) {
                             // In the case where the owner implements drop, then
                             // the path must be initialized to prevent a case of
                             // partial reinitialization
diff --git a/src/librustc_borrowck/borrowck/fragments.rs b/src/librustc_borrowck/borrowck/fragments.rs
index 93f5ac529d3..9bd4da28c99 100644
--- a/src/librustc_borrowck/borrowck/fragments.rs
+++ b/src/librustc_borrowck/borrowck/fragments.rs
@@ -353,7 +353,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
         }
 
         (&ty::TyStruct(def_id, ref _substs), None) => {
-            let fields = ty::lookup_struct_fields(tcx, def_id);
+            let fields = tcx.lookup_struct_fields(def_id);
             match *origin_field_name {
                 mc::NamedField(ast_name) => {
                     for f in &fields {
@@ -378,7 +378,7 @@ fn add_fragment_siblings_for_extension<'tcx>(this: &MoveData<'tcx>,
 
         (&ty::TyEnum(enum_def_id, substs), ref enum_variant_info) => {
             let variant_info = {
-                let mut variants = ty::substd_enum_variants(tcx, enum_def_id, substs);
+                let mut variants = tcx.substd_enum_variants(enum_def_id, substs);
                 match *enum_variant_info {
                     Some((variant_def_id, ref _lp2)) =>
                         variants.iter()
@@ -442,9 +442,9 @@ fn add_fragment_sibling_core<'tcx>(this: &MoveData<'tcx>,
     let loan_path_elem = LpInterior(InteriorField(new_field_name));
     let new_lp_type = match new_field_name {
         mc::NamedField(ast_name) =>
-            ty::named_element_ty(tcx, parent.to_type(), ast_name, opt_variant_did),
+            tcx.named_element_ty(parent.to_type(), ast_name, opt_variant_did),
         mc::PositionalField(idx) =>
-            ty::positional_element_ty(tcx, parent.to_type(), idx, opt_variant_did),
+            tcx.positional_element_ty(parent.to_type(), idx, opt_variant_did),
     };
     let new_lp_variant = LpExtend(parent, mc, loan_path_elem);
     let new_lp = LoanPath::new(new_lp_variant, new_lp_type.unwrap());
diff --git a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
index 7b6c54dbaca..2b33dde2cbe 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/gather_moves.rs
@@ -35,7 +35,7 @@ pub fn gather_decl<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
                              decl_id: ast::NodeId,
                              _decl_span: Span,
                              var_id: ast::NodeId) {
-    let ty = ty::node_id_to_type(bccx.tcx, var_id);
+    let ty = bccx.tcx.node_id_to_type(var_id);
     let loan_path = Rc::new(LoanPath::new(LpVar(var_id), ty));
     move_data.add_move(bccx.tcx, loan_path, decl_id, Declared);
 }
@@ -180,7 +180,7 @@ fn check_and_get_illegal_move_origin<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         mc::cat_interior(ref b, mc::InteriorElement(Kind::Pattern, _)) => {
             match b.ty.sty {
                 ty::TyStruct(did, _) | ty::TyEnum(did, _) => {
-                    if ty::has_dtor(bccx.tcx, did) {
+                    if bccx.tcx.has_dtor(did) {
                         Some(cmt.clone())
                     } else {
                         check_and_get_illegal_move_origin(bccx, b)
diff --git a/src/librustc_borrowck/borrowck/gather_loans/mod.rs b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
index f00eb872642..44a4a0d2504 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/mod.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/mod.rs
@@ -490,7 +490,7 @@ struct StaticInitializerCtxt<'a, 'tcx: 'a> {
 impl<'a, 'tcx, 'v> Visitor<'v> for StaticInitializerCtxt<'a, 'tcx> {
     fn visit_expr(&mut self, ex: &Expr) {
         if let ast::ExprAddrOf(mutbl, ref base) = ex.node {
-            let param_env = ty::empty_parameter_environment(self.bccx.tcx);
+            let param_env = self.bccx.tcx.empty_parameter_environment();
             let mc = mc::MemCategorizationContext::new(&param_env);
             let base_cmt = mc.cat_expr(&**base).unwrap();
             let borrow_kind = ty::BorrowKind::from_mutbl(mutbl);
diff --git a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
index 9a29ed91339..5baabebea11 100644
--- a/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
+++ b/src/librustc_borrowck/borrowck/gather_loans/move_error.rs
@@ -137,7 +137,7 @@ fn report_cannot_move_out_of<'a, 'tcx>(bccx: &BorrowckCtxt<'a, 'tcx>,
         mc::cat_interior(ref b, mc::InteriorField(_)) => {
             match b.ty.sty {
                 ty::TyStruct(did, _) |
-                ty::TyEnum(did, _) if ty::has_dtor(bccx.tcx, did) => {
+                ty::TyEnum(did, _) if bccx.tcx.has_dtor(did) => {
                     bccx.span_err(
                         move_from.span,
                         &format!("cannot move out of type `{}`, \
diff --git a/src/librustc_borrowck/borrowck/mod.rs b/src/librustc_borrowck/borrowck/mod.rs
index ec92c2ed05a..4f726044a1b 100644
--- a/src/librustc_borrowck/borrowck/mod.rs
+++ b/src/librustc_borrowck/borrowck/mod.rs
@@ -29,8 +29,8 @@ use rustc::middle::dataflow::DataFlowOperator;
 use rustc::middle::dataflow::KillFrom;
 use rustc::middle::expr_use_visitor as euv;
 use rustc::middle::free_region::FreeRegionMap;
-use rustc::middle::infer::error_reporting::note_and_explain_region;
 use rustc::middle::mem_categorization as mc;
+use rustc::middle::mem_categorization::Typer;
 use rustc::middle::region;
 use rustc::middle::ty::{self, Ty};
 
@@ -662,7 +662,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                                      .map
                                                      .find(the_move.id) {
                     Some(ast_map::NodeExpr(expr)) => {
-                        (ty::expr_ty_adjusted(self.tcx, &*expr), expr.span)
+                        (self.tcx.expr_ty_adjusted(&*expr), expr.span)
                     }
                     r => {
                         self.tcx.sess.bug(&format!("MoveExpr({}) maps to \
@@ -696,7 +696,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             }
 
             move_data::MovePat => {
-                let pat_ty = ty::node_id_to_type(self.tcx, the_move.id);
+                let pat_ty = self.tcx.node_id_to_type(the_move.id);
                 let span = self.tcx.map.span(the_move.id);
                 self.tcx.sess.span_note(span,
                     &format!("`{}` moved here{} because it has type `{}`, \
@@ -713,7 +713,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                                      .map
                                                      .find(the_move.id) {
                     Some(ast_map::NodeExpr(expr)) => {
-                        (ty::expr_ty_adjusted(self.tcx, &*expr), expr.span)
+                        (self.tcx.expr_ty_adjusted(&*expr), expr.span)
                     }
                     r => {
                         self.tcx.sess.bug(&format!("Captured({}) maps to \
@@ -747,7 +747,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                                     -> (&'static str, &'static str) {
             match ty.sty {
                 _ => {
-                    if ty::type_moves_by_default(param_env, span, ty) {
+                    if param_env.type_moves_by_default(ty, span) {
                         ("non-copyable",
                          "perhaps you meant to use `clone()`?")
                     } else {
@@ -997,13 +997,11 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
             }
 
             err_out_of_scope(super_scope, sub_scope) => {
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "reference must be valid for ",
                     sub_scope,
                     "...");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     "...but borrowed value is only valid for ",
                     super_scope,
                     "");
@@ -1020,14 +1018,12 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                     }
                     None => self.cmt_to_string(&*err.cmt),
                 };
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     &format!("{} would have to be valid for ",
                             descr),
                     loan_scope,
                     "...");
-                note_and_explain_region(
-                    self.tcx,
+                self.tcx.note_and_explain_region(
                     &format!("...but {} is only valid for ", descr),
                     ptr_scope,
                     "");
@@ -1041,14 +1037,14 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
         match loan_path.kind {
             LpUpvar(ty::UpvarId{ var_id: id, closure_expr_id: _ }) |
             LpVar(id) => {
-                out.push_str(&ty::local_var_name_str(self.tcx, id));
+                out.push_str(&self.tcx.local_var_name_str(id));
             }
 
             LpDowncast(ref lp_base, variant_def_id) => {
                 out.push('(');
                 self.append_loan_path_to_string(&**lp_base, out);
                 out.push_str(DOWNCAST_PRINTED_OPERATOR);
-                out.push_str(&ty::item_path_str(self.tcx, variant_def_id));
+                out.push_str(&self.tcx.item_path_str(variant_def_id));
                 out.push(')');
             }
 
@@ -1094,7 +1090,7 @@ impl<'a, 'tcx> BorrowckCtxt<'a, 'tcx> {
                 out.push('(');
                 self.append_autoderefd_loan_path_to_string(&**lp_base, out);
                 out.push(':');
-                out.push_str(&ty::item_path_str(self.tcx, variant_def_id));
+                out.push_str(&self.tcx.item_path_str(variant_def_id));
                 out.push(')');
             }
 
@@ -1184,7 +1180,7 @@ impl<'tcx> fmt::Debug for LoanPath<'tcx> {
 
             LpDowncast(ref lp, variant_def_id) => {
                 let variant_str = if variant_def_id.krate == ast::LOCAL_CRATE {
-                    ty::tls::with(|tcx| ty::item_path_str(tcx, variant_def_id))
+                    ty::tls::with(|tcx| tcx.item_path_str(variant_def_id))
                 } else {
                     format!("{:?}", variant_def_id)
                 };
@@ -1216,7 +1212,7 @@ impl<'tcx> fmt::Display for LoanPath<'tcx> {
 
             LpDowncast(ref lp, variant_def_id) => {
                 let variant_str = if variant_def_id.krate == ast::LOCAL_CRATE {
-                    ty::tls::with(|tcx| ty::item_path_str(tcx, variant_def_id))
+                    ty::tls::with(|tcx| tcx.item_path_str(variant_def_id))
                 } else {
                     format!("{:?}", variant_def_id)
                 };
diff --git a/src/librustc_driver/driver.rs b/src/librustc_driver/driver.rs
index d3297562aef..1ad3f53c328 100644
--- a/src/librustc_driver/driver.rs
+++ b/src/librustc_driver/driver.rs
@@ -648,16 +648,16 @@ pub fn phase_3_run_analysis_passes<'tcx, F, R>(sess: Session,
     time(time_passes, "static item recursion checking", (), |_|
          middle::check_static_recursion::check_crate(&sess, krate, &def_map, &ast_map));
 
-    ty::with_ctxt(sess,
-                  arenas,
-                  def_map,
-                  named_region_map,
-                  ast_map,
-                  freevars,
-                  region_map,
-                  lang_items,
-                  stability::Index::new(krate),
-                  |tcx| {
+    ty::ctxt::create_and_enter(sess,
+                               arenas,
+                               def_map,
+                               named_region_map,
+                               ast_map,
+                               freevars,
+                               region_map,
+                               lang_items,
+                               stability::Index::new(krate),
+                               |tcx| {
 
         // passes are timed inside typeck
         typeck::check_crate(tcx, trait_map);
diff --git a/src/librustc_driver/pretty.rs b/src/librustc_driver/pretty.rs
index a40cb94204d..610f3f3a75e 100644
--- a/src/librustc_driver/pretty.rs
+++ b/src/librustc_driver/pretty.rs
@@ -317,7 +317,7 @@ impl<'a, 'tcx> pprust::PpAnn for TypedAnnotation<'a, 'tcx> {
                 try!(pp::word(&mut s.s, "as"));
                 try!(pp::space(&mut s.s));
                 try!(pp::word(&mut s.s,
-                              &ty::expr_ty(self.tcx, expr).to_string()));
+                              &self.tcx.expr_ty(expr).to_string()));
                 s.pclose()
             }
             _ => Ok(())
diff --git a/src/librustc_driver/test.rs b/src/librustc_driver/test.rs
index 62c8e0368d9..5ec6e293684 100644
--- a/src/librustc_driver/test.rs
+++ b/src/librustc_driver/test.rs
@@ -22,7 +22,7 @@ use rustc_typeck::middle::resolve_lifetime;
 use rustc_typeck::middle::stability;
 use rustc_typeck::middle::subst;
 use rustc_typeck::middle::subst::Subst;
-use rustc_typeck::middle::ty::{self, Ty};
+use rustc_typeck::middle::ty::{self, Ty, RegionEscape};
 use rustc_typeck::middle::ty_relate::TypeRelation;
 use rustc_typeck::middle::infer;
 use rustc_typeck::middle::infer::lub::Lub;
@@ -130,16 +130,16 @@ fn test_env<F>(source_string: &str,
         resolve::resolve_crate(&sess, &ast_map, resolve::MakeGlobMap::No);
     let named_region_map = resolve_lifetime::krate(&sess, krate, &def_map);
     let region_map = region::resolve_crate(&sess, krate);
-    ty::with_ctxt(sess,
-                  &arenas,
-                  def_map,
-                  named_region_map,
-                  ast_map,
-                  freevars,
-                  region_map,
-                  lang_items,
-                  stability::Index::new(krate),
-                  |tcx| {
+    ty::ctxt::create_and_enter(sess,
+                               &arenas,
+                               def_map,
+                               named_region_map,
+                               ast_map,
+                               freevars,
+                               region_map,
+                               lang_items,
+                               stability::Index::new(krate),
+                               |tcx| {
         let infcx = infer::new_infer_ctxt(tcx);
         body(Env { infcx: &infcx });
         let free_regions = FreeRegionMap::new();
@@ -256,30 +256,29 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
                 -> Ty<'tcx>
     {
         let input_args = input_tys.iter().cloned().collect();
-        ty::mk_bare_fn(self.infcx.tcx,
-                       None,
-                       self.infcx.tcx.mk_bare_fn(ty::BareFnTy {
-                           unsafety: ast::Unsafety::Normal,
-                           abi: abi::Rust,
-                           sig: ty::Binder(ty::FnSig {
-                               inputs: input_args,
-                               output: ty::FnConverging(output_ty),
-                               variadic: false
-                           })
-                       }))
+        self.infcx.tcx.mk_fn(None,
+            self.infcx.tcx.mk_bare_fn(ty::BareFnTy {
+                unsafety: ast::Unsafety::Normal,
+                abi: abi::Rust,
+                sig: ty::Binder(ty::FnSig {
+                    inputs: input_args,
+                    output: ty::FnConverging(output_ty),
+                    variadic: false
+                })
+            }))
     }
 
     pub fn t_nil(&self) -> Ty<'tcx> {
-        ty::mk_nil(self.infcx.tcx)
+        self.infcx.tcx.mk_nil()
     }
 
     pub fn t_pair(&self, ty1: Ty<'tcx>, ty2: Ty<'tcx>) -> Ty<'tcx> {
-        ty::mk_tup(self.infcx.tcx, vec![ty1, ty2])
+        self.infcx.tcx.mk_tup(vec![ty1, ty2])
     }
 
     pub fn t_param(&self, space: subst::ParamSpace, index: u32) -> Ty<'tcx> {
         let name = format!("T{}", index);
-        ty::mk_param(self.infcx.tcx, space, index, token::intern(&name[..]))
+        self.infcx.tcx.mk_param(space, index, token::intern(&name[..]))
     }
 
     pub fn re_early_bound(&self,
@@ -302,16 +301,14 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
     }
 
     pub fn t_rptr(&self, r: ty::Region) -> Ty<'tcx> {
-        ty::mk_imm_rptr(self.infcx.tcx,
-                        self.infcx.tcx.mk_region(r),
-                        self.tcx().types.isize)
+        self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r),
+                                   self.tcx().types.isize)
     }
 
     pub fn t_rptr_late_bound(&self, id: u32) -> Ty<'tcx> {
         let r = self.re_late_bound_with_debruijn(id, ty::DebruijnIndex::new(1));
-        ty::mk_imm_rptr(self.infcx.tcx,
-                        self.infcx.tcx.mk_region(r),
-                        self.tcx().types.isize)
+        self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r),
+                                   self.tcx().types.isize)
     }
 
     pub fn t_rptr_late_bound_with_debruijn(&self,
@@ -319,15 +316,14 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
                                            debruijn: ty::DebruijnIndex)
                                            -> Ty<'tcx> {
         let r = self.re_late_bound_with_debruijn(id, debruijn);
-        ty::mk_imm_rptr(self.infcx.tcx,
-                        self.infcx.tcx.mk_region(r),
-                        self.tcx().types.isize)
+        self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r),
+                                   self.tcx().types.isize)
     }
 
     pub fn t_rptr_scope(&self, id: ast::NodeId) -> Ty<'tcx> {
         let r = ty::ReScope(CodeExtent::from_node_id(id));
-        ty::mk_imm_rptr(self.infcx.tcx, self.infcx.tcx.mk_region(r),
-                        self.tcx().types.isize)
+        self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r),
+                                   self.tcx().types.isize)
     }
 
     pub fn re_free(&self, nid: ast::NodeId, id: u32) -> ty::Region {
@@ -337,15 +333,13 @@ impl<'a, 'tcx> Env<'a, 'tcx> {
 
     pub fn t_rptr_free(&self, nid: ast::NodeId, id: u32) -> Ty<'tcx> {
         let r = self.re_free(nid, id);
-        ty::mk_imm_rptr(self.infcx.tcx,
-                        self.infcx.tcx.mk_region(r),
-                        self.tcx().types.isize)
+        self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(r),
+                                   self.tcx().types.isize)
     }
 
     pub fn t_rptr_static(&self) -> Ty<'tcx> {
-        ty::mk_imm_rptr(self.infcx.tcx,
-                        self.infcx.tcx.mk_region(ty::ReStatic),
-                        self.tcx().types.isize)
+        self.infcx.tcx.mk_imm_ref(self.infcx.tcx.mk_region(ty::ReStatic),
+                                   self.tcx().types.isize)
     }
 
     pub fn dummy_type_trace(&self) -> infer::TypeTrace<'tcx> {
@@ -745,22 +739,22 @@ fn escaping() {
         // Situation:
         // Theta = [A -> &'a foo]
 
-        assert!(!ty::type_has_escaping_regions(env.t_nil()));
+        assert!(!env.t_nil().has_escaping_regions());
 
         let t_rptr_free1 = env.t_rptr_free(0, 1);
-        assert!(!ty::type_has_escaping_regions(t_rptr_free1));
+        assert!(!t_rptr_free1.has_escaping_regions());
 
         let t_rptr_bound1 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(1));
-        assert!(ty::type_has_escaping_regions(t_rptr_bound1));
+        assert!(t_rptr_bound1.has_escaping_regions());
 
         let t_rptr_bound2 = env.t_rptr_late_bound_with_debruijn(1, ty::DebruijnIndex::new(2));
-        assert!(ty::type_has_escaping_regions(t_rptr_bound2));
+        assert!(t_rptr_bound2.has_escaping_regions());
 
         // t_fn = fn(A)
         let t_param = env.t_param(subst::TypeSpace, 0);
-        assert!(!ty::type_has_escaping_regions(t_param));
+        assert!(!t_param.has_escaping_regions());
         let t_fn = env.t_fn(&[t_param], env.t_nil());
-        assert!(!ty::type_has_escaping_regions(t_fn));
+        assert!(!t_fn.has_escaping_regions());
     })
 }
 
@@ -804,9 +798,9 @@ fn walk_ty() {
         let tcx = env.infcx.tcx;
         let int_ty = tcx.types.isize;
         let uint_ty = tcx.types.usize;
-        let tup1_ty = ty::mk_tup(tcx, vec!(int_ty, uint_ty, int_ty, uint_ty));
-        let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
-        let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
+        let tup1_ty = tcx.mk_tup(vec!(int_ty, uint_ty, int_ty, uint_ty));
+        let tup2_ty = tcx.mk_tup(vec!(tup1_ty, tup1_ty, uint_ty));
+        let uniq_ty = tcx.mk_box(tup2_ty);
         let walked: Vec<_> = uniq_ty.walk().collect();
         assert_eq!(walked, [uniq_ty,
                             tup2_ty,
@@ -822,9 +816,9 @@ fn walk_ty_skip_subtree() {
         let tcx = env.infcx.tcx;
         let int_ty = tcx.types.isize;
         let uint_ty = tcx.types.usize;
-        let tup1_ty = ty::mk_tup(tcx, vec!(int_ty, uint_ty, int_ty, uint_ty));
-        let tup2_ty = ty::mk_tup(tcx, vec!(tup1_ty, tup1_ty, uint_ty));
-        let uniq_ty = ty::mk_uniq(tcx, tup2_ty);
+        let tup1_ty = tcx.mk_tup(vec!(int_ty, uint_ty, int_ty, uint_ty));
+        let tup2_ty = tcx.mk_tup(vec!(tup1_ty, tup1_ty, uint_ty));
+        let uniq_ty = tcx.mk_box(tup2_ty);
 
         // types we expect to see (in order), plus a boolean saying
         // whether to skip the subtree.
diff --git a/src/librustc_lint/builtin.rs b/src/librustc_lint/builtin.rs
index ffb860283dd..8fe07da1579 100644
--- a/src/librustc_lint/builtin.rs
+++ b/src/librustc_lint/builtin.rs
@@ -30,6 +30,7 @@
 
 use metadata::{csearch, decoder};
 use middle::def::*;
+use middle::mem_categorization::Typer;
 use middle::subst::Substs;
 use middle::ty::{self, Ty};
 use middle::{def, pat_util, stability};
@@ -142,7 +143,7 @@ impl LintPass for TypeLimits {
                         }
                     },
                     _ => {
-                        let t = ty::expr_ty(cx.tcx, &**expr);
+                        let t = cx.tcx.expr_ty(&**expr);
                         match t.sty {
                             ty::TyUint(_) => {
                                 cx.span_lint(UNSIGNED_NEGATION, e.span,
@@ -168,7 +169,7 @@ impl LintPass for TypeLimits {
                 }
 
                 if is_shift_binop(binop.node) {
-                    let opt_ty_bits = match ty::expr_ty(cx.tcx, &**l).sty {
+                    let opt_ty_bits = match cx.tcx.expr_ty(&**l).sty {
                         ty::TyInt(t) => Some(int_ty_bits(t, cx.sess().target.int_type)),
                         ty::TyUint(t) => Some(uint_ty_bits(t, cx.sess().target.uint_type)),
                         _ => None
@@ -193,7 +194,7 @@ impl LintPass for TypeLimits {
                 }
             },
             ast::ExprLit(ref lit) => {
-                match ty::expr_ty(cx.tcx, e).sty {
+                match cx.tcx.expr_ty(e).sty {
                     ty::TyInt(t) => {
                         match lit.node {
                             ast::LitInt(v, ast::SignedIntLit(_, ast::Plus)) |
@@ -343,7 +344,7 @@ impl LintPass for TypeLimits {
             } else {
                 binop
             };
-            match ty::expr_ty(tcx, expr).sty {
+            match tcx.expr_ty(expr).sty {
                 ty::TyInt(int_ty) => {
                     let (min, max) = int_ty_range(int_ty);
                     let lit_val: i64 = match lit.node {
@@ -412,7 +413,7 @@ impl<'a, 'tcx> ImproperCTypesVisitor<'a, 'tcx> {
                     None => panic!("ast_ty_to_ty_cache was incomplete after typeck!")
                 };
 
-                if !ty::is_ffi_safe(self.cx.tcx, tty) {
+                if !tty.is_ffi_safe(self.cx.tcx) {
                     self.cx.span_lint(IMPROPER_CTYPES, sp,
                                       "found type without foreign-function-safe \
                                        representation annotation in foreign module, consider \
@@ -482,20 +483,11 @@ pub struct BoxPointers;
 impl BoxPointers {
     fn check_heap_type<'a, 'tcx>(&self, cx: &Context<'a, 'tcx>,
                                  span: Span, ty: Ty<'tcx>) {
-        let mut n_uniq: usize = 0;
-        ty::fold_ty(cx.tcx, ty, |t| {
-            match t.sty {
-                ty::TyBox(_) => {
-                    n_uniq += 1;
-                }
-                _ => ()
-            };
-            t
-        });
-
-        if n_uniq > 0 {
-            let m = format!("type uses owned (Box type) pointers: {}", ty);
-            cx.span_lint(BOX_POINTERS, span, &m[..]);
+        for leaf_ty in ty.walk() {
+            if let ty::TyBox(_) = leaf_ty.sty {
+                let m = format!("type uses owned (Box type) pointers: {}", ty);
+                cx.span_lint(BOX_POINTERS, span, &m);
+            }
         }
     }
 }
@@ -512,7 +504,7 @@ impl LintPass for BoxPointers {
             ast::ItemEnum(..) |
             ast::ItemStruct(..) =>
                 self.check_heap_type(cx, it.span,
-                                     ty::node_id_to_type(cx.tcx, it.id)),
+                                     cx.tcx.node_id_to_type(it.id)),
             _ => ()
         }
 
@@ -521,7 +513,7 @@ impl LintPass for BoxPointers {
             ast::ItemStruct(ref struct_def, _) => {
                 for struct_field in &struct_def.fields {
                     self.check_heap_type(cx, struct_field.span,
-                                         ty::node_id_to_type(cx.tcx, struct_field.node.id));
+                                         cx.tcx.node_id_to_type(struct_field.node.id));
                 }
             }
             _ => ()
@@ -529,7 +521,7 @@ impl LintPass for BoxPointers {
     }
 
     fn check_expr(&mut self, cx: &Context, e: &ast::Expr) {
-        let ty = ty::expr_ty(cx.tcx, e);
+        let ty = cx.tcx.expr_ty(e);
         self.check_heap_type(cx, e.span, ty);
     }
 }
@@ -582,13 +574,13 @@ impl LintPass for RawPointerDerive {
             ast::ItemImpl(_, _, _, ref t_ref_opt, _, _) => {
                 // Deriving the Copy trait does not cause a warning
                 if let &Some(ref trait_ref) = t_ref_opt {
-                    let def_id = ty::trait_ref_to_def_id(cx.tcx, trait_ref);
+                    let def_id = cx.tcx.trait_ref_to_def_id(trait_ref);
                     if Some(def_id) == cx.tcx.lang_items.copy_trait() {
                         return;
                     }
                 }
 
-                match ty::node_id_to_type(cx.tcx, item.id).sty {
+                match cx.tcx.node_id_to_type(item.id).sty {
                     ty::TyEnum(did, _) => did,
                     ty::TyStruct(did, _) => did,
                     _ => return,
@@ -732,7 +724,7 @@ impl LintPass for UnusedResults {
             return;
         }
 
-        let t = ty::expr_ty(cx.tcx, expr);
+        let t = cx.tcx.expr_ty(expr);
         let warned = match t.sty {
             ty::TyTuple(ref tys) if tys.is_empty() => return,
             ty::TyBool => return,
@@ -877,7 +869,7 @@ fn method_context(cx: &Context, id: ast::NodeId, span: Span) -> MethodContext {
         Some(item) => match item.container() {
             ty::TraitContainer(..) => MethodContext::TraitDefaultImpl,
             ty::ImplContainer(cid) => {
-                match ty::impl_trait_ref(cx.tcx, cid) {
+                match cx.tcx.impl_trait_ref(cid) {
                     Some(_) => MethodContext::TraitImpl,
                     None => MethodContext::PlainImpl
                 }
@@ -1601,7 +1593,7 @@ impl LintPass for MissingDoc {
             ast::ItemImpl(_, _, _, Some(ref trait_ref), _, ref impl_items) => {
                 // If the trait is private, add the impl items to private_traits so they don't get
                 // reported for missing docs.
-                let real_trait = ty::trait_ref_to_def_id(cx.tcx, trait_ref);
+                let real_trait = cx.tcx.trait_ref_to_def_id(trait_ref);
                 match cx.tcx.map.find(real_trait.node) {
                     Some(ast_map::NodeItem(item)) => if item.vis == ast::Visibility::Inherited {
                         for itm in impl_items {
@@ -1699,23 +1691,23 @@ impl LintPass for MissingCopyImplementations {
                 if ast_generics.is_parameterized() {
                     return;
                 }
-                ty::mk_struct(cx.tcx, local_def(item.id),
-                              cx.tcx.mk_substs(Substs::empty()))
+                cx.tcx.mk_struct(local_def(item.id),
+                                 cx.tcx.mk_substs(Substs::empty()))
             }
             ast::ItemEnum(_, ref ast_generics) => {
                 if ast_generics.is_parameterized() {
                     return;
                 }
-                ty::mk_enum(cx.tcx, local_def(item.id),
-                            cx.tcx.mk_substs(Substs::empty()))
+                cx.tcx.mk_enum(local_def(item.id),
+                               cx.tcx.mk_substs(Substs::empty()))
             }
             _ => return,
         };
-        let parameter_environment = ty::empty_parameter_environment(cx.tcx);
-        if !ty::type_moves_by_default(&parameter_environment, item.span, ty) {
+        let parameter_environment = cx.tcx.empty_parameter_environment();
+        if !parameter_environment.type_moves_by_default(ty, item.span) {
             return;
         }
-        if ty::can_type_implement_copy(&parameter_environment, item.span, ty).is_ok() {
+        if parameter_environment.can_type_implement_copy(ty, item.span).is_ok() {
             cx.span_lint(MISSING_COPY_IMPLEMENTATIONS,
                          item.span,
                          "type could implement `Copy`; consider adding `impl \
@@ -1763,11 +1755,11 @@ impl LintPass for MissingDebugImplementations {
         };
 
         if self.impling_types.is_none() {
-            let debug_def = ty::lookup_trait_def(cx.tcx, debug);
+            let debug_def = cx.tcx.lookup_trait_def(debug);
             let mut impls = NodeSet();
             debug_def.for_each_impl(cx.tcx, |d| {
                 if d.krate == ast::LOCAL_CRATE {
-                    if let Some(ty_def) = ty::ty_to_def_id(ty::node_id_to_type(cx.tcx, d.node)) {
+                    if let Some(ty_def) = cx.tcx.node_id_to_type(d.node).ty_to_def_id() {
                         impls.insert(ty_def.node);
                     }
                 }
@@ -1878,7 +1870,7 @@ impl LintPass for UnconditionalRecursion {
             visit::FkFnBlock => return
         };
 
-        let impl_def_id = ty::impl_of_method(cx.tcx, local_def(id))
+        let impl_def_id = cx.tcx.impl_of_method(local_def(id))
             .unwrap_or(local_def(ast::DUMMY_NODE_ID));
         assert!(ast_util::is_local(impl_def_id));
         let impl_node_id = impl_def_id.node;
@@ -2010,7 +2002,7 @@ impl LintPass for UnconditionalRecursion {
                     // method instead.
                     ty::MethodTypeParam(
                         ty::MethodParam { ref trait_ref, method_num, impl_def_id: None, }) => {
-                        ty::trait_item(tcx, trait_ref.def_id, method_num).def_id()
+                        tcx.trait_item(trait_ref.def_id, method_num).def_id()
                     }
 
                     // The `impl` is known, so we check that with a
@@ -2175,11 +2167,11 @@ impl LintPass for MutableTransmutes {
                 ast::ExprPath(..) => (),
                 _ => return None
             }
-            if let DefFn(did, _) = ty::resolve_expr(cx.tcx, expr) {
+            if let DefFn(did, _) = cx.tcx.resolve_expr(expr) {
                 if !def_id_is_transmute(cx, did) {
                     return None;
                 }
-                let typ = ty::node_id_to_type(cx.tcx, expr.id);
+                let typ = cx.tcx.node_id_to_type(expr.id);
                 match typ.sty {
                     ty::TyBareFn(_, ref bare_fn) if bare_fn.abi == RustIntrinsic => {
                         if let ty::FnConverging(to) = bare_fn.sig.0.output {
@@ -2194,11 +2186,11 @@ impl LintPass for MutableTransmutes {
         }
 
         fn def_id_is_transmute(cx: &Context, def_id: DefId) -> bool {
-            match ty::lookup_item_type(cx.tcx, def_id).ty.sty {
+            match cx.tcx.lookup_item_type(def_id).ty.sty {
                 ty::TyBareFn(_, ref bfty) if bfty.abi == RustIntrinsic => (),
                 _ => return false
             }
-            ty::with_path(cx.tcx, def_id, |path| match path.last() {
+            cx.tcx.with_path(def_id, |path| match path.last() {
                 Some(ref last) => last.name().as_str() == "transmute",
                 _ => false
             })
@@ -2251,7 +2243,7 @@ impl LintPass for DropWithReprExtern {
             let (drop_impl_did, dtor_self_type) =
                 if dtor_did.krate == ast::LOCAL_CRATE {
                     let impl_did = ctx.tcx.map.get_parent_did(dtor_did.node);
-                    let ty = ty::lookup_item_type(ctx.tcx, impl_did).ty;
+                    let ty = ctx.tcx.lookup_item_type(impl_did).ty;
                     (impl_did, ty)
                 } else {
                     continue;
@@ -2261,9 +2253,9 @@ impl LintPass for DropWithReprExtern {
                 ty::TyEnum(self_type_did, _) |
                 ty::TyStruct(self_type_did, _) |
                 ty::TyClosure(self_type_did, _) => {
-                    let hints = ty::lookup_repr_hints(ctx.tcx, self_type_did);
+                    let hints = ctx.tcx.lookup_repr_hints(self_type_did);
                     if hints.iter().any(|attr| *attr == attr::ReprExtern) &&
-                        ty::ty_dtor(ctx.tcx, self_type_did).has_drop_flag() {
+                        ctx.tcx.ty_dtor(self_type_did).has_drop_flag() {
                         let drop_impl_span = ctx.tcx.map.def_id_span(drop_impl_did,
                                                                      codemap::DUMMY_SP);
                         let self_defn_span = ctx.tcx.map.def_id_span(self_type_did,
diff --git a/src/librustc_privacy/lib.rs b/src/librustc_privacy/lib.rs
index cae93baaf74..24803562fa3 100644
--- a/src/librustc_privacy/lib.rs
+++ b/src/librustc_privacy/lib.rs
@@ -273,7 +273,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for EmbargoVisitor<'a, 'tcx> {
                     }
                     _ => true,
                 };
-                let tr = ty::impl_trait_ref(self.tcx, local_def(item.id));
+                let tr = self.tcx.impl_trait_ref(local_def(item.id));
                 let public_trait = tr.clone().map_or(false, |tr| {
                     !is_local(tr.def_id) ||
                      self.exported_items.contains(&tr.def_id.node)
@@ -423,7 +423,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                             self.def_privacy(id)
                         }
                         ty::ImplContainer(id) => {
-                            match ty::impl_trait_ref(self.tcx, id) {
+                            match self.tcx.impl_trait_ref(id) {
                                 Some(t) => {
                                     debug!("privacy - impl of trait {:?}", id);
                                     self.def_privacy(t.def_id)
@@ -451,7 +451,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                             self.def_privacy(id)
                         }
                         ty::ImplContainer(id) => {
-                            match ty::impl_trait_ref(self.tcx, id) {
+                            match self.tcx.impl_trait_ref(id) {
                                 Some(t) => {
                                     debug!("privacy - impl of trait {:?}", id);
                                     self.def_privacy(t.def_id)
@@ -476,7 +476,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                             self.def_privacy(id)
                         }
                         ty::ImplContainer(id) => {
-                            match ty::impl_trait_ref(self.tcx, id) {
+                            match self.tcx.impl_trait_ref(id) {
                                 Some(t) => {
                                     debug!("privacy - impl of trait {:?}", id);
                                     self.def_privacy(t.def_id)
@@ -537,7 +537,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                         ast::MethodImplItem(..) => {
                             let imp = self.tcx.map
                                           .get_parent_did(closest_private_id);
-                            match ty::impl_trait_ref(self.tcx, imp) {
+                            match self.tcx.impl_trait_ref(imp) {
                                 Some(..) => return Allowable,
                                 _ if ii.vis == ast::Public => {
                                     return Allowable
@@ -696,7 +696,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                    span: Span,
                    id: ast::DefId,
                    name: FieldName) {
-        let fields = ty::lookup_struct_fields(self.tcx, id);
+        let fields = self.tcx.lookup_struct_fields(id);
         let field = match name {
             NamedField(f_name) => {
                 debug!("privacy - check named field {} in struct {:?}", f_name, id);
@@ -709,10 +709,10 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
             return
         }
 
-        let struct_type = ty::lookup_item_type(self.tcx, id).ty;
+        let struct_type = self.tcx.lookup_item_type(id).ty;
         let struct_desc = match struct_type.sty {
             ty::TyStruct(_, _) =>
-                format!("struct `{}`", ty::item_path_str(self.tcx, id)),
+                format!("struct `{}`", self.tcx.item_path_str(id)),
             // struct variant fields have inherited visibility
             ty::TyEnum(..) => return,
             _ => self.tcx.sess.span_bug(span, "can't find struct for field")
@@ -733,7 +733,7 @@ impl<'a, 'tcx> PrivacyVisitor<'a, 'tcx> {
                            name: ast::Name) {
         // If the method is a default method, we need to use the def_id of
         // the default implementation.
-        let method_id = match ty::impl_or_trait_item(self.tcx, method_id) {
+        let method_id = match self.tcx.impl_or_trait_item(method_id) {
             ty::MethodTraitItem(method_type) => {
                 method_type.provided_source.unwrap_or(method_id)
             }
@@ -893,12 +893,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
     fn visit_expr(&mut self, expr: &ast::Expr) {
         match expr.node {
             ast::ExprField(ref base, ident) => {
-                if let ty::TyStruct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
+                if let ty::TyStruct(id, _) = self.tcx.expr_ty_adjusted(&**base).sty {
                     self.check_field(expr.span, id, NamedField(ident.node.name));
                 }
             }
             ast::ExprTupField(ref base, idx) => {
-                if let ty::TyStruct(id, _) = ty::expr_ty_adjusted(self.tcx, &**base).sty {
+                if let ty::TyStruct(id, _) = self.tcx.expr_ty_adjusted(&**base).sty {
                     self.check_field(expr.span, id, UnnamedField(idx.node));
                 }
             }
@@ -917,12 +917,12 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
                 }
             }
             ast::ExprStruct(_, ref fields, _) => {
-                match ty::expr_ty(self.tcx, expr).sty {
+                match self.tcx.expr_ty(expr).sty {
                     ty::TyStruct(ctor_id, _) => {
                         // RFC 736: ensure all unmentioned fields are visible.
                         // Rather than computing the set of unmentioned fields
                         // (i.e. `all_fields - fields`), just check them all.
-                        let all_fields = ty::lookup_struct_fields(self.tcx, ctor_id);
+                        let all_fields = self.tcx.lookup_struct_fields(ctor_id);
                         for field in all_fields {
                             self.check_field(expr.span, ctor_id,
                                              NamedField(field.name));
@@ -950,7 +950,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
             }
             ast::ExprPath(..) => {
                 let guard = |did: ast::DefId| {
-                    let fields = ty::lookup_struct_fields(self.tcx, did);
+                    let fields = self.tcx.lookup_struct_fields(did);
                     let any_priv = fields.iter().any(|f| {
                         f.vis != ast::Public && (
                             !is_local(f.id) ||
@@ -994,7 +994,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
 
         match pattern.node {
             ast::PatStruct(_, ref fields, _) => {
-                match ty::pat_ty(self.tcx, pattern).sty {
+                match self.tcx.pat_ty(pattern).sty {
                     ty::TyStruct(id, _) => {
                         for field in fields {
                             self.check_field(pattern.span, id,
@@ -1025,7 +1025,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for PrivacyVisitor<'a, 'tcx> {
             // Patterns which bind no fields are allowable (the path is check
             // elsewhere).
             ast::PatEnum(_, Some(ref fields)) => {
-                match ty::pat_ty(self.tcx, pattern).sty {
+                match self.tcx.pat_ty(pattern).sty {
                     ty::TyStruct(id, _) => {
                         for (i, field) in fields.iter().enumerate() {
                             if let ast::PatWild(..) = field.node {
@@ -1337,7 +1337,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for VisiblePrivateTypesVisitor<'a, 'tcx> {
                 let not_private_trait =
                     trait_ref.as_ref().map_or(true, // no trait counts as public trait
                                               |tr| {
-                        let did = ty::trait_ref_to_def_id(self.tcx, tr);
+                        let did = self.tcx.trait_ref_to_def_id(tr);
 
                         !is_local(did) || self.trait_is_public(did.node)
                     });
diff --git a/src/librustc_trans/save/dump_csv.rs b/src/librustc_trans/save/dump_csv.rs
index 65d9d9809c9..5ddad0e1947 100644
--- a/src/librustc_trans/save/dump_csv.rs
+++ b/src/librustc_trans/save/dump_csv.rs
@@ -311,7 +311,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         let mut scope_id;
         // The qualname for a method is the trait name or name of the struct in an impl in
         // which the method is declared in, followed by the method's name.
-        let qualname = match ty::impl_of_method(self.tcx, ast_util::local_def(id)) {
+        let qualname = match self.tcx.impl_of_method(ast_util::local_def(id)) {
             Some(impl_id) => match self.tcx.map.get(impl_id.node) {
                 NodeItem(item) => {
                     scope_id = item.id;
@@ -320,11 +320,11 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                             let mut result = String::from("<");
                             result.push_str(&ty_to_string(&**ty));
 
-                            match ty::trait_of_item(self.tcx, ast_util::local_def(id)) {
+                            match self.tcx.trait_of_item(ast_util::local_def(id)) {
                                 Some(def_id) => {
                                     result.push_str(" as ");
                                     result.push_str(
-                                        &ty::item_path_str(self.tcx, def_id));
+                                        &self.tcx.item_path_str(def_id));
                                 },
                                 None => {}
                             }
@@ -344,12 +344,12 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                  impl_id.node, id, self.tcx.map.get(impl_id.node)));
                 },
             },
-            None => match ty::trait_of_item(self.tcx, ast_util::local_def(id)) {
+            None => match self.tcx.trait_of_item(ast_util::local_def(id)) {
                 Some(def_id) => {
                     scope_id = def_id.node;
                     match self.tcx.map.get(def_id.node) {
                         NodeItem(_) => {
-                            format!("::{}", ty::item_path_str(self.tcx, def_id))
+                            format!("::{}", self.tcx.item_path_str(def_id))
                         }
                         _ => {
                             self.sess.span_bug(span,
@@ -368,7 +368,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         let qualname = &format!("{}::{}", qualname, &token::get_name(name));
 
         // record the decl for this def (if it has one)
-        let decl_id = ty::trait_item_of_item(self.tcx, ast_util::local_def(id))
+        let decl_id = self.tcx.trait_item_of_item(ast_util::local_def(id))
             .and_then(|new_id| {
                 let def_id = new_id.def_id();
                 if def_id.node != 0 && def_id != ast_util::local_def(id) {
@@ -776,10 +776,10 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             def::DefMethod(declid, provenence) => {
                 let sub_span = self.span.sub_span_for_meth_name(span);
                 let defid = if declid.krate == ast::LOCAL_CRATE {
-                    let ti = ty::impl_or_trait_item(self.tcx, declid);
+                    let ti = self.tcx.impl_or_trait_item(declid);
                     match provenence {
                         def::FromTrait(def_id) => {
-                            Some(ty::trait_items(self.tcx, def_id)
+                            Some(self.tcx.trait_items(def_id)
                                     .iter()
                                     .find(|mr| {
                                         mr.name() == ti.name()
@@ -793,10 +793,8 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                                            .unwrap()
                                            .iter()
                                            .find(|mr| {
-                                                ty::impl_or_trait_item(
-                                                    self.tcx,
-                                                    mr.def_id()
-                                                ).name() == ti.name()
+                                                self.tcx.impl_or_trait_item(mr.def_id()).name()
+                                                    == ti.name()
                                             })
                                            .unwrap()
                                            .def_id())
@@ -826,7 +824,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
         // modules or types in the path prefix
         match def {
             def::DefMethod(did, _) => {
-                let ti = ty::impl_or_trait_item(self.tcx, did);
+                let ti = self.tcx.impl_or_trait_item(did);
                 if let ty::MethodTraitItem(m) = ti {
                     if m.explicit_self == ty::StaticExplicitSelfCategory {
                         self.write_sub_path_trait_truncated(path);
@@ -895,14 +893,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             ty::MethodStaticClosure(def_id) => {
                 // method invoked on an object with a concrete type (not a static method)
                 let decl_id =
-                    match ty::trait_item_of_item(self.tcx, def_id) {
+                    match self.tcx.trait_item_of_item(def_id) {
                         None => None,
                         Some(decl_id) => Some(decl_id.def_id()),
                     };
 
                 // This incantation is required if the method referenced is a
                 // trait's default implementation.
-                let def_id = match ty::impl_or_trait_item(self.tcx, def_id) {
+                let def_id = match self.tcx.impl_or_trait_item(def_id) {
                     ty::MethodTraitItem(method) => {
                         method.provided_source.unwrap_or(def_id)
                     }
@@ -915,16 +913,14 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
             }
             ty::MethodTypeParam(ref mp) => {
                 // method invoked on a type parameter
-                let trait_item = ty::trait_item(self.tcx,
-                                                mp.trait_ref.def_id,
-                                                mp.method_num);
+                let trait_item = self.tcx.trait_item(mp.trait_ref.def_id,
+                                                     mp.method_num);
                 (None, Some(trait_item.def_id()))
             }
             ty::MethodTraitObject(ref mo) => {
                 // method invoked on a trait instance
-                let trait_item = ty::trait_item(self.tcx,
-                                                mo.trait_ref.def_id,
-                                                mo.method_num);
+                let trait_item = self.tcx.trait_item(mo.trait_ref.def_id,
+                                                     mo.method_num);
                 (None, Some(trait_item.def_id()))
             }
         };
@@ -953,7 +949,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                     def::DefConst(..) | def::DefAssociatedConst(..) => None,
                     def::DefVariant(_, variant_id, _) => Some(variant_id),
                     _ => {
-                        match ty::ty_to_def_id(ty::node_id_to_type(self.tcx, p.id)) {
+                        match self.tcx.node_id_to_type(p.id).ty_to_def_id() {
                             None => {
                                 self.sess.span_bug(p.span,
                                                    &format!("Could not find struct_def for `{}`",
@@ -965,7 +961,7 @@ impl <'l, 'tcx> DumpCsvVisitor<'l, 'tcx> {
                 };
 
                 if let Some(struct_def) = struct_def {
-                    let struct_fields = ty::lookup_struct_fields(self.tcx, struct_def);
+                    let struct_fields = self.tcx.lookup_struct_fields(struct_def);
                     for &Spanned { node: ref field, span } in fields {
                         let sub_span = self.span.span_for_first_ident(span);
                         for f in &struct_fields {
@@ -1252,10 +1248,10 @@ impl<'l, 'tcx, 'v> Visitor<'v> for DumpCsvVisitor<'l, 'tcx> {
 
                 self.visit_expr(&**sub_ex);
 
-                let ty = &ty::expr_ty_adjusted(self.tcx, &**sub_ex).sty;
+                let ty = &self.tcx.expr_ty_adjusted(&**sub_ex).sty;
                 match *ty {
                     ty::TyStruct(def_id, _) => {
-                        let fields = ty::lookup_struct_fields(self.tcx, def_id);
+                        let fields = self.tcx.lookup_struct_fields(def_id);
                         for (i, f) in fields.iter().enumerate() {
                             if i == idx.node {
                                 let sub_span = self.span.sub_span_after_token(ex.span, token::Dot);
diff --git a/src/librustc_trans/save/mod.rs b/src/librustc_trans/save/mod.rs
index fdfb101ed78..27805b9d833 100644
--- a/src/librustc_trans/save/mod.rs
+++ b/src/librustc_trans/save/mod.rs
@@ -327,10 +327,10 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
     pub fn get_expr_data(&self, expr: &ast::Expr) -> Option<Data> {
         match expr.node {
             ast::ExprField(ref sub_ex, ident) => {
-                let ty = &ty::expr_ty_adjusted(self.tcx, &sub_ex).sty;
+                let ty = &self.tcx.expr_ty_adjusted(&sub_ex).sty;
                 match *ty {
                     ty::TyStruct(def_id, _) => {
-                        let fields = ty::lookup_struct_fields(self.tcx, def_id);
+                        let fields = self.tcx.lookup_struct_fields(def_id);
                         for f in &fields {
                             if f.name == ident.node.name {
                                 let sub_span = self.span_utils.span_for_last_ident(expr.span);
@@ -354,7 +354,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                 }
             }
             ast::ExprStruct(ref path, _, _) => {
-                let ty = &ty::expr_ty_adjusted(&self.tcx, expr).sty;
+                let ty = &self.tcx.expr_ty_adjusted(expr).sty;
                 match *ty {
                     ty::TyStruct(def_id, _) => {
                         let sub_span = self.span_utils.span_for_last_ident(path.span);
@@ -384,7 +384,7 @@ impl<'l, 'tcx: 'l> SaveContext<'l, 'tcx> {
                               struct_id: DefId,
                               parent: NodeId)
                               -> VariableRefData {
-        let fields = ty::lookup_struct_fields(&self.tcx, struct_id);
+        let fields = self.tcx.lookup_struct_fields(struct_id);
         let field_name = get_ident(field_ref.ident.node).to_string();
         for f in &fields {
             if f.name == field_ref.ident.node.name {
diff --git a/src/librustc_trans/trans/_match.rs b/src/librustc_trans/trans/_match.rs
index 4df10ee3d09..47c2a5e579d 100644
--- a/src/librustc_trans/trans/_match.rs
+++ b/src/librustc_trans/trans/_match.rs
@@ -197,6 +197,7 @@ use middle::def::{self, DefMap};
 use middle::expr_use_visitor as euv;
 use middle::lang_items::StrEqFnLangItem;
 use middle::mem_categorization as mc;
+use middle::mem_categorization::Typer;
 use middle::pat_util::*;
 use trans::adt;
 use trans::base::*;
@@ -235,7 +236,7 @@ struct ConstantExpr<'a>(&'a ast::Expr);
 impl<'a> ConstantExpr<'a> {
     fn eq(self, other: ConstantExpr<'a>, tcx: &ty::ctxt) -> bool {
         match const_eval::compare_lit_exprs(tcx, self.0, other.0, None,
-                                            |id| {ty::node_id_item_substs(tcx, id).substs}) {
+                                            |id| {tcx.node_id_item_substs(id).substs}) {
             Some(result) => result == Ordering::Equal,
             None => panic!("compare_list_exprs: type mismatch"),
         }
@@ -279,7 +280,7 @@ impl<'a, 'tcx> Opt<'a, 'tcx> {
         let ccx = bcx.ccx();
         match *self {
             ConstantValue(ConstantExpr(lit_expr), _) => {
-                let lit_ty = ty::node_id_to_type(bcx.tcx(), lit_expr.id);
+                let lit_ty = bcx.tcx().node_id_to_type(lit_expr.id);
                 let (llval, _) = consts::const_expr(ccx, &*lit_expr, bcx.fcx.param_substs, None);
                 let lit_datum = immediate_rvalue(llval, lit_ty);
                 let lit_datum = unpack_datum!(bcx, lit_datum.to_appropriate_datum(bcx));
@@ -562,7 +563,7 @@ fn enter_opt<'a, 'p, 'blk, 'tcx>(
             check_match::Constructor::Variant(def_id)
     };
 
-    let param_env = ty::empty_parameter_environment(bcx.tcx());
+    let param_env = bcx.tcx().empty_parameter_environment();
     let mcx = check_match::MatchCheckCtxt {
         tcx: bcx.tcx(),
         param_env: param_env,
@@ -603,7 +604,7 @@ fn get_branches<'a, 'p, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 let opt_def = tcx.def_map.borrow().get(&cur.id).map(|d| d.full_def());
                 match opt_def {
                     Some(def::DefVariant(enum_id, var_id, _)) => {
-                        let variant = ty::enum_variant_with_id(tcx, enum_id, var_id);
+                        let variant = tcx.enum_variant_with_id(enum_id, var_id);
                         Variant(variant.disr_val,
                                 adt::represent_node(bcx, cur.id),
                                 var_id,
@@ -662,16 +663,20 @@ fn bind_subslice_pat(bcx: Block,
                      offset_right: usize) -> ValueRef {
     let _icx = push_ctxt("match::bind_subslice_pat");
     let vec_ty = node_id_type(bcx, pat_id);
-    let unit_ty = ty::sequence_element_type(bcx.tcx(), ty::type_content(vec_ty));
+    let vec_ty_contents = match vec_ty.sty {
+        ty::TyBox(ty) => ty,
+        ty::TyRef(_, mt) | ty::TyRawPtr(mt) => mt.ty,
+        _ => vec_ty
+    };
+    let unit_ty = vec_ty_contents.sequence_element_type(bcx.tcx());
     let vec_datum = match_datum(val, vec_ty);
     let (base, len) = vec_datum.get_vec_base_and_len(bcx);
 
     let slice_begin = InBoundsGEP(bcx, base, &[C_uint(bcx.ccx(), offset_left)]);
     let slice_len_offset = C_uint(bcx.ccx(), offset_left + offset_right);
     let slice_len = Sub(bcx, len, slice_len_offset, DebugLoc::None);
-    let slice_ty = ty::mk_slice(bcx.tcx(),
-                                bcx.tcx().mk_region(ty::ReStatic),
-                                ty::mt {ty: unit_ty, mutbl: ast::MutImmutable});
+    let slice_ty = bcx.tcx().mk_imm_ref(bcx.tcx().mk_region(ty::ReStatic),
+                                         bcx.tcx().mk_slice(unit_ty));
     let scratch = rvalue_scratch_datum(bcx, slice_ty, "");
     Store(bcx, slice_begin,
           GEPi(bcx, scratch.val, &[0, abi::FAT_PTR_ADDR]));
@@ -836,7 +841,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     }
 
     let _icx = push_ctxt("compare_values");
-    if ty::type_is_scalar(rhs_t) {
+    if rhs_t.is_scalar() {
         let cmp = compare_scalar_types(cx, lhs, rhs, rhs_t, ast::BiEq, debug_loc);
         return Result::new(cx, cmp);
     }
@@ -849,9 +854,7 @@ fn compare_values<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
                     // NOTE: cast &[u8] and &[u8; N] to &str and abuse the str_eq lang item,
                     // which calls memcmp().
                     let pat_len = val_ty(rhs).element_type().array_length();
-                    let ty_str_slice = ty::mk_str_slice(cx.tcx(),
-                                                        cx.tcx().mk_region(ty::ReStatic),
-                                                        ast::MutImmutable);
+                    let ty_str_slice = cx.tcx().mk_static_str();
 
                     let rhs_str = alloc_ty(cx, ty_str_slice, "rhs_str");
                     Store(cx, GEPi(cx, rhs, &[0, 0]), expr::get_dataptr(cx, rhs_str));
@@ -1058,14 +1061,14 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                          .unwrap_or(DUMMY_NODE_ID);
 
     let left_ty = if pat_id == DUMMY_NODE_ID {
-        ty::mk_nil(tcx)
+        tcx.mk_nil()
     } else {
         node_id_type(bcx, pat_id)
     };
 
     let mcx = check_match::MatchCheckCtxt {
         tcx: bcx.tcx(),
-        param_env: ty::empty_parameter_environment(bcx.tcx()),
+        param_env: bcx.tcx().empty_parameter_environment(),
     };
     let adt_vals = if any_irrefutable_adt_pat(bcx.tcx(), m, col) {
         let repr = adt::represent_type(bcx.ccx(), left_ty);
@@ -1088,9 +1091,9 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                 // The last field is technically unsized but
                 // since we can only ever match that field behind
                 // a reference we construct a fat ptr here.
-                let fields = ty::lookup_struct_fields(bcx.tcx(), def_id);
+                let fields = bcx.tcx().lookup_struct_fields(def_id);
                 let unsized_ty = fields.iter().last().map(|field| {
-                    let fty = ty::lookup_field_type(bcx.tcx(), def_id, field.id, substs);
+                    let fty = bcx.tcx().lookup_field_type(def_id, field.id, substs);
                     monomorphize::normalize_associated_type(bcx.tcx(), &fty)
                 }).unwrap();
                 let llty = type_of::type_of(bcx.ccx(), unsized_ty);
@@ -1140,7 +1143,7 @@ fn compile_submatch_continue<'a, 'p, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
         match opts[0] {
             ConstantValue(..) | ConstantRange(..) => {
                 test_val = load_if_immediate(bcx, val, left_ty);
-                kind = if ty::type_is_integral(left_ty) {
+                kind = if left_ty.is_integral() {
                     Switch
                 } else {
                     Compare
@@ -1407,13 +1410,13 @@ fn create_bindings_map<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, pat: &ast::Pat,
         let variable_ty = node_id_type(bcx, p_id);
         let llvariable_ty = type_of::type_of(ccx, variable_ty);
         let tcx = bcx.tcx();
-        let param_env = ty::empty_parameter_environment(tcx);
+        let param_env = tcx.empty_parameter_environment();
 
         let llmatch;
         let trmode;
         match bm {
             ast::BindByValue(_)
-                if !ty::type_moves_by_default(&param_env, span, variable_ty) || reassigned =>
+                if !param_env.type_moves_by_default(variable_ty, span) || reassigned =>
             {
                 llmatch = alloca_no_lifetime(bcx,
                                  llvariable_ty.ptr_to(),
@@ -1466,7 +1469,7 @@ fn trans_match_inner<'blk, 'tcx>(scope_cx: Block<'blk, 'tcx>,
     }
 
     let t = node_id_type(bcx, discr_expr.id);
-    let chk = if ty::type_is_empty(tcx, t) {
+    let chk = if t.is_empty(tcx) {
         Unreachable
     } else {
         Infallible
@@ -1745,9 +1748,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             match opt_def {
                 Some(def::DefVariant(enum_id, var_id, _)) => {
                     let repr = adt::represent_node(bcx, pat.id);
-                    let vinfo = ty::enum_variant_with_id(ccx.tcx(),
-                                                         enum_id,
-                                                         var_id);
+                    let vinfo = ccx.tcx().enum_variant_with_id(enum_id, var_id);
                     let args = extract_variant_args(bcx,
                                                     &*repr,
                                                     vinfo.disr_val,
@@ -1787,7 +1788,7 @@ fn bind_irrefutable_pat<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let pat_repr = adt::represent_type(bcx.ccx(), pat_ty);
             expr::with_field_tys(tcx, pat_ty, Some(pat.id), |discr, field_tys| {
                 for f in fields {
-                    let ix = ty::field_idx_strict(tcx, f.node.ident.name, field_tys);
+                    let ix = tcx.field_idx_strict(f.node.ident.name, field_tys);
                     let fldptr = adt::trans_field_ptr(bcx, &*pat_repr, val,
                                                       discr, ix);
                     bcx = bind_irrefutable_pat(bcx, &*f.node.pat, fldptr, cleanup_scope);
diff --git a/src/librustc_trans/trans/adt.rs b/src/librustc_trans/trans/adt.rs
index 2a1c2457b9d..3ce76167e85 100644
--- a/src/librustc_trans/trans/adt.rs
+++ b/src/librustc_trans/trans/adt.rs
@@ -209,13 +209,13 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             Univariant(mk_struct(cx, &elems[..], false, t), 0)
         }
         ty::TyStruct(def_id, substs) => {
-            let fields = ty::lookup_struct_fields(cx.tcx(), def_id);
+            let fields = cx.tcx().lookup_struct_fields(def_id);
             let mut ftys = fields.iter().map(|field| {
-                let fty = ty::lookup_field_type(cx.tcx(), def_id, field.id, substs);
+                let fty = cx.tcx().lookup_field_type(def_id, field.id, substs);
                 monomorphize::normalize_associated_type(cx.tcx(), &fty)
             }).collect::<Vec<_>>();
-            let packed = ty::lookup_packed(cx.tcx(), def_id);
-            let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
+            let packed = cx.tcx().lookup_packed(def_id);
+            let dtor = cx.tcx().ty_dtor(def_id).has_drop_flag();
             if dtor {
                 ftys.push(cx.tcx().dtor_type());
             }
@@ -230,10 +230,10 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         }
         ty::TyEnum(def_id, substs) => {
             let cases = get_cases(cx.tcx(), def_id, substs);
-            let hint = *ty::lookup_repr_hints(cx.tcx(), def_id).get(0)
+            let hint = *cx.tcx().lookup_repr_hints(def_id).get(0)
                 .unwrap_or(&attr::ReprAny);
 
-            let dtor = ty::ty_dtor(cx.tcx(), def_id).has_drop_flag();
+            let dtor = cx.tcx().ty_dtor(def_id).has_drop_flag();
 
             if cases.is_empty() {
                 // Uninhabitable; represent as unit
@@ -261,9 +261,8 @@ fn represent_type_uncached<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             // been rejected by a checker before this point.
             if !cases.iter().enumerate().all(|(i,c)| c.discr == (i as Disr)) {
                 cx.sess().bug(&format!("non-C-like enum {} with specified \
-                                      discriminants",
-                                      ty::item_path_str(cx.tcx(),
-                                                        def_id)));
+                                        discriminants",
+                                       cx.tcx().item_path_str(def_id)));
             }
 
             if cases.len() == 1 {
@@ -411,9 +410,9 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
 
         // Is this the NonZero lang item wrapping a pointer or integer type?
         ty::TyStruct(did, substs) if Some(did) == tcx.lang_items.non_zero() => {
-            let nonzero_fields = ty::lookup_struct_fields(tcx, did);
+            let nonzero_fields = tcx.lookup_struct_fields(did);
             assert_eq!(nonzero_fields.len(), 1);
-            let nonzero_field = ty::lookup_field_type(tcx, did, nonzero_fields[0].id, substs);
+            let nonzero_field = tcx.lookup_field_type(did, nonzero_fields[0].id, substs);
             match nonzero_field.sty {
                 ty::TyRawPtr(ty::mt { ty, .. }) if !type_is_sized(tcx, ty) => {
                     path.push_all(&[0, FAT_PTR_ADDR]);
@@ -430,9 +429,9 @@ fn find_discr_field_candidate<'tcx>(tcx: &ty::ctxt<'tcx>,
         // Perhaps one of the fields of this struct is non-zero
         // let's recurse and find out
         ty::TyStruct(def_id, substs) => {
-            let fields = ty::lookup_struct_fields(tcx, def_id);
+            let fields = tcx.lookup_struct_fields(def_id);
             for (j, field) in fields.iter().enumerate() {
-                let field_ty = ty::lookup_field_type(tcx, def_id, field.id, substs);
+                let field_ty = tcx.lookup_field_type(def_id, field.id, substs);
                 if let Some(mut fpath) = find_discr_field_candidate(tcx, field_ty, path.clone()) {
                     fpath.push(j);
                     return Some(fpath);
@@ -504,7 +503,7 @@ fn get_cases<'tcx>(tcx: &ty::ctxt<'tcx>,
                    def_id: ast::DefId,
                    substs: &subst::Substs<'tcx>)
                    -> Vec<Case<'tcx>> {
-    ty::enum_variants(tcx, def_id).iter().map(|vi| {
+    tcx.enum_variants(def_id).iter().map(|vi| {
         let arg_tys = vi.args.iter().map(|&raw_ty| {
             monomorphize::apply_param_substs(tcx, substs, &raw_ty)
         }).collect();
@@ -623,8 +622,8 @@ fn bounds_usable(cx: &CrateContext, ity: IntType, bounds: &IntBounds) -> bool {
 
 pub fn ty_of_inttype<'tcx>(tcx: &ty::ctxt<'tcx>, ity: IntType) -> Ty<'tcx> {
     match ity {
-        attr::SignedInt(t) => ty::mk_mach_int(tcx, t),
-        attr::UnsignedInt(t) => ty::mk_mach_uint(tcx, t)
+        attr::SignedInt(t) => tcx.mk_mach_int(t),
+        attr::UnsignedInt(t) => tcx.mk_mach_uint(t)
     }
 }
 
@@ -1078,7 +1077,7 @@ pub fn trans_drop_flag_ptr<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
                                        -> datum::DatumBlock<'blk, 'tcx, datum::Expr>
 {
     let tcx = bcx.tcx();
-    let ptr_ty = ty::mk_imm_ptr(bcx.tcx(), tcx.dtor_type());
+    let ptr_ty = bcx.tcx().mk_imm_ptr(tcx.dtor_type());
     match *r {
         Univariant(ref st, dtor) if dtor_active(dtor) => {
             let flag_ptr = GEPi(bcx, val, &[0, st.fields.len() - 1]);
diff --git a/src/librustc_trans/trans/attributes.rs b/src/librustc_trans/trans/attributes.rs
index 39e5670c975..b432560bc4b 100644
--- a/src/librustc_trans/trans/attributes.rs
+++ b/src/librustc_trans/trans/attributes.rs
@@ -153,7 +153,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
         _ => ccx.sess().bug("expected closure or function.")
     };
 
-    let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
+    let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
 
     let mut attrs = llvm::AttrBuilder::new();
     let ret_ty = fn_sig.output;
@@ -262,7 +262,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                     attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
                 } else {
                     attrs.arg(idx, llvm::NonNullAttribute);
-                    if ty::type_is_trait(inner) {
+                    if inner.is_trait() {
                         attrs.arg(idx + 1, llvm::NonNullAttribute);
                     }
                 }
@@ -274,7 +274,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                 // `&T` where `T` contains no `UnsafeCell<U>` is immutable, and can be marked as
                 // both `readonly` and `noalias`, as LLVM's definition of `noalias` is based solely
                 // on memory dependencies rather than pointer equality
-                let interior_unsafe = ty::type_contents(ccx.tcx(), mt.ty).interior_unsafe();
+                let interior_unsafe = mt.ty.type_contents(ccx.tcx()).interior_unsafe();
 
                 if mt.mutbl == ast::MutMutable || !interior_unsafe {
                     attrs.arg(idx, llvm::Attribute::NoAlias);
@@ -291,7 +291,7 @@ pub fn from_fn_type<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, fn_type: ty::Ty<'tcx
                     attrs.arg(idx, llvm::DereferenceableAttribute(llsz));
                 } else {
                     attrs.arg(idx, llvm::NonNullAttribute);
-                    if ty::type_is_trait(mt.ty) {
+                    if mt.ty.is_trait() {
                         attrs.arg(idx + 1, llvm::NonNullAttribute);
                     }
                 }
diff --git a/src/librustc_trans/trans/base.rs b/src/librustc_trans/trans/base.rs
index 7a37a3e5ee4..f035b32e359 100644
--- a/src/librustc_trans/trans/base.rs
+++ b/src/librustc_trans/trans/base.rs
@@ -40,7 +40,7 @@ use middle::cfg;
 use middle::lang_items::{LangItem, ExchangeMallocFnLangItem, StartFnLangItem};
 use middle::weak_lang_items;
 use middle::subst::Substs;
-use middle::ty::{self, Ty, ClosureTyper, type_is_simd, simd_size};
+use middle::ty::{self, Ty, ClosureTyper, HasTypeFlags};
 use rustc::ast_map;
 use session::config::{self, NoDebugInfo};
 use session::Session;
@@ -202,10 +202,10 @@ pub fn self_type_for_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let closure_kind = ccx.tcx().closure_kind(closure_id);
     match closure_kind {
         ty::FnClosureKind => {
-            ty::mk_imm_rptr(ccx.tcx(), ccx.tcx().mk_region(ty::ReStatic), fn_ty)
+            ccx.tcx().mk_imm_ref(ccx.tcx().mk_region(ty::ReStatic), fn_ty)
         }
         ty::FnMutClosureKind => {
-            ty::mk_mut_rptr(ccx.tcx(), ccx.tcx().mk_region(ty::ReStatic), fn_ty)
+            ccx.tcx().mk_mut_ref(ccx.tcx().mk_region(ty::ReStatic), fn_ty)
         }
         ty::FnOnceClosureKind => fn_ty
     }
@@ -232,7 +232,7 @@ pub fn get_extern_const<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, did: ast::DefId,
     // don't do this then linker errors can be generated where the linker
     // complains that one object files has a thread local version of the
     // symbol and another one doesn't.
-    for attr in ty::get_attrs(ccx.tcx(), did).iter() {
+    for attr in ccx.tcx().get_attrs(did).iter() {
         if attr.check_name("thread_local") {
             llvm::set_thread_local(c, true);
         }
@@ -443,11 +443,11 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
       }
       ty::TyArray(_, n) => {
         let (base, len) = tvec::get_fixed_base_and_len(cx, data_ptr, n);
-        let unit_ty = ty::sequence_element_type(cx.tcx(), t);
+        let unit_ty = t.sequence_element_type(cx.tcx());
         cx = tvec::iter_vec_raw(cx, base, unit_ty, len, f);
       }
       ty::TySlice(_) | ty::TyStr => {
-        let unit_ty = ty::sequence_element_type(cx.tcx(), t);
+        let unit_ty = t.sequence_element_type(cx.tcx());
         cx = tvec::iter_vec_raw(cx, data_ptr, unit_ty, info.unwrap(), f);
       }
       ty::TyTuple(ref args) => {
@@ -462,7 +462,7 @@ pub fn iter_structural_ty<'blk, 'tcx, F>(cx: Block<'blk, 'tcx>,
           let ccx = fcx.ccx;
 
           let repr = adt::represent_type(ccx, t);
-          let variants = ty::enum_variants(ccx.tcx(), tid);
+          let variants = ccx.tcx().enum_variants(tid);
           let n_variants = (*variants).len();
 
           // NB: we must hit the discriminant first so that structural
@@ -626,9 +626,9 @@ pub fn fail_if_zero_or_overflows<'blk, 'tcx>(
             let zero = C_integral(Type::uint_from_ty(cx.ccx(), t), 0, false);
             (ICmp(cx, llvm::IntEQ, rhs, zero, debug_loc), false)
         }
-        ty::TyStruct(_, _) if type_is_simd(cx.tcx(), rhs_t) => {
+        ty::TyStruct(_, _) if rhs_t.is_simd(cx.tcx()) => {
             let mut res = C_bool(cx.ccx(), false);
-            for i in 0 .. simd_size(cx.tcx(), rhs_t) {
+            for i in 0 .. rhs_t.simd_size(cx.tcx()) {
                 res = Or(cx, res,
                          IsNull(cx,
                                 ExtractElement(cx, rhs, C_int(cx.ccx(), i as i64))), debug_loc);
@@ -805,13 +805,13 @@ pub fn load_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>,
         }
     }
 
-    let val =  if ty::type_is_bool(t) {
+    let val =  if t.is_bool() {
         LoadRangeAssert(cx, ptr, 0, 2, llvm::False)
-    } else if ty::type_is_char(t) {
+    } else if t.is_char() {
         // a char is a Unicode codepoint, and so takes values from 0
         // to 0x10FFFF inclusive only.
         LoadRangeAssert(cx, ptr, 0, 0x10FFFF + 1, llvm::False)
-    } else if (ty::type_is_region_ptr(t) || ty::type_is_unique(t))
+    } else if (t.is_region_ptr() || t.is_unique())
         && !common::type_is_fat_ptr(cx.tcx(), t) {
             LoadNonNull(cx, ptr)
     } else {
@@ -844,7 +844,7 @@ pub fn store_ty<'blk, 'tcx>(cx: Block<'blk, 'tcx>, v: ValueRef, dst: ValueRef, t
 }
 
 pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
-    if ty::type_is_bool(ty) {
+    if ty.is_bool() {
         ZExt(bcx, val, Type::i8(bcx.ccx()))
     } else {
         val
@@ -852,7 +852,7 @@ pub fn from_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
 }
 
 pub fn to_arg_ty(bcx: Block, val: ValueRef, ty: Ty) -> ValueRef {
-    if ty::type_is_bool(ty) {
+    if ty.is_bool() {
         Trunc(bcx, val, Type::i1(bcx.ccx()))
     } else {
         val
@@ -958,7 +958,7 @@ pub fn memcpy_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              t: Ty<'tcx>) {
     let _icx = push_ctxt("memcpy_ty");
     let ccx = bcx.ccx();
-    if ty::type_is_structural(t) {
+    if t.is_structural() {
         let llty = type_of::type_of(ccx, t);
         let llsz = llsize_of(ccx, llty);
         let llalign = type_of::align_of(ccx, t);
@@ -1012,7 +1012,7 @@ pub fn alloc_ty<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, name: &str) ->
     let _icx = push_ctxt("alloc_ty");
     let ccx = bcx.ccx();
     let ty = type_of::type_of(ccx, t);
-    assert!(!ty::type_has_params(t));
+    assert!(!t.has_param_types());
     let val = alloca(bcx, ty, name);
     return val;
 }
@@ -1221,7 +1221,7 @@ pub fn new_fn_ctxt<'a, 'tcx>(ccx: &'a CrateContext<'a, 'tcx>,
           llfn: llfndecl,
           llenv: None,
           llretslotptr: Cell::new(None),
-          param_env: ty::empty_parameter_environment(ccx.tcx()),
+          param_env: ccx.tcx().empty_parameter_environment(),
           alloca_insert_pt: Cell::new(None),
           llreturn: Cell::new(None),
           needs_ret_allocas: nested_returns,
@@ -1584,7 +1584,7 @@ pub fn trans_closure<'a, 'b, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
         // Tuple up closure argument types for the "rust-call" ABI.
         closure::ClosureEnv::Closure(_) => {
-            vec![ty::mk_tup(ccx.tcx(), monomorphized_arg_types)]
+            vec![ccx.tcx().mk_tup(monomorphized_arg_types)]
         }
     };
     for monomorphized_arg_type in &monomorphized_arg_types {
@@ -1673,9 +1673,9 @@ pub fn trans_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let _s = StatRecorder::new(ccx, ccx.tcx().map.path_to_string(id).to_string());
     debug!("trans_fn(param_substs={:?})", param_substs);
     let _icx = push_ctxt("trans_fn");
-    let fn_ty = ty::node_id_to_type(ccx.tcx(), id);
-    let output_type = ty::erase_late_bound_regions(ccx.tcx(), &ty::ty_fn_ret(fn_ty));
-    let abi = ty::ty_fn_abi(fn_ty);
+    let fn_ty = ccx.tcx().node_id_to_type(id);
+    let output_type = ccx.tcx().erase_late_bound_regions(&fn_ty.fn_ret());
+    let abi = fn_ty.fn_abi();
     trans_closure(ccx, decl, body, llfndecl, param_substs, id, attrs, output_type, abi,
                   closure::ClosureEnv::NotClosure);
 }
@@ -1709,7 +1709,7 @@ pub fn trans_named_tuple_constructor<'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
     let result_ty = match ctor_ty.sty {
         ty::TyBareFn(_, ref bft) => {
-            ty::erase_late_bound_regions(bcx.tcx(), &bft.sig.output()).unwrap()
+            bcx.tcx().erase_late_bound_regions(&bft.sig.output()).unwrap()
         }
         _ => ccx.sess().bug(
             &format!("trans_enum_variant_constructor: \
@@ -1782,12 +1782,12 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
                                                      disr: ty::Disr,
                                                      param_substs: &'tcx Substs<'tcx>,
                                                      llfndecl: ValueRef) {
-    let ctor_ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
+    let ctor_ty = ccx.tcx().node_id_to_type(ctor_id);
     let ctor_ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &ctor_ty);
 
     let result_ty = match ctor_ty.sty {
         ty::TyBareFn(_, ref bft) => {
-            ty::erase_late_bound_regions(ccx.tcx(), &bft.sig.output())
+            ccx.tcx().erase_late_bound_regions(&bft.sig.output())
         }
         _ => ccx.sess().bug(
             &format!("trans_enum_variant_or_tuple_like_struct: \
@@ -1803,9 +1803,7 @@ fn trans_enum_variant_or_tuple_like_struct<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx
 
     assert!(!fcx.needs_ret_allocas);
 
-    let arg_tys =
-        ty::erase_late_bound_regions(
-            ccx.tcx(), &ty::ty_fn_args(ctor_ty));
+    let arg_tys = ccx.tcx().erase_late_bound_regions(&ctor_ty.fn_args());
 
     let arg_datums = create_datums_for_fn_args(bcx, &arg_tys[..]);
 
@@ -1841,7 +1839,7 @@ fn enum_variant_size_lint(ccx: &CrateContext, enum_def: &ast::EnumDef, sp: Span,
         return
     }
 
-    let ty = ty::node_id_to_type(ccx.tcx(), id);
+    let ty = ccx.tcx().node_id_to_type(id);
     let avar = adt::represent_type(ccx, ty);
     match *avar {
         adt::General(_, ref variants, _) => {
@@ -2040,7 +2038,7 @@ pub fn trans_item(ccx: &CrateContext, item: &ast::Item) {
                     // error in trans. This is used to write compile-fail tests
                     // that actually test that compilation succeeds without
                     // reporting an error.
-                    if ty::has_attr(ccx.tcx(), local_def(item.id), "rustc_error") {
+                    if ccx.tcx().has_attr(local_def(item.id), "rustc_error") {
                         ccx.tcx().sess.span_fatal(item.span, "compilation successful");
                     }
                 }
@@ -2120,7 +2118,7 @@ pub fn register_fn_llvmty(ccx: &CrateContext,
     debug!("register_fn_llvmty id={} sym={}", node_id, sym);
 
     let llfn = declare::define_fn(ccx, &sym[..], cc, llfty,
-                                   ty::FnConverging(ty::mk_nil(ccx.tcx()))).unwrap_or_else(||{
+                                   ty::FnConverging(ccx.tcx().mk_nil())).unwrap_or_else(||{
         ccx.sess().span_fatal(sp, &format!("symbol `{}` is already defined", sym));
     });
     finish_register_fn(ccx, sym, node_id, llfn);
@@ -2202,7 +2200,7 @@ pub fn create_entry_wrapper(ccx: &CrateContext,
                                &ccx.int_type());
 
         let llfn = declare::define_cfn(ccx, "main", llfty,
-                                       ty::mk_nil(ccx.tcx())).unwrap_or_else(||{
+                                       ccx.tcx().mk_nil()).unwrap_or_else(||{
             ccx.sess().span_err(sp, "entry symbol `main` defined multiple times");
             // FIXME: We should be smart and show a better diagnostic here.
             ccx.sess().help("did you use #[no_mangle] on `fn main`? Use #[start] instead");
@@ -2319,7 +2317,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
     debug!("get_item_val: id={} item={:?}", id, item);
     let val = match item {
         ast_map::NodeItem(i) => {
-            let ty = ty::node_id_to_type(ccx.tcx(), i.id);
+            let ty = ccx.tcx().node_id_to_type(i.id);
             let sym = || exported_name(ccx, id, ty, &i.attrs);
 
             let v = match i.node {
@@ -2339,7 +2337,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                     unsafe {
                         // boolean SSA values are i1, but they have to be stored in i8 slots,
                         // otherwise some LLVM optimization passes don't work as expected
-                        let llty = if ty::type_is_bool(ty) {
+                        let llty = if ty.is_bool() {
                             llvm::LLVMInt8TypeInContext(ccx.llcx())
                         } else {
                             llvm::LLVMTypeOf(v)
@@ -2426,7 +2424,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             match ni.node {
                 ast::ForeignItemFn(..) => {
                     let abi = ccx.tcx().map.get_foreign_abi(id);
-                    let ty = ty::node_id_to_type(ccx.tcx(), ni.id);
+                    let ty = ccx.tcx().node_id_to_type(ni.id);
                     let name = foreign::link_name(&*ni);
                     let llfn = foreign::register_foreign_item_fn(ccx, abi, ty, &name);
                     attributes::from_fn_attrs(ccx, &ni.attrs, llfn);
@@ -2447,7 +2445,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
                 }
             };
             assert!(!args.is_empty());
-            let ty = ty::node_id_to_type(ccx.tcx(), id);
+            let ty = ccx.tcx().node_id_to_type(id);
             let parent = ccx.tcx().map.get_parent(id);
             let enm = ccx.tcx().map.expect_item(parent);
             let sym = exported_name(ccx,
@@ -2476,7 +2474,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
             };
             let parent = ccx.tcx().map.get_parent(id);
             let struct_item = ccx.tcx().map.expect_item(parent);
-            let ty = ty::node_id_to_type(ccx.tcx(), ctor_id);
+            let ty = ccx.tcx().node_id_to_type(ctor_id);
             let sym = exported_name(ccx,
                                     id,
                                     ty,
@@ -2508,7 +2506,7 @@ pub fn get_item_val(ccx: &CrateContext, id: ast::NodeId) -> ValueRef {
 
 fn register_method(ccx: &CrateContext, id: ast::NodeId,
                    attrs: &[ast::Attribute], span: Span) -> ValueRef {
-    let mty = ty::node_id_to_type(ccx.tcx(), id);
+    let mty = ccx.tcx().node_id_to_type(id);
 
     let sym = exported_name(ccx, id, mty, &attrs);
 
diff --git a/src/librustc_trans/trans/callee.rs b/src/librustc_trans/trans/callee.rs
index 093b824701f..24abe0ed3fd 100644
--- a/src/librustc_trans/trans/callee.rs
+++ b/src/librustc_trans/trans/callee.rs
@@ -49,7 +49,7 @@ use trans::meth;
 use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags, RegionEscape};
 use middle::ty::MethodCall;
 use rustc::ast_map;
 
@@ -173,7 +173,7 @@ fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, expr: &ast::Expr)
                                                                 bcx.fcx.param_substs).val)
             }
             def::DefVariant(tid, vid, _) => {
-                let vinfo = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
+                let vinfo = bcx.tcx().enum_variant_with_id(tid, vid);
                 let substs = common::node_id_substs(bcx.ccx(),
                                                     ExprId(ref_expr.id),
                                                     bcx.fcx.param_substs);
@@ -277,7 +277,7 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
         ty::FnOnceClosureKind => false,
     };
     let bare_fn_ty_maybe_ref = if is_by_ref {
-        ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), bare_fn_ty)
+        tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), bare_fn_ty)
     } else {
         bare_fn_ty
     };
@@ -307,19 +307,18 @@ pub fn trans_fn_pointer_shim<'a, 'tcx>(
                                       bare_fn_ty));
             }
         };
-    let sig = ty::erase_late_bound_regions(tcx, sig);
-    let tuple_input_ty = ty::mk_tup(tcx, sig.inputs.to_vec());
-    let tuple_fn_ty = ty::mk_bare_fn(tcx,
-                                     opt_def_id,
-                                     tcx.mk_bare_fn(ty::BareFnTy {
-                                         unsafety: ast::Unsafety::Normal,
-                                         abi: synabi::RustCall,
-                                         sig: ty::Binder(ty::FnSig {
-                                             inputs: vec![bare_fn_ty_maybe_ref,
-                                                          tuple_input_ty],
-                                             output: sig.output,
-                                             variadic: false
-                                         })}));
+    let sig = tcx.erase_late_bound_regions(sig);
+    let tuple_input_ty = tcx.mk_tup(sig.inputs.to_vec());
+    let tuple_fn_ty = tcx.mk_fn(opt_def_id,
+        tcx.mk_bare_fn(ty::BareFnTy {
+            unsafety: ast::Unsafety::Normal,
+            abi: synabi::RustCall,
+            sig: ty::Binder(ty::FnSig {
+                inputs: vec![bare_fn_ty_maybe_ref,
+                             tuple_input_ty],
+                output: sig.output,
+                variadic: false
+            })}));
     debug!("tuple_fn_ty: {:?}", tuple_fn_ty);
 
     //
@@ -402,22 +401,22 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
            param_substs,
            substs);
 
-    assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
-    assert!(substs.types.all(|t| !ty::type_has_escaping_regions(*t)));
+    assert!(!substs.types.needs_infer());
+    assert!(!substs.types.has_escaping_regions());
     let substs = substs.erase_regions();
 
     // Load the info for the appropriate trait if necessary.
-    match ty::trait_of_item(tcx, def_id) {
+    match tcx.trait_of_item(def_id) {
         None => {}
         Some(trait_id) => {
-            ty::populate_implementations_for_trait_if_necessary(tcx, trait_id)
+            tcx.populate_implementations_for_trait_if_necessary(trait_id)
         }
     }
 
     // We need to do a bunch of special handling for default methods.
     // We need to modify the def_id and our substs in order to monomorphize
     // the function.
-    let (is_default, def_id, substs) = match ty::provided_source(tcx, def_id) {
+    let (is_default, def_id, substs) = match tcx.provided_source(def_id) {
         None => {
             (false, def_id, tcx.mk_substs(substs))
         }
@@ -435,16 +434,16 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
             // So, what we need to do is find this substitution and
             // compose it with the one we already have.
 
-            let impl_id = ty::impl_or_trait_item(tcx, def_id).container()
+            let impl_id = tcx.impl_or_trait_item(def_id).container()
                                                              .id();
-            let impl_or_trait_item = ty::impl_or_trait_item(tcx, source_id);
+            let impl_or_trait_item = tcx.impl_or_trait_item(source_id);
             match impl_or_trait_item {
                 ty::MethodTraitItem(method) => {
-                    let trait_ref = ty::impl_trait_ref(tcx, impl_id).unwrap();
+                    let trait_ref = tcx.impl_trait_ref(impl_id).unwrap();
 
                     // Compute the first substitution
                     let first_subst =
-                        ty::make_substs_for_receiver_types(tcx, &trait_ref, &*method)
+                        tcx.make_substs_for_receiver_types(&trait_ref, &*method)
                         .erase_regions();
 
                     // And compose them
@@ -517,7 +516,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
             // Monotype of the REFERENCE to the function (type params
             // are subst'd)
             let ref_ty = match node {
-                ExprId(id) => ty::node_id_to_type(tcx, id),
+                ExprId(id) => tcx.node_id_to_type(id),
                 MethodCallKey(method_call) => {
                     tcx.method_map.borrow().get(&method_call).unwrap().ty
                 }
@@ -535,7 +534,7 @@ pub fn trans_fn_ref_with_substs<'a, 'tcx>(
     }
 
     // Type scheme of the function item (may have type params)
-    let fn_type_scheme = ty::lookup_item_type(tcx, def_id);
+    let fn_type_scheme = tcx.lookup_item_type(def_id);
     let fn_type = monomorphize::normalize_associated_type(tcx, &fn_type_scheme.ty);
 
     // Find the actual function pointer.
@@ -615,7 +614,7 @@ pub fn trans_method_call<'a, 'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         Some(method) => match method.origin {
             ty::MethodTraitObject(_) => match method.ty.sty {
                 ty::TyBareFn(_, ref fty) => {
-                    ty::mk_bare_fn(bcx.tcx(), None, meth::opaque_method_ty(bcx.tcx(), fty))
+                    bcx.tcx().mk_fn(None, meth::opaque_method_ty(bcx.tcx(), fty))
                 }
                 _ => method.ty
             },
@@ -641,7 +640,7 @@ pub fn trans_lang_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                    debug_loc: DebugLoc)
                                    -> Result<'blk, 'tcx> {
     let fty = if did.krate == ast::LOCAL_CRATE {
-        ty::node_id_to_type(bcx.tcx(), did.node)
+        bcx.tcx().node_id_to_type(did.node)
     } else {
         csearch::get_type(bcx.tcx(), did).ty
     };
@@ -693,7 +692,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
 
     let (abi, ret_ty) = match callee_ty.sty {
         ty::TyBareFn(_, ref f) => {
-            let output = ty::erase_late_bound_regions(bcx.tcx(), &f.sig.output());
+            let output = bcx.tcx().erase_late_bound_regions(&f.sig.output());
             (f.abi, output)
         }
         _ => panic!("expected bare rust fn or closure in trans_call_inner")
@@ -749,7 +748,7 @@ pub fn trans_call_inner<'a, 'blk, 'tcx, F>(bcx: Block<'blk, 'tcx>,
         expr::Ignore => {
             let ret_ty = match ret_ty {
                 ty::FnConverging(ret_ty) => ret_ty,
-                ty::FnDiverging => ty::mk_nil(ccx.tcx())
+                ty::FnDiverging => ccx.tcx().mk_nil()
             };
             if !is_rust_fn ||
               type_of::return_uses_outptr(ccx, ret_ty) ||
@@ -915,9 +914,7 @@ fn trans_args_under_call_abi<'blk, 'tcx>(
                              ignore_self: bool)
                              -> Block<'blk, 'tcx>
 {
-    let args =
-        ty::erase_late_bound_regions(
-            bcx.tcx(), &ty::ty_fn_args(fn_ty));
+    let args = bcx.tcx().erase_late_bound_regions(&fn_ty.fn_args());
 
     // Translate the `self` argument first.
     if !ignore_self {
@@ -978,7 +975,7 @@ fn trans_overloaded_call_args<'blk, 'tcx>(
                               ignore_self: bool)
                               -> Block<'blk, 'tcx> {
     // Translate the `self` argument first.
-    let arg_tys = ty::erase_late_bound_regions(bcx.tcx(),  &ty::ty_fn_args(fn_ty));
+    let arg_tys = bcx.tcx().erase_late_bound_regions( &fn_ty.fn_args());
     if !ignore_self {
         let arg_datum = unpack_datum!(bcx, expr::trans(bcx, arg_exprs[0]));
         bcx = trans_arg_datum(bcx,
@@ -1024,8 +1021,8 @@ pub fn trans_args<'a, 'blk, 'tcx>(cx: Block<'blk, 'tcx>,
     debug!("trans_args(abi={})", abi);
 
     let _icx = push_ctxt("trans_args");
-    let arg_tys = ty::erase_late_bound_regions(cx.tcx(), &ty::ty_fn_args(fn_ty));
-    let variadic = ty::fn_is_variadic(fn_ty);
+    let arg_tys = cx.tcx().erase_late_bound_regions(&fn_ty.fn_args());
+    let variadic = fn_ty.fn_sig().0.variadic;
 
     let mut bcx = cx;
 
diff --git a/src/librustc_trans/trans/closure.rs b/src/librustc_trans/trans/closure.rs
index 61351847a83..cb30bcdbf53 100644
--- a/src/librustc_trans/trans/closure.rs
+++ b/src/librustc_trans/trans/closure.rs
@@ -135,7 +135,7 @@ pub fn get_or_create_declaration_if_closure<'a, 'tcx>(ccx: &CrateContext<'a, 'tc
         return None
     }
 
-    let function_type = ty::node_id_to_type(ccx.tcx(), closure_id.node);
+    let function_type = ccx.tcx().node_id_to_type(closure_id.node);
     let function_type = monomorphize::apply_param_substs(ccx.tcx(), substs, &function_type);
 
     // Normalize type so differences in regions and typedefs don't cause
@@ -218,9 +218,9 @@ pub fn trans_closure_expr<'a, 'tcx>(dest: Dest<'a, 'tcx>,
     let function_type = typer.closure_type(closure_id, param_substs);
 
     let freevars: Vec<ty::Freevar> =
-        ty::with_freevars(tcx, id, |fv| fv.iter().cloned().collect());
+        tcx.with_freevars(id, |fv| fv.iter().cloned().collect());
 
-    let sig = ty::erase_late_bound_regions(tcx, &function_type.sig);
+    let sig = tcx.erase_late_bound_regions(&function_type.sig);
 
     trans_closure(ccx,
                   decl,
@@ -363,8 +363,8 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     // Find a version of the closure type. Substitute static for the
     // region since it doesn't really matter.
     let substs = tcx.mk_substs(substs);
-    let closure_ty = ty::mk_closure(tcx, closure_def_id, substs);
-    let ref_closure_ty = ty::mk_imm_rptr(tcx, tcx.mk_region(ty::ReStatic), closure_ty);
+    let closure_ty = tcx.mk_closure(closure_def_id, substs);
+    let ref_closure_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic), closure_ty);
 
     // Make a version with the type of by-ref closure.
     let ty::ClosureTy { unsafety, abi, mut sig } = typer.closure_type(closure_def_id, substs);
@@ -372,7 +372,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     let llref_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
                                                                abi: abi,
                                                                sig: sig.clone() });
-    let llref_fn_ty = ty::mk_bare_fn(tcx, None, llref_bare_fn_ty);
+    let llref_fn_ty = tcx.mk_fn(None, llref_bare_fn_ty);
     debug!("trans_fn_once_adapter_shim: llref_fn_ty={:?}",
            llref_fn_ty);
 
@@ -383,7 +383,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
     let llonce_bare_fn_ty = tcx.mk_bare_fn(ty::BareFnTy { unsafety: unsafety,
                                                                 abi: abi,
                                                                 sig: sig });
-    let llonce_fn_ty = ty::mk_bare_fn(tcx, None, llonce_bare_fn_ty);
+    let llonce_fn_ty = tcx.mk_fn(None, llonce_bare_fn_ty);
 
     // Create the by-value helper.
     let function_name = link::mangle_internal_name_by_type_and_seq(ccx, llonce_fn_ty, "once_shim");
@@ -392,7 +392,7 @@ fn trans_fn_once_adapter_shim<'a, 'tcx>(
             ccx.sess().bug(&format!("symbol `{}` already defined", function_name));
         });
 
-    let sig = ty::erase_late_bound_regions(tcx, &llonce_bare_fn_ty.sig);
+    let sig = tcx.erase_late_bound_regions(&llonce_bare_fn_ty.sig);
     let (block_arena, fcx): (TypedArena<_>, FunctionContext);
     block_arena = TypedArena::new();
     fcx = new_fn_ctxt(ccx,
diff --git a/src/librustc_trans/trans/common.rs b/src/librustc_trans/trans/common.rs
index 403755c536d..777b61f25f0 100644
--- a/src/librustc_trans/trans/common.rs
+++ b/src/librustc_trans/trans/common.rs
@@ -23,6 +23,7 @@ use middle::def;
 use middle::infer;
 use middle::lang_items::LangItem;
 use middle::mem_categorization as mc;
+use middle::mem_categorization::Typer;
 use middle::region;
 use middle::subst::{self, Subst, Substs};
 use trans::base;
@@ -37,7 +38,7 @@ use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of;
 use middle::traits;
-use middle::ty::{self, HasProjectionTypes, Ty};
+use middle::ty::{self, HasTypeFlags, Ty};
 use middle::ty_fold;
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use rustc::ast_map::{PathElem, PathName};
@@ -89,7 +90,7 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
         fn fold_binder<T>(&mut self, t: &ty::Binder<T>) -> ty::Binder<T>
             where T : TypeFoldable<'tcx>
         {
-            let u = ty::anonymize_late_bound_regions(self.tcx(), t);
+            let u = self.tcx().anonymize_late_bound_regions(t);
             ty_fold::super_fold_binder(self, &u)
         }
 
@@ -119,7 +120,7 @@ pub fn erase_regions<'tcx,T>(cx: &ty::ctxt<'tcx>, value: &T) -> T
 
 /// Is the type's representation size known at compile time?
 pub fn type_is_sized<'tcx>(tcx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    ty::type_is_sized(None, tcx, DUMMY_SP, ty)
+    ty.is_sized(&tcx.empty_parameter_environment(), DUMMY_SP)
 }
 
 pub fn type_is_fat_ptr<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
@@ -155,13 +156,13 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<
         }
 
         let mut needs_unwind_cleanup = false;
-        ty::maybe_walk_ty(ty, |ty| {
+        ty.maybe_walk(|ty| {
             needs_unwind_cleanup |= match ty.sty {
                 ty::TyBool | ty::TyInt(_) | ty::TyUint(_) |
                 ty::TyFloat(_) | ty::TyTuple(_) | ty::TyRawPtr(_) => false,
 
                 ty::TyEnum(did, substs) =>
-                    ty::enum_variants(tcx, did).iter().any(|v|
+                    tcx.enum_variants(did).iter().any(|v|
                         v.args.iter().any(|&aty| {
                             let t = aty.subst(tcx, substs);
                             type_needs_unwind_cleanup_(tcx, t, tycache)
@@ -183,7 +184,7 @@ pub fn type_needs_unwind_cleanup<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<
 /// (Note that this implies that if `ty` has a destructor attached,
 /// then `type_needs_drop` will definitely return `true` for `ty`.)
 pub fn type_needs_drop<'tcx>(cx: &ty::ctxt<'tcx>, ty: Ty<'tcx>) -> bool {
-    type_needs_drop_given_env(cx, ty, &ty::empty_parameter_environment(cx))
+    type_needs_drop_given_env(cx, ty, &cx.empty_parameter_environment())
 }
 
 /// Core implementation of type_needs_drop, potentially making use of
@@ -195,7 +196,7 @@ fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
     // normalized version of the type, and therefore will definitely
     // know whether the type implements Copy (and thus needs no
     // cleanup/drop/zeroing) ...
-    let implements_copy = !ty::type_moves_by_default(&param_env, DUMMY_SP, ty);
+    let implements_copy = !param_env.type_moves_by_default(ty, DUMMY_SP);
 
     if implements_copy { return false; }
 
@@ -210,7 +211,7 @@ fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
     // bound attached (see above), it is sound to treat it as having a
     // destructor (e.g. zero its memory on move).
 
-    let contents = ty::type_contents(cx, ty);
+    let contents = ty.type_contents(cx);
     debug!("type_needs_drop ty={:?} contents={:?}", ty, contents);
     contents.needs_drop(cx)
 }
@@ -218,9 +219,9 @@ fn type_needs_drop_given_env<'a,'tcx>(cx: &ty::ctxt<'tcx>,
 fn type_is_newtype_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> bool {
     match ty.sty {
         ty::TyStruct(def_id, substs) => {
-            let fields = ty::lookup_struct_fields(ccx.tcx(), def_id);
+            let fields = ccx.tcx().lookup_struct_fields(def_id);
             fields.len() == 1 && {
-                let ty = ty::lookup_field_type(ccx.tcx(), def_id, fields[0].id, substs);
+                let ty = ccx.tcx().lookup_field_type(def_id, fields[0].id, substs);
                 let ty = monomorphize::normalize_associated_type(ccx.tcx(), &ty);
                 type_is_immediate(ccx, ty)
             }
@@ -234,10 +235,10 @@ pub fn type_is_immediate<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
     use trans::type_of::sizing_type_of;
 
     let tcx = ccx.tcx();
-    let simple = ty::type_is_scalar(ty) ||
-        ty::type_is_unique(ty) || ty::type_is_region_ptr(ty) ||
+    let simple = ty.is_scalar() ||
+        ty.is_unique() || ty.is_region_ptr() ||
         type_is_newtype_immediate(ccx, ty) ||
-        ty::type_is_simd(tcx, ty);
+        ty.is_simd(tcx);
     if simple && !type_is_fat_ptr(tcx, ty) {
         return true;
     }
@@ -267,7 +268,7 @@ pub fn type_is_zero_size<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -
 /// zero-size, but not all zero-size types use a `void` return type (in order to aid with C ABI
 /// compatibility).
 pub fn return_type_is_void(ccx: &CrateContext, ty: Ty) -> bool {
-    ty::type_is_nil(ty) || ty::type_is_empty(ccx.tcx(), ty)
+    ty.is_nil() || ty.is_empty(ccx.tcx())
 }
 
 /// Generates a unique symbol based off the name given. This is used to create
@@ -336,7 +337,7 @@ pub fn BuilderRef_res(b: BuilderRef) -> BuilderRef_res {
 pub type ExternMap = FnvHashMap<String, ValueRef>;
 
 pub fn validate_substs(substs: &Substs) {
-    assert!(substs.types.all(|t| !ty::type_needs_infer(*t)));
+    assert!(!substs.types.needs_infer());
 }
 
 // work around bizarre resolve errors
@@ -512,7 +513,7 @@ impl<'a, 'tcx> FunctionContext<'a, 'tcx> {
     }
 
     pub fn monomorphize<T>(&self, value: &T) -> T
-        where T : TypeFoldable<'tcx> + HasProjectionTypes
+        where T : TypeFoldable<'tcx> + HasTypeFlags
     {
         monomorphize::apply_param_substs(self.ccx.tcx(),
                                          self.param_substs,
@@ -610,7 +611,7 @@ impl<'blk, 'tcx> BlockS<'blk, 'tcx> {
     }
 
     pub fn monomorphize<T>(&self, value: &T) -> T
-        where T : TypeFoldable<'tcx> + HasProjectionTypes
+        where T : TypeFoldable<'tcx> + HasTypeFlags
     {
         monomorphize::apply_param_substs(self.tcx(),
                                          self.fcx.param_substs,
@@ -661,8 +662,8 @@ impl<'blk, 'tcx> mc::Typer<'tcx> for BlockS<'blk, 'tcx> {
         Some(self.tcx().upvar_capture_map.borrow().get(&upvar_id).unwrap().clone())
     }
 
-    fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
-        self.fcx.param_env.type_moves_by_default(span, ty)
+    fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
+        self.fcx.param_env.type_moves_by_default(ty, span)
     }
 }
 
@@ -952,7 +953,7 @@ pub fn monomorphize_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, t: Ty<'tcx>) -> T
 
 pub fn node_id_type<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, id: ast::NodeId) -> Ty<'tcx> {
     let tcx = bcx.tcx();
-    let t = ty::node_id_to_type(tcx, id);
+    let t = tcx.node_id_to_type(id);
     monomorphize_type(bcx, t)
 }
 
@@ -961,7 +962,7 @@ pub fn expr_ty<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx>
 }
 
 pub fn expr_ty_adjusted<'blk, 'tcx>(bcx: &BlockS<'blk, 'tcx>, ex: &ast::Expr) -> Ty<'tcx> {
-    monomorphize_type(bcx, ty::expr_ty_adjusted(bcx.tcx(), ex))
+    monomorphize_type(bcx, bcx.tcx().expr_ty_adjusted(ex))
 }
 
 /// Attempts to resolve an obligation. The result is a shallow vtable resolution -- meaning that we
@@ -989,7 +990,7 @@ pub fn fulfill_obligation<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     debug!("trans fulfill_obligation: trait_ref={:?} def_id={:?}",
            trait_ref, trait_ref.def_id());
 
-    ty::populate_implementations_for_trait_if_necessary(tcx, trait_ref.def_id());
+    tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id());
     let infcx = infer::new_infer_ctxt(tcx);
 
     // Do the initial selection for the obligation. This yields the
@@ -1077,7 +1078,7 @@ impl<'a,'tcx> NormalizingClosureTyper<'a,'tcx> {
     pub fn new(tcx: &'a ty::ctxt<'tcx>) -> NormalizingClosureTyper<'a,'tcx> {
         // Parameter environment is used to give details about type parameters,
         // but since we are in trans, everything is fully monomorphized.
-        NormalizingClosureTyper { param_env: ty::empty_parameter_environment(tcx) }
+        NormalizingClosureTyper { param_env: tcx.empty_parameter_environment() }
     }
 }
 
@@ -1111,7 +1112,7 @@ impl<'a,'tcx> ty::ClosureTyper<'tcx> for NormalizingClosureTyper<'a,'tcx> {
     {
         // the substitutions in `substs` are already monomorphized,
         // but we still must normalize associated types
-        let result = ty::closure_upvars(&self.param_env, def_id, substs);
+        let result = self.param_env.closure_upvars(def_id, substs);
         monomorphize::normalize_associated_type(self.param_env.tcx, &result)
     }
 }
@@ -1187,14 +1188,14 @@ pub fn node_id_substs<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let substs = match node {
         ExprId(id) => {
-            ty::node_id_item_substs(tcx, id).substs
+            tcx.node_id_item_substs(id).substs
         }
         MethodCallKey(method_call) => {
             tcx.method_map.borrow().get(&method_call).unwrap().substs.clone()
         }
     };
 
-    if substs.types.any(|t| ty::type_needs_infer(*t)) {
+    if substs.types.needs_infer() {
             tcx.sess.bug(&format!("type parameters for node {:?} include inference types: {:?}",
                                  node, substs));
         }
diff --git a/src/librustc_trans/trans/consts.rs b/src/librustc_trans/trans/consts.rs
index 7fbc86d7a8a..8ec60000ee8 100644
--- a/src/librustc_trans/trans/consts.rs
+++ b/src/librustc_trans/trans/consts.rs
@@ -57,7 +57,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
             C_integral(Type::uint_from_ty(cx, t), u, false)
         }
         ast::LitInt(i, ast::UnsuffixedIntLit(_)) => {
-            let lit_int_ty = ty::node_id_to_type(cx.tcx(), e.id);
+            let lit_int_ty = cx.tcx().node_id_to_type(e.id);
             match lit_int_ty.sty {
                 ty::TyInt(t) => {
                     C_integral(Type::int_from_ty(cx, t), i as u64, true)
@@ -75,7 +75,7 @@ pub fn const_lit(cx: &CrateContext, e: &ast::Expr, lit: &ast::Lit)
             C_floating(&fs, Type::float_from_ty(cx, t))
         }
         ast::LitFloatUnsuffixed(ref fs) => {
-            let lit_float_ty = ty::node_id_to_type(cx.tcx(), e.id);
+            let lit_float_ty = cx.tcx().node_id_to_type(e.id);
             match lit_float_ty.sty {
                 ty::TyFloat(t) => {
                     C_floating(&fs, Type::float_from_ty(cx, t))
@@ -149,7 +149,7 @@ fn const_deref<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                          v: ValueRef,
                          ty: Ty<'tcx>)
                          -> (ValueRef, Ty<'tcx>) {
-    match ty::deref(ty, true) {
+    match ty.builtin_deref(true) {
         Some(mt) => {
             if type_is_sized(cx.tcx(), mt.ty) {
                 (const_deref_ptr(cx, v), mt.ty)
@@ -249,7 +249,7 @@ pub fn get_const_expr_as_global<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         // Avoid autorefs as they would create global instead of stack
         // references, even when only the latter are correct.
         let ty = monomorphize::apply_param_substs(ccx.tcx(), param_substs,
-                                                  &ty::expr_ty(ccx.tcx(), expr));
+                                                  &ccx.tcx().expr_ty(expr));
         const_expr_unadjusted(ccx, expr, ty, param_substs, None)
     } else {
         const_expr(ccx, expr, param_substs, None).0
@@ -276,11 +276,11 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                             fn_args: FnArgMap)
                             -> (ValueRef, Ty<'tcx>) {
     let ety = monomorphize::apply_param_substs(cx.tcx(), param_substs,
-                                               &ty::expr_ty(cx.tcx(), e));
+                                               &cx.tcx().expr_ty(e));
     let llconst = const_expr_unadjusted(cx, e, ety, param_substs, fn_args);
     let mut llconst = llconst;
     let mut ety_adjusted = monomorphize::apply_param_substs(cx.tcx(), param_substs,
-                                                            &ty::expr_ty_adjusted(cx.tcx(), e));
+                                                            &cx.tcx().expr_ty_adjusted(e));
     let opt_adj = cx.tcx().adjustments.borrow().get(&e.id).cloned();
     match opt_adj {
         Some(ty::AdjustReifyFnPointer) => {
@@ -306,7 +306,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     // Don't copy data to do a deref+ref
                     // (i.e., skip the last auto-deref).
                     llconst = addr_of(cx, llconst, "autoref");
-                    ty = ty::mk_imm_rptr(cx.tcx(), cx.tcx().mk_region(ty::ReStatic), ty);
+                    ty = cx.tcx().mk_imm_ref(cx.tcx().mk_region(ty::ReStatic), ty);
                 }
             } else {
                 let (dv, dt) = const_deref(cx, llconst, ty);
@@ -323,7 +323,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                                               param_substs,
                                                               &target);
 
-                let pointee_ty = ty::deref(ty, true)
+                let pointee_ty = ty.builtin_deref(true)
                     .expect("consts: unsizing got non-pointer type").ty;
                 let (base, old_info) = if !type_is_sized(cx.tcx(), pointee_ty) {
                     // Normally, the source is a thin pointer and we are
@@ -338,7 +338,7 @@ pub fn const_expr<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     (llconst, None)
                 };
 
-                let unsized_ty = ty::deref(target, true)
+                let unsized_ty = target.builtin_deref(true)
                     .expect("consts: unsizing got non-pointer target type").ty;
                 let ptr_ty = type_of::in_memory_type_of(cx, unsized_ty).ptr_to();
                 let base = ptrcast(base, ptr_ty);
@@ -499,14 +499,14 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             debug!("const_expr_unadjusted: te1={}, ty={:?}",
                    cx.tn().val_to_string(te1),
                    ty);
-            let is_simd = ty::type_is_simd(cx.tcx(), ty);
+            let is_simd = ty.is_simd(cx.tcx());
             let intype = if is_simd {
-                ty::simd_type(cx.tcx(), ty)
+                ty.simd_type(cx.tcx())
             } else {
                 ty
             };
-            let is_float = ty::type_is_fp(intype);
-            let signed = ty::type_is_signed(intype);
+            let is_float = intype.is_fp();
+            let signed = intype.is_signed();
 
             let (te2, _) = const_expr(cx, &**e2, param_substs, fn_args);
 
@@ -572,7 +572,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             check_unary_expr_validity(cx, e, ty, te);
 
-            let is_float = ty::type_is_fp(ty);
+            let is_float = ty.is_fp();
             match u {
               ast::UnUniq | ast::UnDeref => {
                 const_deref(cx, te, ty).0
@@ -588,7 +588,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               let (bv, bt) = const_expr(cx, &**base, param_substs, fn_args);
               let brepr = adt::represent_type(cx, bt);
               expr::with_field_tys(cx.tcx(), bt, None, |discr, field_tys| {
-                  let ix = ty::field_idx_strict(cx.tcx(), field.node.name, field_tys);
+                  let ix = cx.tcx().field_idx_strict(field.node.name, field_tys);
                   adt::const_get_field(cx, &*brepr, bv, discr, ix)
               })
           }
@@ -660,7 +660,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
             if type_is_fat_ptr(cx.tcx(), t_expr) {
                 // Fat pointer casts.
-                let t_cast_inner = ty::deref(t_cast, true).expect("cast to non-pointer").ty;
+                let t_cast_inner = t_cast.builtin_deref(true).expect("cast to non-pointer").ty;
                 let ptr_ty = type_of::in_memory_type_of(cx, t_cast_inner).ptr_to();
                 let addr = ptrcast(const_get_elt(cx, v, &[abi::FAT_PTR_ADDR as u32]),
                                    ptr_ty);
@@ -681,11 +681,11 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                 llvm::LLVMConstIntCast(iv, llty.to_ref(), s)
               }
               (CastTy::Int(_), CastTy::Int(_)) => {
-                let s = ty::type_is_signed(t_expr) as Bool;
+                let s = t_expr.is_signed() as Bool;
                 llvm::LLVMConstIntCast(v, llty.to_ref(), s)
               }
               (CastTy::Int(_), CastTy::Float) => {
-                if ty::type_is_signed(t_expr) {
+                if t_expr.is_signed() {
                     llvm::LLVMConstSIToFP(v, llty.to_ref())
                 } else {
                     llvm::LLVMConstUIToFP(v, llty.to_ref())
@@ -781,7 +781,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                           }
                       }
                   }).collect::<Vec<_>>();
-                  if ty::type_is_simd(cx.tcx(), ety) {
+                  if ety.is_simd(cx.tcx()) {
                       C_vector(&cs[..])
                   } else {
                       adt::trans_const(cx, &*repr, discr, &cs[..])
@@ -789,7 +789,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
               })
           }
           ast::ExprVec(ref es) => {
-            let unit_ty = ty::sequence_element_type(cx.tcx(), ety);
+            let unit_ty = ety.sequence_element_type(cx.tcx());
             let llunitty = type_of::type_of(cx, unit_ty);
             let vs = es.iter().map(|e| const_expr(cx, &**e, param_substs, fn_args).0)
                               .collect::<Vec<_>>();
@@ -801,9 +801,9 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             }
           }
           ast::ExprRepeat(ref elem, ref count) => {
-            let unit_ty = ty::sequence_element_type(cx.tcx(), ety);
+            let unit_ty = ety.sequence_element_type(cx.tcx());
             let llunitty = type_of::type_of(cx, unit_ty);
-            let n = ty::eval_repeat_count(cx.tcx(), count);
+            let n = cx.tcx().eval_repeat_count(count);
             let unit_val = const_expr(cx, &**elem, param_substs, fn_args).0;
             let vs: Vec<_> = repeat(unit_val).take(n).collect();
             if val_ty(unit_val) != llunitty {
@@ -829,9 +829,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                     const_deref_ptr(cx, get_const_val(cx, def_id, e))
                 }
                 def::DefVariant(enum_did, variant_did, _) => {
-                    let vinfo = ty::enum_variant_with_id(cx.tcx(),
-                                                         enum_did,
-                                                         variant_did);
+                    let vinfo = cx.tcx().enum_variant_with_id(enum_did, variant_did);
                     if !vinfo.args.is_empty() {
                         // N-ary variant.
                         expr::trans_def_fn_unadjusted(cx, e, def, param_substs).val
@@ -875,7 +873,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                       const_fn_call(cx, ExprId(callee.id), did, &arg_vals, param_substs)
                   }
                   def::DefStruct(_) => {
-                      if ty::type_is_simd(cx.tcx(), ety) {
+                      if ety.is_simd(cx.tcx()) {
                           C_vector(&arg_vals[..])
                       } else {
                           let repr = adt::represent_type(cx, ety);
@@ -884,9 +882,7 @@ fn const_expr_unadjusted<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                   }
                   def::DefVariant(enum_did, variant_did, _) => {
                       let repr = adt::represent_type(cx, ety);
-                      let vinfo = ty::enum_variant_with_id(cx.tcx(),
-                                                           enum_did,
-                                                           variant_did);
+                      let vinfo = cx.tcx().enum_variant_with_id(enum_did, variant_did);
                       adt::trans_const(cx,
                                        &*repr,
                                        vinfo.disr_val,
@@ -945,8 +941,8 @@ pub fn trans_static(ccx: &CrateContext, m: ast::Mutability, id: ast::NodeId) ->
         // As an optimization, all shared statics which do not have interior
         // mutability are placed into read-only memory.
         if m != ast::MutMutable {
-            let node_ty = ty::node_id_to_type(ccx.tcx(), id);
-            let tcontents = ty::type_contents(ccx.tcx(), node_ty);
+            let node_ty = ccx.tcx().node_id_to_type(id);
+            let tcontents = node_ty.type_contents(ccx.tcx());
             if !tcontents.interior_unsafe() {
                 llvm::LLVMSetGlobalConstant(g, True);
             }
diff --git a/src/librustc_trans/trans/context.rs b/src/librustc_trans/trans/context.rs
index 0ae69682f91..cf9d70cc657 100644
--- a/src/librustc_trans/trans/context.rs
+++ b/src/librustc_trans/trans/context.rs
@@ -791,7 +791,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
         ($name:expr, fn() -> $ret:expr) => (
             if *key == $name {
                 let f = declare::declare_cfn(ccx, $name, Type::func(&[], &$ret),
-                                             ty::mk_nil(ccx.tcx()));
+                                             ccx.tcx().mk_nil());
                 ccx.intrinsics().borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
@@ -799,7 +799,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
         ($name:expr, fn($($arg:expr),*) -> $ret:expr) => (
             if *key == $name {
                 let f = declare::declare_cfn(ccx, $name, Type::func(&[$($arg),*], &$ret),
-                                             ty::mk_nil(ccx.tcx()));
+                                             ccx.tcx().mk_nil());
                 ccx.intrinsics().borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
@@ -939,7 +939,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
             } else if *key == $name {
                 let f = declare::declare_cfn(ccx, stringify!($cname),
                                              Type::func(&[$($arg),*], &void),
-                                             ty::mk_nil(ccx.tcx()));
+                                             ccx.tcx().mk_nil());
                 llvm::SetLinkage(f, llvm::InternalLinkage);
 
                 let bld = ccx.builder();
@@ -962,7 +962,7 @@ fn declare_intrinsic(ccx: &CrateContext, key: & &'static str) -> Option<ValueRef
             } else if *key == $name {
                 let f = declare::declare_cfn(ccx, stringify!($cname),
                                              Type::func(&[$($arg),*], &$ret),
-                                             ty::mk_nil(ccx.tcx()));
+                                             ccx.tcx().mk_nil());
                 ccx.intrinsics().borrow_mut().insert($name, f.clone());
                 return Some(f);
             }
diff --git a/src/librustc_trans/trans/datum.rs b/src/librustc_trans/trans/datum.rs
index e60e4e4abe0..2c539b67cb6 100644
--- a/src/librustc_trans/trans/datum.rs
+++ b/src/librustc_trans/trans/datum.rs
@@ -101,7 +101,8 @@ use trans::cleanup::CleanupMethods;
 use trans::expr;
 use trans::tvec;
 use trans::type_of;
-use middle::ty::{self, Ty};
+use middle::mem_categorization::Typer;
+use middle::ty::Ty;
 
 use std::fmt;
 use syntax::ast;
@@ -605,9 +606,8 @@ impl<'tcx, K: KindOps + fmt::Debug> Datum<'tcx, K> {
          * affine values (since they must never be duplicated).
          */
 
-        assert!(!ty::type_moves_by_default(&ty::empty_parameter_environment(bcx.tcx()),
-                                           DUMMY_SP,
-                                           self.ty));
+        assert!(!bcx.tcx().empty_parameter_environment()
+                          .type_moves_by_default(self.ty, DUMMY_SP));
         self.shallow_copy_raw(bcx, dst)
     }
 
@@ -640,7 +640,7 @@ impl<'tcx, K: KindOps + fmt::Debug> Datum<'tcx, K> {
     }
 
     pub fn to_llbool<'blk>(self, bcx: Block<'blk, 'tcx>) -> ValueRef {
-        assert!(ty::type_is_bool(self.ty));
+        assert!(self.ty.is_bool());
         self.to_llscalarish(bcx)
     }
 }
diff --git a/src/librustc_trans/trans/debuginfo/metadata.rs b/src/librustc_trans/trans/debuginfo/metadata.rs
index 7660f59e1d0..1fbbf0763aa 100644
--- a/src/librustc_trans/trans/debuginfo/metadata.rs
+++ b/src/librustc_trans/trans/debuginfo/metadata.rs
@@ -242,9 +242,7 @@ impl<'tcx> TypeMap<'tcx> {
             ty::TyTrait(ref trait_data) => {
                 unique_type_id.push_str("trait ");
 
-                let principal =
-                    ty::erase_late_bound_regions(cx.tcx(),
-                                                 &trait_data.principal);
+                let principal = cx.tcx().erase_late_bound_regions(&trait_data.principal);
 
                 from_def_id_and_substs(self,
                                        cx,
@@ -261,7 +259,7 @@ impl<'tcx> TypeMap<'tcx> {
 
                 unique_type_id.push_str(" fn(");
 
-                let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
+                let sig = cx.tcx().erase_late_bound_regions(sig);
 
                 for &parameter_type in &sig.inputs {
                     let parameter_type_id =
@@ -376,7 +374,7 @@ impl<'tcx> TypeMap<'tcx> {
 
         unique_type_id.push_str("|");
 
-        let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
+        let sig = cx.tcx().erase_late_bound_regions(sig);
 
         for &parameter_type in &sig.inputs {
             let parameter_type_id =
@@ -562,7 +560,7 @@ fn vec_slice_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                 unique_type_id: UniqueTypeId,
                                 span: Span)
                                 -> MetadataCreationResult {
-    let data_ptr_type = ty::mk_ptr(cx.tcx(), ty::mt {
+    let data_ptr_type = cx.tcx().mk_ptr(ty::mt {
         ty: element_type,
         mutbl: ast::MutImmutable
     });
@@ -626,7 +624,7 @@ fn subroutine_type_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                       span: Span)
                                       -> MetadataCreationResult
 {
-    let signature = ty::erase_late_bound_regions(cx.tcx(), signature);
+    let signature = cx.tcx().erase_late_bound_regions(signature);
 
     let mut signature_metadata: Vec<DIType> = Vec::with_capacity(signature.inputs.len() + 1);
 
@@ -1176,7 +1174,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                                                   unique_type_id,
                                                   containing_scope);
 
-    let mut fields = ty::struct_fields(cx.tcx(), def_id, substs);
+    let mut fields = cx.tcx().struct_fields(def_id, substs);
 
     // The `Ty` values returned by `ty::struct_fields` can still contain
     // `TyProjection` variants, so normalize those away.
@@ -1192,7 +1190,7 @@ fn prepare_struct_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         struct_llvm_type,
         StructMDF(StructMemberDescriptionFactory {
             fields: fields,
-            is_simd: ty::type_is_simd(cx.tcx(), struct_type),
+            is_simd: struct_type.is_simd(cx.tcx()),
             span: span,
         })
     )
@@ -1588,7 +1586,7 @@ fn prepare_enum_metadata<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
     let loc = span_start(cx, definition_span);
     let file_metadata = file_metadata(cx, &loc.file.name);
 
-    let variants = ty::enum_variants(cx.tcx(), enum_def_id);
+    let variants = cx.tcx().enum_variants(enum_def_id);
 
     let enumerators_metadata: Vec<DIDescriptor> = variants
         .iter()
@@ -1891,7 +1889,7 @@ pub fn create_global_var_metadata(cx: &CrateContext,
     };
 
     let is_local_to_unit = is_node_local_to_unit(cx, node_id);
-    let variable_type = ty::node_id_to_type(cx.tcx(), node_id);
+    let variable_type = cx.tcx().node_id_to_type(node_id);
     let type_metadata = type_metadata(cx, variable_type, span);
     let namespace_node = namespace_for_item(cx, ast_util::local_def(node_id));
     let var_name = token::get_name(name).to_string();
diff --git a/src/librustc_trans/trans/debuginfo/mod.rs b/src/librustc_trans/trans/debuginfo/mod.rs
index 06f1a56c6ef..7487e8d331b 100644
--- a/src/librustc_trans/trans/debuginfo/mod.rs
+++ b/src/librustc_trans/trans/debuginfo/mod.rs
@@ -30,7 +30,7 @@ use rustc::ast_map;
 use trans::common::{NodeIdAndSpan, CrateContext, FunctionContext, Block};
 use trans;
 use trans::monomorphize;
-use middle::ty::{self, Ty, ClosureTyper};
+use middle::ty::{Ty, ClosureTyper};
 use session::config::{self, FullDebugInfo, LimitedDebugInfo, NoDebugInfo};
 use util::nodemap::{DefIdMap, NodeMap, FnvHashMap, FnvHashSet};
 
@@ -412,11 +412,11 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
         // Return type -- llvm::DIBuilder wants this at index 0
         assert_type_for_node_id(cx, fn_ast_id, error_reporting_span);
-        let return_type = ty::node_id_to_type(cx.tcx(), fn_ast_id);
+        let return_type = cx.tcx().node_id_to_type(fn_ast_id);
         let return_type = monomorphize::apply_param_substs(cx.tcx(),
                                                            param_substs,
                                                            &return_type);
-        if ty::type_is_nil(return_type) {
+        if return_type.is_nil() {
             signature.push(ptr::null_mut())
         } else {
             signature.push(type_metadata(cx, return_type, codemap::DUMMY_SP));
@@ -425,7 +425,7 @@ pub fn create_function_debug_context<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
         // Arguments types
         for arg in &fn_decl.inputs {
             assert_type_for_node_id(cx, arg.pat.id, arg.pat.span);
-            let arg_type = ty::node_id_to_type(cx.tcx(), arg.pat.id);
+            let arg_type = cx.tcx().node_id_to_type(arg.pat.id);
             let arg_type = monomorphize::apply_param_substs(cx.tcx(),
                                                             param_substs,
                                                             &arg_type);
diff --git a/src/librustc_trans/trans/debuginfo/namespace.rs b/src/librustc_trans/trans/debuginfo/namespace.rs
index e6fe674f220..2e5943a248a 100644
--- a/src/librustc_trans/trans/debuginfo/namespace.rs
+++ b/src/librustc_trans/trans/debuginfo/namespace.rs
@@ -16,7 +16,7 @@ use llvm;
 use llvm::debuginfo::DIScope;
 use rustc::ast_map;
 use trans::common::CrateContext;
-use middle::ty::{self, ClosureTyper};
+use middle::ty::ClosureTyper;
 
 use std::ffi::CString;
 use std::ptr;
@@ -56,7 +56,7 @@ pub fn crate_root_namespace<'a>(cx: &'a CrateContext) -> &'a str {
 }
 
 pub fn namespace_for_item(cx: &CrateContext, def_id: ast::DefId) -> Rc<NamespaceTreeNode> {
-    ty::with_path(cx.tcx(), def_id, |path| {
+    cx.tcx().with_path(def_id, |path| {
         // prepend crate name if not already present
         let krate = if def_id.krate == ast::LOCAL_CRATE {
             let crate_namespace_name = token::intern(crate_root_namespace(cx));
diff --git a/src/librustc_trans/trans/debuginfo/type_names.rs b/src/librustc_trans/trans/debuginfo/type_names.rs
index 5ba5ecb02c0..6ea43d7392c 100644
--- a/src/librustc_trans/trans/debuginfo/type_names.rs
+++ b/src/librustc_trans/trans/debuginfo/type_names.rs
@@ -106,7 +106,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             output.push(']');
         },
         ty::TyTrait(ref trait_data) => {
-            let principal = ty::erase_late_bound_regions(cx.tcx(), &trait_data.principal);
+            let principal = cx.tcx().erase_late_bound_regions(&trait_data.principal);
             push_item_name(cx, principal.def_id, false, output);
             push_type_params(cx, principal.substs, output);
         },
@@ -123,7 +123,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
 
             output.push_str("fn(");
 
-            let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
+            let sig = cx.tcx().erase_late_bound_regions(sig);
             if !sig.inputs.is_empty() {
                 for &parameter_type in &sig.inputs {
                     push_debuginfo_type_name(cx, parameter_type, true, output);
@@ -144,7 +144,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
             output.push(')');
 
             match sig.output {
-                ty::FnConverging(result_type) if ty::type_is_nil(result_type) => {}
+                ty::FnConverging(result_type) if result_type.is_nil() => {}
                 ty::FnConverging(result_type) => {
                     output.push_str(" -> ");
                     push_debuginfo_type_name(cx, result_type, true, output);
@@ -170,7 +170,7 @@ pub fn push_debuginfo_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                       def_id: ast::DefId,
                       qualified: bool,
                       output: &mut String) {
-        ty::with_path(cx.tcx(), def_id, |path| {
+        cx.tcx().with_path(def_id, |path| {
             if qualified {
                 if def_id.krate == ast::LOCAL_CRATE {
                     output.push_str(crate_root_namespace(cx));
diff --git a/src/librustc_trans/trans/declare.rs b/src/librustc_trans/trans/declare.rs
index 8bc3326d300..646ca6733c3 100644
--- a/src/librustc_trans/trans/declare.rs
+++ b/src/librustc_trans/trans/declare.rs
@@ -128,7 +128,7 @@ pub fn declare_rust_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>, name: &str,
         _ => ccx.sess().bug("expected closure or fn")
     };
 
-    let sig = ty::Binder(ty::erase_late_bound_regions(ccx.tcx(), sig));
+    let sig = ty::Binder(ccx.tcx().erase_late_bound_regions(sig));
     debug!("declare_rust_fn (after region erasure) sig={:?}", sig);
     let llfty = type_of::type_of_rust_fn(ccx, env, &sig, abi);
     debug!("declare_rust_fn llfty={}", ccx.tn().type_to_string(llfty));
diff --git a/src/librustc_trans/trans/expr.rs b/src/librustc_trans/trans/expr.rs
index 5ee71594935..8fd88055b8e 100644
--- a/src/librustc_trans/trans/expr.rs
+++ b/src/librustc_trans/trans/expr.rs
@@ -73,7 +73,6 @@ use trans::monomorphize;
 use trans::tvec;
 use trans::type_of;
 use middle::cast::{CastKind, CastTy};
-use middle::ty::{struct_fields, tup_fields};
 use middle::ty::{AdjustDerefRef, AdjustReifyFnPointer, AdjustUnsafeFnPointer};
 use middle::ty::{self, Ty};
 use middle::ty::MethodCall;
@@ -252,7 +251,7 @@ pub fn trans<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let llty = type_of::type_of(bcx.ccx(), const_ty);
             // HACK(eddyb) get around issues with lifetime intrinsics.
             let scratch = alloca_no_lifetime(bcx, llty, "const");
-            let lldest = if !ty::type_is_structural(const_ty) {
+            let lldest = if !const_ty.is_structural() {
                 // Cast pointer to slot, because constants have different types.
                 PointerCast(bcx, scratch, val_ty(global))
             } else {
@@ -313,7 +312,7 @@ pub fn unsized_info<'ccx, 'tcx>(ccx: &CrateContext<'ccx, 'tcx>,
                                 old_info: Option<ValueRef>,
                                 param_substs: &'tcx Substs<'tcx>)
                                 -> ValueRef {
-    let (source, target) = ty::struct_lockstep_tails(ccx.tcx(), source, target);
+    let (source, target) = ccx.tcx().struct_lockstep_tails(source, target);
     match (&source.sty, &target.sty) {
         (&ty::TyArray(_, len), &ty::TySlice(_)) => C_uint(ccx, len),
         (&ty::TyTrait(_), &ty::TyTrait(_)) => {
@@ -500,7 +499,7 @@ fn coerce_unsized<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
             let kind = match fulfill_obligation(bcx.ccx(), span, trait_ref) {
                 traits::VtableImpl(traits::VtableImplData { impl_def_id, .. }) => {
-                    ty::custom_coerce_unsized_kind(bcx.tcx(), impl_def_id)
+                    bcx.tcx().custom_coerce_unsized_kind(impl_def_id)
                 }
                 vtable => {
                     bcx.sess().span_bug(span, &format!("invalid CoerceUnsized vtable: {:?}",
@@ -748,7 +747,7 @@ fn trans_rec_field<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                base: &ast::Expr,
                                field: ast::Name)
                                -> DatumBlock<'blk, 'tcx, Expr> {
-    trans_field(bcx, base, |tcx, field_tys| ty::field_idx_strict(tcx, field, field_tys))
+    trans_field(bcx, base, |tcx, field_tys| tcx.field_idx_strict(field, field_tys))
 }
 
 /// Translates `base.<idx>`.
@@ -789,9 +788,8 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let ix_datum = unpack_datum!(bcx, trans(bcx, idx));
 
             let ref_ty = // invoked methods have LB regions instantiated:
-                ty::no_late_bound_regions(
-                    bcx.tcx(), &ty::ty_fn_ret(method_ty)).unwrap().unwrap();
-            let elt_ty = match ty::deref(ref_ty, true) {
+                bcx.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap().unwrap();
+            let elt_ty = match ref_ty.builtin_deref(true) {
                 None => {
                     bcx.tcx().sess.span_bug(index_expr.span,
                                             "index method didn't return a \
@@ -835,7 +833,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                                                       ccx.int_type());
             let ix_val = {
                 if ix_size < int_size {
-                    if ty::type_is_signed(expr_ty(bcx, idx)) {
+                    if expr_ty(bcx, idx).is_signed() {
                         SExt(bcx, ix_val, ccx.int_type())
                     } else { ZExt(bcx, ix_val, ccx.int_type()) }
                 } else if ix_size > int_size {
@@ -845,7 +843,7 @@ fn trans_index<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                 }
             };
 
-            let unit_ty = ty::sequence_element_type(bcx.tcx(), base_datum.ty);
+            let unit_ty = base_datum.ty.sequence_element_type(bcx.tcx());
 
             let (base, len) = base_datum.get_vec_base_and_len(bcx);
 
@@ -1110,7 +1108,7 @@ fn trans_rvalue_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                              None,
                              expr.span,
                              expr.id,
-                             ty::mk_struct(tcx, did, tcx.mk_substs(substs)),
+                             tcx.mk_struct(did, tcx.mk_substs(substs)),
                              dest)
             } else {
                 tcx.sess.span_bug(expr.span,
@@ -1227,7 +1225,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 
     match def {
         def::DefVariant(tid, vid, _) => {
-            let variant_info = ty::enum_variant_with_id(bcx.tcx(), tid, vid);
+            let variant_info = bcx.tcx().enum_variant_with_id(tid, vid);
             if !variant_info.args.is_empty() {
                 // N-ary variant.
                 let llfn = callee::trans_fn_ref(bcx.ccx(), vid,
@@ -1247,7 +1245,7 @@ fn trans_def_dps_unadjusted<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         def::DefStruct(_) => {
             let ty = expr_ty(bcx, ref_expr);
             match ty.sty {
-                ty::TyStruct(did, _) if ty::has_dtor(bcx.tcx(), did) => {
+                ty::TyStruct(did, _) if bcx.tcx().has_dtor(did) => {
                     let repr = adt::represent_type(bcx.ccx(), ty);
                     adt::trans_set_discr(bcx, &*repr, lldest, 0);
                 }
@@ -1342,13 +1340,22 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
 {
     match ty.sty {
         ty::TyStruct(did, substs) => {
-            let fields = struct_fields(tcx, did, substs);
+            let fields = tcx.struct_fields(did, substs);
             let fields = monomorphize::normalize_associated_type(tcx, &fields);
             op(0, &fields[..])
         }
 
         ty::TyTuple(ref v) => {
-            op(0, &tup_fields(&v[..]))
+            let fields: Vec<_> = v.iter().enumerate().map(|(i, &f)| {
+                ty::field {
+                    name: token::intern(&i.to_string()),
+                    mt: ty::mt {
+                        ty: f,
+                        mutbl: ast::MutImmutable
+                    }
+                }
+            }).collect();
+            op(0, &fields)
         }
 
         ty::TyEnum(_, substs) => {
@@ -1364,8 +1371,8 @@ pub fn with_field_tys<'tcx, R, F>(tcx: &ty::ctxt<'tcx>,
                     let def = tcx.def_map.borrow().get(&node_id).unwrap().full_def();
                     match def {
                         def::DefVariant(enum_id, variant_id, _) => {
-                            let variant_info = ty::enum_variant_with_id(tcx, enum_id, variant_id);
-                            let fields = struct_fields(tcx, variant_id, substs);
+                            let variant_info = tcx.enum_variant_with_id(enum_id, variant_id);
+                            let fields = tcx.struct_fields(variant_id, substs);
                             let fields = monomorphize::normalize_associated_type(tcx, &fields);
                             op(variant_info.disr_val, &fields[..])
                         }
@@ -1490,7 +1497,7 @@ pub fn trans_adt<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
     // panic occur before the ADT as a whole is ready.
     let custom_cleanup_scope = fcx.push_custom_cleanup_scope();
 
-    if ty::type_is_simd(bcx.tcx(), ty) {
+    if ty.is_simd(bcx.tcx()) {
         // Issue 23112: The original logic appeared vulnerable to same
         // order-of-eval bug. But, SIMD values are tuple-structs;
         // i.e. functional record update (FRU) syntax is unavailable.
@@ -1626,11 +1633,11 @@ fn trans_unary<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             let datum = unpack_datum!(bcx, trans(bcx, sub_expr));
             let val = datum.to_llscalarish(bcx);
             let (bcx, llneg) = {
-                if ty::type_is_fp(un_ty) {
+                if un_ty.is_fp() {
                     let result = FNeg(bcx, val, debug_loc);
                     (bcx, result)
                 } else {
-                    let is_signed = ty::type_is_signed(un_ty);
+                    let is_signed = un_ty.is_signed();
                     let result = Neg(bcx, val, debug_loc);
                     let bcx = if bcx.ccx().check_overflow() && is_signed {
                         let (llty, min) = base::llty_and_min_for_signed_ty(bcx, un_ty);
@@ -1697,7 +1704,7 @@ fn trans_uniq_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn ref_fat_ptr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                            lval: Datum<'tcx, Lvalue>)
                            -> DatumBlock<'blk, 'tcx, Expr> {
-    let dest_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), lval.ty);
+    let dest_ty = bcx.tcx().mk_imm_ref(bcx.tcx().mk_region(ty::ReStatic), lval.ty);
     let scratch = rvalue_scratch_datum(bcx, dest_ty, "__fat_ptr");
     memcpy_ty(bcx, scratch.val, lval.val, scratch.ty);
 
@@ -1735,14 +1742,14 @@ fn trans_eager_binop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let _icx = push_ctxt("trans_eager_binop");
 
     let tcx = bcx.tcx();
-    let is_simd = ty::type_is_simd(tcx, lhs_t);
+    let is_simd = lhs_t.is_simd(tcx);
     let intype = if is_simd {
-        ty::simd_type(tcx, lhs_t)
+        lhs_t.simd_type(tcx)
     } else {
         lhs_t
     };
-    let is_float = ty::type_is_fp(intype);
-    let is_signed = ty::type_is_signed(intype);
+    let is_float = intype.is_fp();
+    let is_signed = intype.is_signed();
     let info = expr_info(binop_expr);
 
     let binop_debug_loc = binop_expr.debug_loc();
@@ -1999,7 +2006,7 @@ pub fn cast_is_noop<'tcx>(tcx: &ty::ctxt<'tcx>,
         return true;
     }
 
-    match (ty::deref(t_in, true), ty::deref(t_out, true)) {
+    match (t_in.builtin_deref(true), t_out.builtin_deref(true)) {
         (Some(ty::mt{ ty: t_in, .. }), Some(ty::mt{ ty: t_out, .. })) => {
             t_in == t_out
         }
@@ -2108,7 +2115,7 @@ fn trans_imm_cast<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ll_t_in = val_ty(discr);
         (discr, adt::is_discr_signed(&*repr))
     } else {
-        (datum.to_llscalarish(bcx), ty::type_is_signed(t_in))
+        (datum.to_llscalarish(bcx), t_in.is_signed())
     };
 
     let newval = match (r_t_in, r_t_out) {
@@ -2180,7 +2187,7 @@ fn auto_ref<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // Compute final type. Note that we are loose with the region and
     // mutability, since those things don't matter in trans.
     let referent_ty = lv_datum.ty;
-    let ptr_ty = ty::mk_imm_rptr(bcx.tcx(), bcx.tcx().mk_region(ty::ReStatic), referent_ty);
+    let ptr_ty = bcx.tcx().mk_imm_ref(bcx.tcx().mk_region(ty::ReStatic), referent_ty);
 
     // Get the pointer.
     let llref = lv_datum.to_llref();
@@ -2241,8 +2248,7 @@ fn deref_once<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
             };
 
             let ref_ty = // invoked methods have their LB regions instantiated
-                ty::no_late_bound_regions(
-                    ccx.tcx(), &ty::ty_fn_ret(method_ty)).unwrap().unwrap();
+                ccx.tcx().no_late_bound_regions(&method_ty.fn_ret()).unwrap().unwrap();
             let scratch = rvalue_scratch_datum(bcx, ref_ty, "overloaded_deref");
 
             unpack_result!(bcx, trans_overloaded_op(bcx, expr, method_call,
@@ -2545,13 +2551,13 @@ fn build_unchecked_rshift<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     // #1877, #10183: Ensure that input is always valid
     let rhs = shift_mask_rhs(bcx, rhs, binop_debug_loc);
     let tcx = bcx.tcx();
-    let is_simd = ty::type_is_simd(tcx, lhs_t);
+    let is_simd = lhs_t.is_simd(tcx);
     let intype = if is_simd {
-        ty::simd_type(tcx, lhs_t)
+        lhs_t.simd_type(tcx)
     } else {
         lhs_t
     };
-    let is_signed = ty::type_is_signed(intype);
+    let is_signed = intype.is_signed();
     if is_signed {
         AShr(bcx, lhs, rhs, binop_debug_loc)
     } else {
@@ -2629,9 +2635,9 @@ fn expr_kind(tcx: &ty::ctxt, expr: &ast::Expr) -> ExprKind {
 
     match expr.node {
         ast::ExprPath(..) => {
-            match ty::resolve_expr(tcx, expr) {
+            match tcx.resolve_expr(expr) {
                 def::DefStruct(_) | def::DefVariant(..) => {
-                    if let ty::TyBareFn(..) = ty::node_id_to_type(tcx, expr.id).sty {
+                    if let ty::TyBareFn(..) = tcx.node_id_to_type(expr.id).sty {
                         // ctor function
                         ExprKind::RvalueDatum
                     } else {
diff --git a/src/librustc_trans/trans/foreign.rs b/src/librustc_trans/trans/foreign.rs
index 4f3f13e4bed..9e8c0189a97 100644
--- a/src/librustc_trans/trans/foreign.rs
+++ b/src/librustc_trans/trans/foreign.rs
@@ -109,7 +109,7 @@ pub fn llvm_calling_convention(ccx: &CrateContext,
 
 pub fn register_static(ccx: &CrateContext,
                        foreign_item: &ast::ForeignItem) -> ValueRef {
-    let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
+    let ty = ccx.tcx().node_id_to_type(foreign_item.id);
     let llty = type_of::type_of(ccx, ty);
 
     let ident = link_name(foreign_item);
@@ -245,7 +245,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         ty::TyBareFn(_, ref fn_ty) => (fn_ty.abi, &fn_ty.sig),
         _ => ccx.sess().bug("trans_native_call called on non-function type")
     };
-    let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
+    let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
     let llsig = foreign_signature(ccx, &fn_sig, &passed_arg_tys[..]);
     let fn_type = cabi::compute_abi_info(ccx,
                                          &llsig.llarg_tys,
@@ -324,7 +324,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         let llarg_foreign = if foreign_indirect {
             llarg_rust
         } else {
-            if ty::type_is_bool(passed_arg_tys[i]) {
+            if passed_arg_tys[i].is_bool() {
                 let val = LoadRangeAssert(bcx, llarg_rust, 0, 2, llvm::False);
                 Trunc(bcx, val, Type::i1(bcx.ccx()))
             } else {
@@ -450,7 +450,7 @@ pub fn trans_native_call<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn gate_simd_ffi(tcx: &ty::ctxt, decl: &ast::FnDecl, ty: &ty::BareFnTy) {
     if !tcx.sess.features.borrow().simd_ffi {
         let check = |ast_ty: &ast::Ty, ty: ty::Ty| {
-            if ty::type_is_simd(tcx, ty) {
+            if ty.is_simd(tcx) {
                 tcx.sess.span_err(ast_ty.span,
                               &format!("use of SIMD type `{}` in FFI is highly experimental and \
                                         may result in invalid code",
@@ -478,7 +478,7 @@ pub fn trans_foreign_mod(ccx: &CrateContext, foreign_mod: &ast::ForeignMod) {
             match foreign_mod.abi {
                 Rust | RustIntrinsic => {}
                 abi => {
-                    let ty = ty::node_id_to_type(ccx.tcx(), foreign_item.id);
+                    let ty = ccx.tcx().node_id_to_type(foreign_item.id);
                     match ty.sty {
                         ty::TyBareFn(_, bft) => gate_simd_ffi(ccx.tcx(), &**decl, bft),
                         _ => ccx.tcx().sess.span_bug(foreign_item.span,
@@ -538,7 +538,7 @@ pub fn decl_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         _ => panic!("expected bare fn in decl_rust_fn_with_foreign_abi")
     };
     let llfn = declare::declare_fn(ccx, name, cconv, llfn_ty,
-                                   ty::FnConverging(ty::mk_nil(ccx.tcx())));
+                                   ty::FnConverging(ccx.tcx().mk_nil()));
     add_argument_attributes(&tys, llfn);
     debug!("decl_rust_fn_with_foreign_abi(llfn_ty={}, llfn={})",
            ccx.tn().type_to_string(llfn_ty), ccx.tn().val_to_string(llfn));
@@ -554,7 +554,7 @@ pub fn register_rust_fn_with_foreign_abi(ccx: &CrateContext,
 
     let tys = foreign_types_for_id(ccx, node_id);
     let llfn_ty = lltype_for_fn_from_foreign_types(ccx, &tys);
-    let t = ty::node_id_to_type(ccx.tcx(), node_id);
+    let t = ccx.tcx().node_id_to_type(node_id);
     let cconv = match t.sty {
         ty::TyBareFn(_, ref fn_ty) => {
             llvm_calling_convention(ccx, fn_ty.abi)
@@ -578,7 +578,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                                 hash: Option<&str>) {
     let _icx = push_ctxt("foreign::build_foreign_fn");
 
-    let fnty = ty::node_id_to_type(ccx.tcx(), id);
+    let fnty = ccx.tcx().node_id_to_type(id);
     let mty = monomorphize::apply_param_substs(ccx.tcx(), param_substs, &fnty);
     let tys = foreign_types_for_fn_ty(ccx, mty);
 
@@ -601,7 +601,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     {
         let _icx = push_ctxt("foreign::foreign::build_rust_fn");
         let tcx = ccx.tcx();
-        let t = ty::node_id_to_type(tcx, id);
+        let t = tcx.node_id_to_type(id);
         let t = monomorphize::apply_param_substs(tcx, param_substs, &t);
 
         let ps = ccx.tcx().map.with_path(id, |path| {
@@ -777,7 +777,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             // pointer).  It makes adapting types easier, since we can
             // always just bitcast pointers.
             if !foreign_indirect {
-                llforeign_arg = if ty::type_is_bool(rust_ty) {
+                llforeign_arg = if rust_ty.is_bool() {
                     let lltemp = builder.alloca(Type::bool(ccx), "");
                     builder.store(builder.zext(llforeign_arg, Type::bool(ccx)), lltemp);
                     lltemp
@@ -799,7 +799,7 @@ pub fn trans_rust_fn_with_foreign_abi<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             let llrust_arg = if rust_indirect || type_is_fat_ptr(ccx.tcx(), rust_ty) {
                 llforeign_arg
             } else {
-                if ty::type_is_bool(rust_ty) {
+                if rust_ty.is_bool() {
                     let tmp = builder.load_range_assert(llforeign_arg, 0, 2, llvm::False);
                     builder.trunc(tmp, Type::i1(ccx))
                 } else if type_of::type_of(ccx, rust_ty).is_aggregate() {
@@ -933,7 +933,7 @@ fn foreign_signature<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
 fn foreign_types_for_id<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
                                   id: ast::NodeId) -> ForeignTypes<'tcx> {
-    foreign_types_for_fn_ty(ccx, ty::node_id_to_type(ccx.tcx(), id))
+    foreign_types_for_fn_ty(ccx, ccx.tcx().node_id_to_type(id))
 }
 
 fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
@@ -942,7 +942,7 @@ fn foreign_types_for_fn_ty<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         ty::TyBareFn(_, ref fn_ty) => &fn_ty.sig,
         _ => ccx.sess().bug("foreign_types_for_fn_ty called on non-function type")
     };
-    let fn_sig = ty::erase_late_bound_regions(ccx.tcx(), fn_sig);
+    let fn_sig = ccx.tcx().erase_late_bound_regions(fn_sig);
     let llsig = foreign_signature(ccx, &fn_sig, &fn_sig.inputs);
     let fn_ty = cabi::compute_abi_info(ccx,
                                        &llsig.llarg_tys,
diff --git a/src/librustc_trans/trans/glue.rs b/src/librustc_trans/trans/glue.rs
index b84475d915a..3bcdcd89c47 100644
--- a/src/librustc_trans/trans/glue.rs
+++ b/src/librustc_trans/trans/glue.rs
@@ -218,7 +218,7 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let llty = if type_is_sized(ccx.tcx(), t) {
         type_of(ccx, t).ptr_to()
     } else {
-        type_of(ccx, ty::mk_uniq(ccx.tcx(), t)).ptr_to()
+        type_of(ccx, ccx.tcx().mk_box(t)).ptr_to()
     };
 
     let llfnty = Type::glue_fn(ccx, llty);
@@ -226,13 +226,13 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     // To avoid infinite recursion, don't `make_drop_glue` until after we've
     // added the entry to the `drop_glues` cache.
     if let Some(old_sym) = ccx.available_drop_glues().borrow().get(&g) {
-        let llfn = declare::declare_cfn(ccx, &old_sym, llfnty, ty::mk_nil(ccx.tcx()));
+        let llfn = declare::declare_cfn(ccx, &old_sym, llfnty, ccx.tcx().mk_nil());
         ccx.drop_glues().borrow_mut().insert(g, llfn);
         return llfn;
     };
 
     let fn_nm = mangle_internal_name_by_type_and_seq(ccx, t, "drop");
-    let llfn = declare::define_cfn(ccx, &fn_nm, llfnty, ty::mk_nil(ccx.tcx())).unwrap_or_else(||{
+    let llfn = declare::define_cfn(ccx, &fn_nm, llfnty, ccx.tcx().mk_nil()).unwrap_or_else(||{
        ccx.sess().bug(&format!("symbol `{}` already defined", fn_nm));
     });
     ccx.available_drop_glues().borrow_mut().insert(g, fn_nm);
@@ -243,10 +243,10 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     let (arena, fcx): (TypedArena<_>, FunctionContext);
     arena = TypedArena::new();
     fcx = new_fn_ctxt(ccx, llfn, ast::DUMMY_NODE_ID, false,
-                      ty::FnConverging(ty::mk_nil(ccx.tcx())),
+                      ty::FnConverging(ccx.tcx().mk_nil()),
                       empty_substs, None, &arena);
 
-    let bcx = init_function(&fcx, false, ty::FnConverging(ty::mk_nil(ccx.tcx())));
+    let bcx = init_function(&fcx, false, ty::FnConverging(ccx.tcx().mk_nil()));
 
     update_linkage(ccx, llfn, None, OriginalTranslation);
 
@@ -261,7 +261,7 @@ fn get_drop_glue_core<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     let llrawptr0 = get_param(llfn, fcx.arg_offset() as c_uint);
     let bcx = make_drop_glue(bcx, llrawptr0, g);
-    finish_fn(&fcx, bcx, ty::FnConverging(ty::mk_nil(ccx.tcx())), DebugLoc::None);
+    finish_fn(&fcx, bcx, ty::FnConverging(ccx.tcx().mk_nil()), DebugLoc::None);
 
     llfn
 }
@@ -326,12 +326,11 @@ pub fn get_res_dtor<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     } else {
         let tcx = ccx.tcx();
         let name = csearch::get_symbol(&ccx.sess().cstore, did);
-        let class_ty = ty::lookup_item_type(tcx, parent_id).ty.subst(tcx, substs);
+        let class_ty = tcx.lookup_item_type(parent_id).ty.subst(tcx, substs);
         let llty = type_of_dtor(ccx, class_ty);
-        let dtor_ty = ty::mk_ctor_fn(ccx.tcx(),
-                                     did,
-                                     &[get_drop_glue_type(ccx, t)],
-                                     ty::mk_nil(ccx.tcx()));
+        let dtor_ty = ccx.tcx().mk_ctor_fn(did,
+                                           &[get_drop_glue_type(ccx, t)],
+                                           ccx.tcx().mk_nil());
         foreign::get_extern_fn(ccx, &mut *ccx.externs().borrow_mut(), &name[..], llvm::CCallConv,
                                llty, dtor_ty)
     }
@@ -371,7 +370,7 @@ fn trans_struct_drop<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     bcx.fcx.schedule_drop_adt_contents(cleanup::CustomScope(contents_scope), v0, t);
 
     let glue_type = get_drop_glue_type(bcx.ccx(), t);
-    let dtor_ty = ty::mk_ctor_fn(bcx.tcx(), class_did, &[glue_type], ty::mk_nil(bcx.tcx()));
+    let dtor_ty = bcx.tcx().mk_ctor_fn(class_did, &[glue_type], bcx.tcx().mk_nil());
     let (_, bcx) = invoke(bcx, dtor_addr, &[v0], dtor_ty, DebugLoc::None);
 
     bcx.fcx.pop_and_trans_custom_cleanup_scope(bcx, contents_scope)
@@ -392,7 +391,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
             let ccx = bcx.ccx();
             // First get the size of all statically known fields.
             // Don't use type_of::sizing_type_of because that expects t to be sized.
-            assert!(!ty::type_is_simd(bcx.tcx(), t));
+            assert!(!t.is_simd(bcx.tcx()));
             let repr = adt::represent_type(ccx, t);
             let sizing_type = adt::sizing_type_of(ccx, &*repr, true);
             let sized_size = C_uint(ccx, llsize_of_alloc(ccx, sizing_type));
@@ -400,7 +399,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
 
             // Recurse to get the size of the dynamically sized field (must be
             // the last field).
-            let fields = ty::struct_fields(bcx.tcx(), id, substs);
+            let fields = bcx.tcx().struct_fields(id, substs);
             let last_field = fields[fields.len()-1];
             let field_ty = last_field.mt.ty;
             let (unsized_size, unsized_align) = size_and_align_of_dst(bcx, field_ty, info);
@@ -426,7 +425,7 @@ pub fn size_and_align_of_dst<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, t: Ty<'tcx>, in
             (Load(bcx, size_ptr), Load(bcx, align_ptr))
         }
         ty::TySlice(_) | ty::TyStr => {
-            let unit_ty = ty::sequence_element_type(bcx.tcx(), t);
+            let unit_ty = t.sequence_element_type(bcx.tcx());
             // The info in this case is the length of the str, so the size is that
             // times the unit size.
             let llunit_ty = sizing_type_of(bcx.ccx(), unit_ty);
@@ -496,7 +495,7 @@ fn make_drop_glue<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, v0: ValueRef, g: DropGlueK
         }
         ty::TyStruct(did, substs) | ty::TyEnum(did, substs) => {
             let tcx = bcx.tcx();
-            match (ty::ty_dtor(tcx, did), skip_dtor) {
+            match (tcx.ty_dtor(did), skip_dtor) {
                 (ty::TraitDtor(dtor, true), false) => {
                     // FIXME(16758) Since the struct is unsized, it is hard to
                     // find the drop flag (which is at the end of the struct).
diff --git a/src/librustc_trans/trans/inline.rs b/src/librustc_trans/trans/inline.rs
index f860fe44f28..75c80690f2a 100644
--- a/src/librustc_trans/trans/inline.rs
+++ b/src/librustc_trans/trans/inline.rs
@@ -14,7 +14,6 @@ use middle::astencode;
 use middle::subst::Substs;
 use trans::base::{push_ctxt, trans_item, get_item_val, trans_fn};
 use trans::common::*;
-use middle::ty;
 
 use syntax::ast;
 use syntax::ast_util::local_def;
@@ -28,7 +27,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
         Some(&Some(node_id)) => {
             // Already inline
             debug!("instantiate_inline({}): already inline as node id {}",
-                   ty::item_path_str(ccx.tcx(), fn_id), node_id);
+                   ccx.tcx().item_path_str(fn_id), node_id);
             return Some(local_def(node_id));
         }
         Some(&None) => {
@@ -104,8 +103,8 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
           let mut my_id = 0;
           match item.node {
             ast::ItemEnum(_, _) => {
-              let vs_here = ty::enum_variants(ccx.tcx(), local_def(item.id));
-              let vs_there = ty::enum_variants(ccx.tcx(), parent_id);
+              let vs_here = ccx.tcx().enum_variants(local_def(item.id));
+              let vs_there = ccx.tcx().enum_variants(parent_id);
               for (here, there) in vs_here.iter().zip(vs_there.iter()) {
                   if there.id == fn_id { my_id = here.id.node; }
                   ccx.external().borrow_mut().insert(there.id, Some(here.id.node));
@@ -140,7 +139,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
             // the logic to do that already exists in `middle`. In order to
             // reuse that code, it needs to be able to look up the traits for
             // inlined items.
-            let ty_trait_item = ty::impl_or_trait_item(ccx.tcx(), fn_id).clone();
+            let ty_trait_item = ccx.tcx().impl_or_trait_item(fn_id).clone();
             ccx.tcx().impl_or_trait_items.borrow_mut()
                      .insert(local_def(trait_item.id), ty_trait_item);
 
@@ -157,7 +156,7 @@ fn instantiate_inline(ccx: &CrateContext, fn_id: ast::DefId)
 
             // Translate monomorphic impl methods immediately.
             if let ast::MethodImplItem(ref sig, ref body) = impl_item.node {
-                let impl_tpt = ty::lookup_item_type(ccx.tcx(), impl_did);
+                let impl_tpt = ccx.tcx().lookup_item_type(impl_did);
                 if impl_tpt.generics.types.is_empty() &&
                         sig.generics.ty_params.is_empty() {
                     let empty_substs = ccx.tcx().mk_substs(Substs::trans_empty());
diff --git a/src/librustc_trans/trans/intrinsic.rs b/src/librustc_trans/trans/intrinsic.rs
index dd97265e428..b449c3ad060 100644
--- a/src/librustc_trans/trans/intrinsic.rs
+++ b/src/librustc_trans/trans/intrinsic.rs
@@ -30,7 +30,7 @@ use trans::type_of;
 use trans::machine;
 use trans::machine::llsize_of;
 use trans::type_::Type;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use syntax::abi::RustIntrinsic;
 use syntax::ast;
 use syntax::parse::token;
@@ -103,8 +103,8 @@ pub fn check_intrinsics(ccx: &CrateContext) {
 
         debug!("transmute_restriction: {:?}", transmute_restriction);
 
-        assert!(!ty::type_has_params(transmute_restriction.substituted_from));
-        assert!(!ty::type_has_params(transmute_restriction.substituted_to));
+        assert!(!transmute_restriction.substituted_from.has_param_types());
+        assert!(!transmute_restriction.substituted_to.has_param_types());
 
         let llfromtype = type_of::sizing_type_of(ccx,
                                                  transmute_restriction.substituted_from);
@@ -163,7 +163,7 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
 
     let ret_ty = match callee_ty.sty {
         ty::TyBareFn(_, ref f) => {
-            ty::erase_late_bound_regions(bcx.tcx(), &f.sig.output())
+            bcx.tcx().erase_late_bound_regions(&f.sig.output())
         }
         _ => panic!("expected bare_fn in trans_intrinsic_call")
     };
@@ -411,10 +411,8 @@ pub fn trans_intrinsic_call<'a, 'blk, 'tcx>(mut bcx: Block<'blk, 'tcx>,
             C_str_slice(ccx, ty_name)
         }
         (_, "type_id") => {
-            let hash = ty::hash_crate_independent(
-                ccx.tcx(),
-                *substs.types.get(FnSpace, 0),
-                &ccx.link_meta().crate_hash);
+            let hash = ccx.tcx().hash_crate_independent(*substs.types.get(FnSpace, 0),
+                                                        &ccx.link_meta().crate_hash);
             C_u64(ccx, hash)
         }
         (_, "init_dropped") => {
diff --git a/src/librustc_trans/trans/meth.rs b/src/librustc_trans/trans/meth.rs
index e61770768db..a3e5b640fd0 100644
--- a/src/librustc_trans/trans/meth.rs
+++ b/src/librustc_trans/trans/meth.rs
@@ -37,7 +37,7 @@ use trans::machine;
 use trans::monomorphize;
 use trans::type_::Type;
 use trans::type_of::*;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use middle::ty::MethodCall;
 
 use syntax::abi::{Rust, RustCall};
@@ -182,7 +182,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     debug!("trans_static_method_callee(method_id={:?}, trait_id={}, \
             expr_id={})",
            method_id,
-           ty::item_path_str(tcx, trait_id),
+           tcx.item_path_str(trait_id),
            expr_id);
 
     let mname = if method_id.krate == ast::LOCAL_CRATE {
@@ -248,7 +248,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             substs: impl_substs,
             nested: _ }) =>
         {
-            assert!(impl_substs.types.all(|t| !ty::type_needs_infer(*t)));
+            assert!(!impl_substs.types.needs_infer());
 
             // Create the substitutions that are in scope. This combines
             // the type parameters from the impl with those declared earlier.
@@ -282,7 +282,7 @@ pub fn trans_static_method_callee<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
         traits::VtableObject(ref data) => {
             let trait_item_def_ids =
-                ty::trait_item_def_ids(ccx.tcx(), trait_id);
+                ccx.tcx().trait_item_def_ids(trait_id);
             let method_offset_in_trait =
                 trait_item_def_ids.iter()
                                   .position(|item| item.def_id() == method_id)
@@ -314,7 +314,7 @@ fn method_with_name(ccx: &CrateContext, impl_id: ast::DefId, name: ast::Name)
                   .expect("could not find impl while translating");
     let meth_did = impl_items.iter()
                              .find(|&did| {
-                                ty::impl_or_trait_item(ccx.tcx(), did.def_id()).name() == name
+                                ccx.tcx().impl_or_trait_item(did.def_id()).name() == name
                              }).expect("could not find method while \
                                         translating");
 
@@ -334,7 +334,7 @@ fn trans_monomorphized_callee<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
         traits::VtableImpl(vtable_impl) => {
             let ccx = bcx.ccx();
             let impl_did = vtable_impl.impl_def_id;
-            let mname = match ty::trait_item(ccx.tcx(), trait_id, n_method) {
+            let mname = match ccx.tcx().trait_item(trait_id, n_method) {
                 ty::MethodTraitItem(method) => method.name,
                 _ => {
                     bcx.tcx().sess.bug("can't monomorphize a non-method trait \
@@ -567,12 +567,12 @@ pub fn trans_object_shim<'a, 'tcx>(
         };
 
     // Upcast to the trait in question and extract out the substitutions.
-    let upcast_trait_ref = ty::erase_late_bound_regions(tcx, &upcast_trait_ref);
+    let upcast_trait_ref = tcx.erase_late_bound_regions(&upcast_trait_ref);
     let object_substs = upcast_trait_ref.substs.clone().erase_regions();
     debug!("trans_object_shim: object_substs={:?}", object_substs);
 
     // Lookup the type of this method as declared in the trait and apply substitutions.
-    let method_ty = match ty::trait_item(tcx, trait_id, method_offset_in_trait) {
+    let method_ty = match tcx.trait_item(trait_id, method_offset_in_trait) {
         ty::MethodTraitItem(method) => method,
         _ => {
             tcx.sess.bug("can't create a method shim for a non-method item")
@@ -584,14 +584,14 @@ pub fn trans_object_shim<'a, 'tcx>(
     debug!("trans_object_shim: fty={:?} method_ty={:?}", fty, method_ty);
 
     //
-    let shim_fn_ty = ty::mk_bare_fn(tcx, None, fty);
-    let method_bare_fn_ty = ty::mk_bare_fn(tcx, None, method_ty);
+    let shim_fn_ty = tcx.mk_fn(None, fty);
+    let method_bare_fn_ty = tcx.mk_fn(None, method_ty);
     let function_name = link::mangle_internal_name_by_type_and_seq(ccx, shim_fn_ty, "object_shim");
     let llfn = declare::define_internal_rust_fn(ccx, &function_name, shim_fn_ty).unwrap_or_else(||{
         ccx.sess().bug(&format!("symbol `{}` already defined", function_name));
     });
 
-    let sig = ty::erase_late_bound_regions(ccx.tcx(), &fty.sig);
+    let sig = ccx.tcx().erase_late_bound_regions(&fty.sig);
 
     let empty_substs = tcx.mk_substs(Substs::trans_empty());
     let (block_arena, fcx): (TypedArena<_>, FunctionContext);
@@ -747,16 +747,16 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            substs,
            param_substs);
 
-    let trt_id = match ty::impl_trait_ref(tcx, impl_id) {
+    let trt_id = match tcx.impl_trait_ref(impl_id) {
         Some(t_id) => t_id.def_id,
         None       => ccx.sess().bug("make_impl_vtable: don't know how to \
                                       make a vtable for a type impl!")
     };
 
-    ty::populate_implementations_for_trait_if_necessary(tcx, trt_id);
+    tcx.populate_implementations_for_trait_if_necessary(trt_id);
 
     let nullptr = C_null(Type::nil(ccx).ptr_to());
-    let trait_item_def_ids = ty::trait_item_def_ids(tcx, trt_id);
+    let trait_item_def_ids = tcx.trait_item_def_ids(trt_id);
     trait_item_def_ids
         .iter()
 
@@ -775,7 +775,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             debug!("emit_vtable_methods: trait_method_def_id={:?}",
                    trait_method_def_id);
 
-            let trait_method_type = match ty::impl_or_trait_item(tcx, trait_method_def_id) {
+            let trait_method_type = match tcx.impl_or_trait_item(trait_method_def_id) {
                 ty::MethodTraitItem(m) => m,
                 _ => ccx.sess().bug("should be a method, not other assoc item"),
             };
@@ -793,7 +793,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             // The substitutions we have are on the impl, so we grab
             // the method type from the impl to substitute into.
             let impl_method_def_id = method_with_name(ccx, impl_id, name);
-            let impl_method_type = match ty::impl_or_trait_item(tcx, impl_method_def_id) {
+            let impl_method_type = match tcx.impl_or_trait_item(impl_method_def_id) {
                 ty::MethodTraitItem(m) => m,
                 _ => ccx.sess().bug("should be a method, not other assoc item"),
             };
@@ -806,7 +806,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
             // particular set of type parameters. Note that this
             // method could then never be called, so we do not want to
             // try and trans it, in that case. Issue #23435.
-            if ty::provided_source(tcx, impl_method_def_id).is_some() {
+            if tcx.provided_source(impl_method_def_id).is_some() {
                 let predicates = impl_method_type.predicates.predicates.subst(tcx, &substs);
                 if !normalize_and_test_predicates(ccx, predicates.into_vec()) {
                     debug!("emit_vtable_methods: predicates do not hold");
@@ -827,7 +827,7 @@ fn emit_vtable_methods<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 pub fn opaque_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>, method_ty: &ty::BareFnTy<'tcx>)
         -> &'tcx ty::BareFnTy<'tcx> {
     let mut inputs = method_ty.sig.0.inputs.clone();
-    inputs[0] = ty::mk_mut_ptr(tcx, ty::mk_mach_int(tcx, ast::TyI8));
+    inputs[0] = tcx.mk_mut_ptr(tcx.mk_mach_int(ast::TyI8));
 
     tcx.mk_bare_fn(ty::BareFnTy {
         unsafety: method_ty.unsafety,
diff --git a/src/librustc_trans/trans/monomorphize.rs b/src/librustc_trans/trans/monomorphize.rs
index f4bad313baf..cae810c9082 100644
--- a/src/librustc_trans/trans/monomorphize.rs
+++ b/src/librustc_trans/trans/monomorphize.rs
@@ -25,7 +25,7 @@ use trans::base;
 use trans::common::*;
 use trans::declare;
 use trans::foreign;
-use middle::ty::{self, HasProjectionTypes, Ty};
+use middle::ty::{self, HasTypeFlags, Ty};
 
 use syntax::abi;
 use syntax::ast;
@@ -47,9 +47,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
            psubsts,
            ref_id);
 
-    assert!(psubsts.types.all(|t| {
-        !ty::type_needs_infer(*t) && !ty::type_has_params(*t)
-    }));
+    assert!(!psubsts.types.needs_infer() && !psubsts.types.has_param_types());
 
     let _icx = push_ctxt("monomorphic_fn");
 
@@ -58,7 +56,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         params: &psubsts.types
     };
 
-    let item_ty = ty::lookup_item_type(ccx.tcx(), fn_id).ty;
+    let item_ty = ccx.tcx().lookup_item_type(fn_id).ty;
 
     debug!("monomorphic_fn about to subst into {:?}", item_ty);
     let mono_ty = item_ty.subst(ccx.tcx(), psubsts);
@@ -66,7 +64,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
     match ccx.monomorphized().borrow().get(&hash_id) {
         Some(&val) => {
             debug!("leaving monomorphic fn {}",
-            ty::item_path_str(ccx.tcx(), fn_id));
+            ccx.tcx().item_path_str(fn_id));
             return (val, mono_ty, false);
         }
         None => ()
@@ -200,7 +198,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
         }
         ast_map::NodeVariant(v) => {
             let parent = ccx.tcx().map.get_parent(fn_id.node);
-            let tvs = ty::enum_variants(ccx.tcx(), local_def(parent));
+            let tvs = ccx.tcx().enum_variants(local_def(parent));
             let this_tv = tvs.iter().find(|tv| { tv.id.node == fn_id.node}).unwrap();
             let d = mk_lldecl(abi::Rust);
             attributes::inline(d, attributes::InlineAttr::Hint);
@@ -286,7 +284,7 @@ pub fn monomorphic_fn<'a, 'tcx>(ccx: &CrateContext<'a, 'tcx>,
 
     ccx.monomorphizing().borrow_mut().insert(fn_id, depth);
 
-    debug!("leaving monomorphic fn {}", ty::item_path_str(ccx.tcx(), fn_id));
+    debug!("leaving monomorphic fn {}", ccx.tcx().item_path_str(fn_id));
     (lldecl, mono_ty, true)
 }
 
@@ -302,7 +300,7 @@ pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>,
                                   param_substs: &Substs<'tcx>,
                                   value: &T)
                                   -> T
-    where T : TypeFoldable<'tcx> + HasProjectionTypes
+    where T : TypeFoldable<'tcx> + HasTypeFlags
 {
     let substituted = value.subst(tcx, param_substs);
     normalize_associated_type(tcx, &substituted)
@@ -313,7 +311,7 @@ pub fn apply_param_substs<'tcx,T>(tcx: &ty::ctxt<'tcx>,
 /// and hence we can be sure that all associated types will be
 /// completely normalized away.
 pub fn normalize_associated_type<'tcx,T>(tcx: &ty::ctxt<'tcx>, value: &T) -> T
-    where T : TypeFoldable<'tcx> + HasProjectionTypes
+    where T : TypeFoldable<'tcx> + HasTypeFlags
 {
     debug!("normalize_associated_type(t={:?})", value);
 
diff --git a/src/librustc_trans/trans/tvec.rs b/src/librustc_trans/trans/tvec.rs
index bba0f6d2608..d94a0e235ee 100644
--- a/src/librustc_trans/trans/tvec.rs
+++ b/src/librustc_trans/trans/tvec.rs
@@ -106,9 +106,7 @@ pub fn trans_slice_vec<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
     let count = elements_required(bcx, content_expr);
     debug!("    vt={}, count={}", vt.to_string(ccx), count);
 
-    let fixed_ty = ty::mk_vec(bcx.tcx(),
-                              vt.unit_ty,
-                              Some(count));
+    let fixed_ty = bcx.tcx().mk_array(vt.unit_ty, count);
     let llfixed_ty = type_of::type_of(bcx.ccx(), fixed_ty);
 
     // Always create an alloca even if zero-sized, to preserve
@@ -227,7 +225,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
                     return expr::trans_into(bcx, &**element, Ignore);
                 }
                 SaveIn(lldest) => {
-                    match ty::eval_repeat_count(bcx.tcx(), &**count_expr) {
+                    match bcx.tcx().eval_repeat_count(&**count_expr) {
                         0 => expr::trans_into(bcx, &**element, Ignore),
                         1 => expr::trans_into(bcx, &**element, SaveIn(lldest)),
                         count => {
@@ -253,7 +251,7 @@ fn write_content<'blk, 'tcx>(bcx: Block<'blk, 'tcx>,
 fn vec_types_from_expr<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, vec_expr: &ast::Expr)
                                    -> VecTypes<'tcx> {
     let vec_ty = node_id_type(bcx, vec_expr.id);
-    vec_types(bcx, ty::sequence_element_type(bcx.tcx(), vec_ty))
+    vec_types(bcx, vec_ty.sequence_element_type(bcx.tcx()))
 }
 
 fn vec_types<'blk, 'tcx>(bcx: Block<'blk, 'tcx>, unit_ty: Ty<'tcx>)
@@ -279,7 +277,7 @@ fn elements_required(bcx: Block, content_expr: &ast::Expr) -> usize {
         },
         ast::ExprVec(ref es) => es.len(),
         ast::ExprRepeat(_, ref count_expr) => {
-            ty::eval_repeat_count(bcx.tcx(), &**count_expr)
+            bcx.tcx().eval_repeat_count(&**count_expr)
         }
         _ => bcx.tcx().sess.span_bug(content_expr.span,
                                      "unexpected vec content")
diff --git a/src/librustc_trans/trans/type_of.rs b/src/librustc_trans/trans/type_of.rs
index 49601ac6fe9..20d25518e27 100644
--- a/src/librustc_trans/trans/type_of.rs
+++ b/src/librustc_trans/trans/type_of.rs
@@ -102,7 +102,7 @@ pub fn type_of_rust_fn<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
            sig,
            abi);
 
-    let sig = ty::erase_late_bound_regions(cx.tcx(), sig);
+    let sig = cx.tcx().erase_late_bound_regions(sig);
     assert!(!sig.variadic); // rust fns are never variadic
 
     let mut atys: Vec<Type> = Vec::new();
@@ -222,9 +222,9 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
         }
 
         ty::TyStruct(..) => {
-            if ty::type_is_simd(cx.tcx(), t) {
-                let llet = type_of(cx, ty::simd_type(cx.tcx(), t));
-                let n = ty::simd_size(cx.tcx(), t) as u64;
+            if t.is_simd(cx.tcx()) {
+                let llet = type_of(cx, t.simd_type(cx.tcx()));
+                let n = t.simd_size(cx.tcx()) as u64;
                 ensure_array_fits_in_address_space(cx, llet, n, t);
                 Type::vector(&llet, n)
             } else {
@@ -245,7 +245,7 @@ pub fn sizing_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Typ
 }
 
 pub fn foreign_arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-    if ty::type_is_bool(t) {
+    if t.is_bool() {
         Type::i1(cx)
     } else {
         type_of(cx, t)
@@ -253,7 +253,7 @@ pub fn foreign_arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -
 }
 
 pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
-    if ty::type_is_bool(t) {
+    if t.is_bool() {
         Type::i1(cx)
     } else if type_is_immediate(cx, t) && type_of(cx, t).is_aggregate() {
         // We want to pass small aggregates as immediate values, but using an aggregate LLVM type
@@ -278,7 +278,7 @@ pub fn arg_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) -> Type {
 /// For the raw type without far pointer indirection, see `in_memory_type_of`.
 pub fn type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, ty: Ty<'tcx>) -> Type {
     let ty = if !type_is_sized(cx.tcx(), ty) {
-        ty::mk_imm_ptr(cx.tcx(), ty)
+        cx.tcx().mk_imm_ptr(ty)
     } else {
         ty
     };
@@ -362,7 +362,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
                   cx.tn().find_type("str_slice").unwrap()
               } else {
                   let ptr_ty = in_memory_type_of(cx, ty).ptr_to();
-                  let unsized_part = ty::struct_tail(cx.tcx(), ty);
+                  let unsized_part = cx.tcx().struct_tail(ty);
                   let info_ty = match unsized_part.sty {
                       ty::TyStr | ty::TyArray(..) | ty::TySlice(_) => {
                           Type::uint_from_ty(cx, ast::TyUs)
@@ -402,9 +402,9 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
           adt::type_of(cx, &*repr)
       }
       ty::TyStruct(did, ref substs) => {
-          if ty::type_is_simd(cx.tcx(), t) {
-              let llet = in_memory_type_of(cx, ty::simd_type(cx.tcx(), t));
-              let n = ty::simd_size(cx.tcx(), t) as u64;
+          if t.is_simd(cx.tcx()) {
+              let llet = in_memory_type_of(cx, t.simd_type(cx.tcx()));
+              let n = t.simd_size(cx.tcx()) as u64;
               ensure_array_fits_in_address_space(cx, llet, n, t);
               Type::vector(&llet, n)
           } else {
@@ -434,7 +434,7 @@ pub fn in_memory_type_of<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>, t: Ty<'tcx>) ->
     // If this was an enum or struct, fill in the type now.
     match t.sty {
         ty::TyEnum(..) | ty::TyStruct(..) | ty::TyClosure(..)
-                if !ty::type_is_simd(cx.tcx(), t) => {
+                if !t.is_simd(cx.tcx()) => {
             let repr = adt::represent_type(cx, t);
             adt::finish_type_of(cx, &*repr, &mut llty);
         }
@@ -454,7 +454,7 @@ fn llvm_type_name<'a, 'tcx>(cx: &CrateContext<'a, 'tcx>,
                             did: ast::DefId,
                             tps: &[Ty<'tcx>])
                             -> String {
-    let base = ty::item_path_str(cx.tcx(), did);
+    let base = cx.tcx().item_path_str(did);
     let strings: Vec<String> = tps.iter().map(|t| t.to_string()).collect();
     let tstr = if strings.is_empty() {
         base
diff --git a/src/librustc_typeck/astconv.rs b/src/librustc_typeck/astconv.rs
index d4ecdc65ead..2575dc0184f 100644
--- a/src/librustc_typeck/astconv.rs
+++ b/src/librustc_typeck/astconv.rs
@@ -56,7 +56,7 @@ use middle::resolve_lifetime as rl;
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst::{FnSpace, TypeSpace, SelfSpace, Subst, Substs};
 use middle::traits;
-use middle::ty::{self, RegionEscape, Ty, ToPredicate};
+use middle::ty::{self, RegionEscape, Ty, ToPredicate, HasTypeFlags};
 use middle::ty_fold;
 use rscope::{self, UnelidableRscope, RegionScope, ElidableRscope, ExplicitRscope,
              ObjectLifetimeDefaultRscope, ShiftedRscope, BindingRscope};
@@ -124,7 +124,7 @@ pub trait AstConv<'tcx> {
                                         item_name: ast::Name)
                                         -> Ty<'tcx>
     {
-        if ty::binds_late_bound_regions(self.tcx(), &poly_trait_ref) {
+        if self.tcx().binds_late_bound_regions(&poly_trait_ref) {
             span_err!(self.tcx().sess, span, E0212,
                 "cannot extract an associated type from a higher-ranked trait bound \
                  in this context");
@@ -439,7 +439,7 @@ fn create_substs_for_ast_path<'tcx>(
             // other type parameters may reference `Self` in their
             // defaults. This will lead to an ICE if we are not
             // careful!
-            if self_ty.is_none() && ty::type_has_self(default) {
+            if self_ty.is_none() && default.has_self_ty() {
                 span_err!(tcx.sess, span, E0393,
                           "the type parameter `{}` must be explicitly specified \
                            in an object type because its default value `{}` references \
@@ -513,7 +513,7 @@ fn find_implied_output_region(input_tys: &[Ty], input_pats: Vec<String>)
 
     for (input_type, input_pat) in input_tys.iter().zip(input_pats) {
         let mut accumulator = Vec::new();
-        ty::accumulate_lifetimes_in_type(&mut accumulator, *input_type);
+        input_type.accumulate_lifetimes_in_type(&mut accumulator);
 
         if accumulator.len() == 1 {
             // there's a chance that the unique lifetime of this
@@ -579,7 +579,7 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
     let (implied_output_region,
          params_lifetimes) = find_implied_output_region(&*inputs, input_params);
 
-    let input_ty = ty::mk_tup(this.tcx(), inputs);
+    let input_ty = this.tcx().mk_tup(inputs);
 
     let (output, output_span) = match data.output {
         Some(ref output_ty) => {
@@ -590,7 +590,7 @@ fn convert_parenthesized_parameters<'tcx>(this: &AstConv<'tcx>,
              output_ty.span)
         }
         None => {
-            (ty::mk_nil(this.tcx()), data.span)
+            (this.tcx().mk_nil(), data.span)
         }
     };
 
@@ -852,7 +852,7 @@ fn ast_type_binding_to_poly_projection_predicate<'tcx>(
     // this, we currently insert a dummy type and then remove it
     // later. Yuck.
 
-    let dummy_self_ty = ty::mk_infer(tcx, ty::FreshTy(0));
+    let dummy_self_ty = tcx.mk_infer(ty::FreshTy(0));
     if self_ty.is_none() { // if converting for an object type
         let mut dummy_substs = trait_ref.skip_binder().substs.clone(); // binder moved here -+
         assert!(dummy_substs.self_ty().is_none());                     //                    |
@@ -924,7 +924,7 @@ fn ast_path_to_ty<'tcx>(
     // FIXME(#12938): This is a hack until we have full support for DST.
     if Some(did) == this.tcx().lang_items.owned_box() {
         assert_eq!(substs.types.len(TypeSpace), 1);
-        return ty::mk_uniq(this.tcx(), *substs.types.get(TypeSpace, 0));
+        return this.tcx().mk_box(*substs.types.get(TypeSpace, 0));
     }
 
     decl_ty.subst(this.tcx(), &substs)
@@ -1060,7 +1060,7 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
     let mut associated_types: FnvHashSet<(ast::DefId, ast::Name)> =
         traits::supertraits(tcx, object_trait_ref)
         .flat_map(|tr| {
-            let trait_def = ty::lookup_trait_def(tcx, tr.def_id());
+            let trait_def = tcx.lookup_trait_def(tr.def_id());
             trait_def.associated_type_names
                 .clone()
                 .into_iter()
@@ -1078,10 +1078,10 @@ fn make_object_type<'tcx>(this: &AstConv<'tcx>,
         span_err!(tcx.sess, span, E0191,
             "the value of the associated type `{}` (from the trait `{}`) must be specified",
                     name,
-                    ty::item_path_str(tcx, trait_def_id));
+                    tcx.item_path_str(trait_def_id));
     }
 
-    ty::mk_trait(tcx, object.principal, object.bounds)
+    tcx.mk_trait(object.principal, object.bounds)
 }
 
 fn report_ambiguous_associated_type(tcx: &ty::ctxt,
@@ -1265,7 +1265,7 @@ fn associated_path_def_to_ty<'tcx>(this: &AstConv<'tcx>,
             _ => unreachable!()
         }
     } else {
-        let trait_items = ty::trait_items(tcx, trait_did);
+        let trait_items = tcx.trait_items(trait_did);
         let item = trait_items.iter().find(|i| i.name() == assoc_name);
         item.expect("missing associated type").def_id()
     };
@@ -1290,7 +1290,7 @@ fn qpath_to_ty<'tcx>(this: &AstConv<'tcx>,
     let self_ty = if let Some(ty) = opt_self_ty {
         ty
     } else {
-        let path_str = ty::item_path_str(tcx, trait_def_id);
+        let path_str = tcx.item_path_str(trait_def_id);
         report_ambiguous_associated_type(tcx,
                                          span,
                                          "Type",
@@ -1393,7 +1393,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         }
         def::DefTyParam(space, index, _, name) => {
             check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
-            ty::mk_param(tcx, space, index, name)
+            tcx.mk_param(space, index, name)
         }
         def::DefSelfTy(_, Some((_, self_ty_id))) => {
             // Self in impl (we know the concrete type).
@@ -1411,7 +1411,7 @@ fn base_def_to_ty<'tcx>(this: &AstConv<'tcx>,
         def::DefSelfTy(Some(_), None) => {
             // Self in trait.
             check_path_args(tcx, base_segments, NO_TPS | NO_REGIONS);
-            ty::mk_self_type(tcx)
+            tcx.mk_self_type()
         }
         def::DefAssociatedTy(trait_did, _) => {
             check_path_args(tcx, &base_segments[..base_segments.len()-2], NO_TPS | NO_REGIONS);
@@ -1509,7 +1509,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
 
     let typ = match ast_ty.node {
         ast::TyVec(ref ty) => {
-            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty), None)
+            tcx.mk_slice(ast_ty_to_ty(this, rscope, &**ty))
         }
         ast::TyObjectSum(ref ty, ref bounds) => {
             match ast_ty_to_trait_ref(this, rscope, &**ty, bounds) {
@@ -1527,7 +1527,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
             }
         }
         ast::TyPtr(ref mt) => {
-            ty::mk_ptr(tcx, ty::mt {
+            tcx.mk_ptr(ty::mt {
                 ty: ast_ty_to_ty(this, rscope, &*mt.ty),
                 mutbl: mt.mutbl
             })
@@ -1540,13 +1540,13 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                     rscope,
                     Some(ty::ObjectLifetimeDefault::Specific(r)));
             let t = ast_ty_to_ty(this, rscope1, &*mt.ty);
-            ty::mk_rptr(tcx, tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
+            tcx.mk_ref(tcx.mk_region(r), ty::mt {ty: t, mutbl: mt.mutbl})
         }
         ast::TyTup(ref fields) => {
             let flds = fields.iter()
                              .map(|t| ast_ty_to_ty(this, rscope, &**t))
                              .collect();
-            ty::mk_tup(tcx, flds)
+            tcx.mk_tup(flds)
         }
         ast::TyParen(ref typ) => ast_ty_to_ty(this, rscope, &**typ),
         ast::TyBareFn(ref bf) => {
@@ -1555,7 +1555,7 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                           "variadic function must have C calling convention");
             }
             let bare_fn = ty_of_bare_fn(this, bf.unsafety, bf.abi, &*bf.decl);
-            ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(bare_fn))
+            tcx.mk_fn(None, tcx.mk_bare_fn(bare_fn))
         }
         ast::TyPolyTraitRef(ref bounds) => {
             conv_ty_poly_trait_ref(this, rscope, ast_ty.span, bounds)
@@ -1603,11 +1603,11 @@ pub fn ast_ty_to_ty<'tcx>(this: &AstConv<'tcx>,
                 Ok(r) => {
                     match r {
                         ConstVal::Int(i) =>
-                            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
-                                        Some(i as usize)),
+                            tcx.mk_array(ast_ty_to_ty(this, rscope, &**ty),
+                                         i as usize),
                         ConstVal::Uint(i) =>
-                            ty::mk_vec(tcx, ast_ty_to_ty(this, rscope, &**ty),
-                                        Some(i as usize)),
+                            tcx.mk_array(ast_ty_to_ty(this, rscope, &**ty),
+                                         i as usize),
                         _ => {
                             span_err!(tcx.sess, ast_ty.span, E0249,
                                       "expected constant integer expression \
@@ -1724,7 +1724,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
                     (Some(self_info.untransformed_self_ty), None)
                 }
                 ty::ByReferenceExplicitSelfCategory(region, mutability) => {
-                    (Some(ty::mk_rptr(this.tcx(),
+                    (Some(this.tcx().mk_ref(
                                       this.tcx().mk_region(region),
                                       ty::mt {
                                         ty: self_info.untransformed_self_ty,
@@ -1733,7 +1733,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
                      Some(region))
                 }
                 ty::ByBoxExplicitSelfCategory => {
-                    (Some(ty::mk_uniq(this.tcx(), self_info.untransformed_self_ty)), None)
+                    (Some(this.tcx().mk_box(self_info.untransformed_self_ty)), None)
                 }
             }
         }
@@ -1779,7 +1779,7 @@ fn ty_of_method_or_bare_fn<'a, 'tcx>(this: &AstConv<'tcx>,
                                                               implied_output_region,
                                                               lifetimes_for_params,
                                                               &**output)),
-        ast::DefaultReturn(..) => ty::FnConverging(ty::mk_nil(this.tcx())),
+        ast::DefaultReturn(..) => ty::FnConverging(this.tcx().mk_nil()),
         ast::NoReturn(..) => ty::FnDiverging
     };
 
@@ -2116,8 +2116,7 @@ pub fn partition_bounds<'a>(tcx: &ty::ctxt,
             ast::TraitTyParamBound(ref b, ast::TraitBoundModifier::None) => {
                 match ::lookup_full_def(tcx, b.trait_ref.path.span, b.trait_ref.ref_id) {
                     def::DefTrait(trait_did) => {
-                        if ty::try_add_builtin_trait(tcx,
-                                                     trait_did,
+                        if tcx.try_add_builtin_trait(trait_did,
                                                      &mut builtin_bounds) {
                             let segments = &b.trait_ref.path.segments;
                             let parameters = &segments[segments.len() - 1].parameters;
diff --git a/src/librustc_typeck/check/_match.rs b/src/librustc_typeck/check/_match.rs
index cf086a32ae5..87f867d7f90 100644
--- a/src/librustc_typeck/check/_match.rs
+++ b/src/librustc_typeck/check/_match.rs
@@ -15,7 +15,7 @@ use middle::pat_util::{PatIdMap, pat_id_map, pat_is_binding};
 use middle::pat_util::pat_is_resolved_const;
 use middle::privacy::{AllPublic, LastMod};
 use middle::subst::Substs;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use check::{check_expr, check_expr_has_type, check_expr_with_expectation};
 use check::{check_expr_coercable_to_type, demand, FnCtxt, Expectation};
 use check::{check_expr_with_lvalue_pref, LvaluePreference};
@@ -59,8 +59,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                     let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
                     if let ty::TyRef(_, mt) = expected_ty.sty {
                         if let ty::TySlice(_) = mt.ty.sty {
-                            pat_ty = ty::mk_slice(tcx, tcx.mk_region(ty::ReStatic),
-                                ty::mt{ ty: tcx.types.u8, mutbl: ast::MutImmutable })
+                            pat_ty = tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
+                                                     tcx.mk_slice(tcx.types.u8))
                         }
                     }
                 }
@@ -90,7 +90,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let rhs_ty = fcx.expr_ty(end);
 
             // Check that both end-points are of numeric or char type.
-            let numeric_or_char = |t| ty::type_is_numeric(t) || ty::type_is_char(t);
+            let numeric_or_char = |ty: Ty| ty.is_numeric() || ty.is_char();
             let lhs_compat = numeric_or_char(lhs_ty);
             let rhs_compat = numeric_or_char(rhs_ty);
 
@@ -147,7 +147,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         }
         ast::PatEnum(..) | ast::PatIdent(..) if pat_is_resolved_const(&tcx.def_map, pat) => {
             let const_did = tcx.def_map.borrow().get(&pat.id).unwrap().def_id();
-            let const_scheme = ty::lookup_item_type(tcx, const_did);
+            let const_scheme = tcx.lookup_item_type(const_did);
             assert!(const_scheme.generics.is_empty());
             let const_ty = pcx.fcx.instantiate_type_scheme(pat.span,
                                                            &Substs::empty(),
@@ -171,7 +171,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                     // and T is the expected type.
                     let region_var = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
                     let mt = ty::mt { ty: expected, mutbl: mutbl };
-                    let region_ty = ty::mk_rptr(tcx, tcx.mk_region(region_var), mt);
+                    let region_ty = tcx.mk_ref(tcx.mk_region(region_var), mt);
 
                     // `x` is assigned a value of type `&M T`, hence `&M T <: typeof(x)` is
                     // required. However, we use equality, which is stronger. See (*) for
@@ -227,8 +227,8 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                     resolve_ty_and_def_ufcs(fcx, path_res, Some(self_ty),
                                             path, pat.span, pat.id) {
                 if check_assoc_item_is_const(pcx, def, pat.span) {
-                    let scheme = ty::lookup_item_type(tcx, def.def_id());
-                    let predicates = ty::lookup_predicates(tcx, def.def_id());
+                    let scheme = tcx.lookup_item_type(def.def_id());
+                    let predicates = tcx.lookup_predicates(def.def_id());
                     instantiate_path(fcx, segments,
                                      scheme, &predicates,
                                      opt_ty, def, pat.span, pat.id);
@@ -246,7 +246,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let element_tys: Vec<_> =
                 (0..elements.len()).map(|_| fcx.infcx().next_ty_var())
                                         .collect();
-            let pat_ty = ty::mk_tup(tcx, element_tys.clone());
+            let pat_ty = tcx.mk_tup(element_tys.clone());
             fcx.write_ty(pat.id, pat_ty);
             demand::eqtype(fcx, pat.span, expected, pat_ty);
             for (element_pat, element_ty) in elements.iter().zip(element_tys) {
@@ -255,7 +255,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         }
         ast::PatBox(ref inner) => {
             let inner_ty = fcx.infcx().next_ty_var();
-            let uniq_ty = ty::mk_uniq(tcx, inner_ty);
+            let uniq_ty = tcx.mk_box(inner_ty);
 
             if check_dereferencable(pcx, pat.span, expected, &**inner) {
                 // Here, `demand::subtype` is good enough, but I don't
@@ -274,7 +274,7 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
 
             let mt = ty::mt { ty: inner_ty, mutbl: mutbl };
             let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
-            let rptr_ty = ty::mk_rptr(tcx, tcx.mk_region(region), mt);
+            let rptr_ty = tcx.mk_ref(tcx.mk_region(region), mt);
 
             if check_dereferencable(pcx, pat.span, expected, &**inner) {
                 // `demand::subtype` would be good enough, but using
@@ -292,19 +292,19 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             let expected_ty = structurally_resolved_type(fcx, pat.span, expected);
             let inner_ty = fcx.infcx().next_ty_var();
             let pat_ty = match expected_ty.sty {
-                ty::TyArray(_, size) => ty::mk_vec(tcx, inner_ty, Some({
+                ty::TyArray(_, size) => tcx.mk_array(inner_ty, {
                     let min_len = before.len() + after.len();
                     match *slice {
                         Some(_) => cmp::max(min_len, size),
                         None => min_len
                     }
-                })),
+                }),
                 _ => {
                     let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
-                    ty::mk_slice(tcx, tcx.mk_region(region), ty::mt {
-                        ty: inner_ty,
-                        mutbl: ty::deref(expected_ty, true).map(|mt| mt.mutbl)
-                                                           .unwrap_or(ast::MutImmutable)
+                    tcx.mk_ref(tcx.mk_region(region), ty::mt {
+                        ty: tcx.mk_slice(inner_ty),
+                        mutbl: expected_ty.builtin_deref(true).map(|mt| mt.mutbl)
+                                                              .unwrap_or(ast::MutImmutable)
                     })
                 }
             };
@@ -321,11 +321,11 @@ pub fn check_pat<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
             }
             if let Some(ref slice) = *slice {
                 let region = fcx.infcx().next_region_var(infer::PatternRegion(pat.span));
-                let mutbl = ty::deref(expected_ty, true)
+                let mutbl = expected_ty.builtin_deref(true)
                     .map_or(ast::MutImmutable, |mt| mt.mutbl);
 
-                let slice_ty = ty::mk_slice(tcx, tcx.mk_region(region), ty::mt {
-                    ty: inner_ty,
+                let slice_ty = tcx.mk_ref(tcx.mk_region(region), ty::mt {
+                    ty: tcx.mk_slice(inner_ty),
                     mutbl: mutbl
                 });
                 check_pat(pcx, &**slice, slice_ty);
@@ -411,7 +411,7 @@ pub fn check_dereferencable<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     let tcx = pcx.fcx.ccx.tcx;
     if pat_is_binding(&tcx.def_map, inner) {
         let expected = fcx.infcx().shallow_resolve(expected);
-        ty::deref(expected, true).map_or(true, |mt| match mt.ty.sty {
+        expected.builtin_deref(true).map_or(true, |mt| match mt.ty.sty {
             ty::TyTrait(_) => {
                 // This is "x = SomeTrait" being reduced from
                 // "let &x = &SomeTrait" or "let box x = Box<SomeTrait>", an error.
@@ -485,7 +485,7 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             // us to give better error messages (pointing to a usually better
             // arm for inconsistent arms or to the whole match when a `()` type
             // is required).
-            Expectation::ExpectHasType(ety) if ety != ty::mk_nil(fcx.tcx()) => {
+            Expectation::ExpectHasType(ety) if ety != fcx.tcx().mk_nil() => {
                 check_expr_coercable_to_type(fcx, &*arm.body, ety);
                 ety
             }
@@ -499,7 +499,7 @@ pub fn check_match<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             check_expr_has_type(fcx, &**e, tcx.types.bool);
         }
 
-        if ty::type_is_error(result_ty) || ty::type_is_error(bty) {
+        if result_ty.references_error() || bty.references_error() {
             tcx.types.err
         } else {
             let (origin, expected, found) = match match_src {
@@ -555,7 +555,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
             return;
         },
         _ => {
-            let def_type = ty::lookup_item_type(tcx, def.def_id());
+            let def_type = tcx.lookup_item_type(def.def_id());
             match def_type.ty.sty {
                 ty::TyStruct(struct_def_id, _) =>
                     (struct_def_id, struct_def_id),
@@ -579,8 +579,8 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
 
     instantiate_path(pcx.fcx,
                      &path.segments,
-                     ty::lookup_item_type(tcx, enum_def_id),
-                     &ty::lookup_predicates(tcx, enum_def_id),
+                     tcx.lookup_item_type(enum_def_id),
+                     &tcx.lookup_predicates(enum_def_id),
                      None,
                      def,
                      pat.span,
@@ -595,7 +595,7 @@ pub fn check_pat_struct<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>, pat: &'tcx ast::Pat,
         .map(|substs| substs.substs.clone())
         .unwrap_or_else(|| Substs::empty());
 
-    let struct_fields = ty::struct_fields(tcx, variant_def_id, &item_substs);
+    let struct_fields = tcx.struct_fields(variant_def_id, &item_substs);
     check_struct_pat_fields(pcx, pat.span, fields, &struct_fields,
                             variant_def_id, etc);
 }
@@ -631,10 +631,10 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
     let enum_def = def.variant_def_ids()
         .map_or_else(|| def.def_id(), |(enum_def, _)| enum_def);
 
-    let ctor_scheme = ty::lookup_item_type(tcx, enum_def);
-    let ctor_predicates = ty::lookup_predicates(tcx, enum_def);
-    let path_scheme = if ty::is_fn_ty(ctor_scheme.ty) {
-        let fn_ret = ty::no_late_bound_regions(tcx, &ty::ty_fn_ret(ctor_scheme.ty)).unwrap();
+    let ctor_scheme = tcx.lookup_item_type(enum_def);
+    let ctor_predicates = tcx.lookup_predicates(enum_def);
+    let path_scheme = if ctor_scheme.ty.is_fn() {
+        let fn_ret = tcx.no_late_bound_regions(&ctor_scheme.ty.fn_ret()).unwrap();
         ty::TypeScheme {
             ty: fn_ret.unwrap(),
             generics: ctor_scheme.generics,
@@ -664,14 +664,14 @@ pub fn check_pat_enum<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
         ty::TyEnum(enum_def_id, expected_substs)
             if def == def::DefVariant(enum_def_id, def.def_id(), false) =>
         {
-            let variant = ty::enum_variant_with_id(tcx, enum_def_id, def.def_id());
+            let variant = tcx.enum_variant_with_id(enum_def_id, def.def_id());
             (variant.args.iter()
                          .map(|t| fcx.instantiate_type_scheme(pat.span, expected_substs, t))
                          .collect(),
              "variant")
         }
         ty::TyStruct(struct_def_id, expected_substs) => {
-            let struct_fields = ty::struct_fields(tcx, struct_def_id, expected_substs);
+            let struct_fields = tcx.struct_fields(struct_def_id, expected_substs);
             (struct_fields.iter()
                           .map(|field| fcx.instantiate_type_scheme(pat.span,
                                                                    expected_substs,
@@ -761,7 +761,7 @@ pub fn check_struct_pat_fields<'a, 'tcx>(pcx: &pat_ctxt<'a, 'tcx>,
                     .unwrap_or_else(|| {
                         span_err!(tcx.sess, span, E0026,
                             "struct `{}` does not have a field named `{}`",
-                            ty::item_path_str(tcx, struct_id),
+                            tcx.item_path_str(struct_id),
                             token::get_ident(field.ident));
                         tcx.types.err
                     })
diff --git a/src/librustc_typeck/check/assoc.rs b/src/librustc_typeck/check/assoc.rs
index df9fe6b002e..4eafbaaf794 100644
--- a/src/librustc_typeck/check/assoc.rs
+++ b/src/librustc_typeck/check/assoc.rs
@@ -11,7 +11,7 @@
 use middle::infer::InferCtxt;
 use middle::traits::{self, FulfillmentContext, Normalized, MiscObligation,
                      SelectionContext, ObligationCause};
-use middle::ty::{self, HasProjectionTypes};
+use middle::ty::{self, HasTypeFlags};
 use middle::ty_fold::TypeFoldable;
 use syntax::ast;
 use syntax::codemap::Span;
@@ -23,7 +23,7 @@ pub fn normalize_associated_types_in<'a,'tcx,T>(infcx: &InferCtxt<'a,'tcx>,
                                                 body_id: ast::NodeId,
                                                 value: &T)
                                                 -> T
-    where T : TypeFoldable<'tcx> + HasProjectionTypes
+    where T : TypeFoldable<'tcx> + HasTypeFlags
 {
     debug!("normalize_associated_types_in(value={:?})", value);
     let mut selcx = SelectionContext::new(infcx, typer);
diff --git a/src/librustc_typeck/check/callee.rs b/src/librustc_typeck/check/callee.rs
index e7271d2fa88..7109e45b552 100644
--- a/src/librustc_typeck/check/callee.rs
+++ b/src/librustc_typeck/check/callee.rs
@@ -358,9 +358,8 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
                 // can't because of the annoying need for a TypeTrace.
                 // (This always bites me, should find a way to
                 // refactor it.)
-                let method_sig =
-                    ty::no_late_bound_regions(fcx.tcx(),
-                                              ty::ty_fn_sig(method_callee.ty)).unwrap();
+                let method_sig = fcx.tcx().no_late_bound_regions(method_callee.ty.fn_sig())
+                                          .unwrap();
 
                 debug!("attempt_resolution: method_callee={:?}",
                        method_callee);
@@ -371,7 +370,7 @@ impl<'tcx> DeferredCallResolution<'tcx> for CallResolution<'tcx> {
                     demand::eqtype(fcx, self.call_expr.span, self_arg_ty, method_arg_ty);
                 }
 
-                let nilty = ty::mk_nil(fcx.tcx());
+                let nilty = fcx.tcx().mk_nil();
                 demand::eqtype(fcx,
                                self.call_expr.span,
                                method_sig.output.unwrap_or(nilty),
diff --git a/src/librustc_typeck/check/cast.rs b/src/librustc_typeck/check/cast.rs
index c46a033c13f..49b47da5177 100644
--- a/src/librustc_typeck/check/cast.rs
+++ b/src/librustc_typeck/check/cast.rs
@@ -45,8 +45,7 @@ use super::structurally_resolved_type;
 
 use lint;
 use middle::cast::{CastKind, CastTy};
-use middle::ty;
-use middle::ty::Ty;
+use middle::ty::{self, Ty, HasTypeFlags};
 use syntax::ast;
 use syntax::ast::UintTy::{TyU8};
 use syntax::codemap::Span;
@@ -81,7 +80,7 @@ fn unsize_kind<'a,'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         ty::TySlice(_) | ty::TyStr => Some(UnsizeKind::Length),
         ty::TyTrait(ref tty) => Some(UnsizeKind::Vtable(tty.principal_def_id())),
         ty::TyStruct(did, substs) => {
-            match ty::struct_fields(fcx.tcx(), did, substs).pop() {
+            match fcx.tcx().struct_fields(did, substs).pop() {
                 None => None,
                 Some(f) => unsize_kind(fcx, f.mt.ty)
             }
@@ -170,7 +169,7 @@ impl<'tcx> CastCheck<'tcx> {
     fn trivial_cast_lint<'a>(&self, fcx: &FnCtxt<'a, 'tcx>) {
         let t_cast = self.cast_ty;
         let t_expr = self.expr_ty;
-        if ty::type_is_numeric(t_cast) && ty::type_is_numeric(t_expr) {
+        if t_cast.is_numeric() && t_expr.is_numeric() {
             fcx.tcx().sess.add_lint(lint::builtin::TRIVIAL_NUMERIC_CASTS,
                                     self.expr.id,
                                     self.span,
@@ -199,7 +198,7 @@ impl<'tcx> CastCheck<'tcx> {
         debug!("check_cast({}, {:?} as {:?})", self.expr.id, self.expr_ty,
                self.cast_ty);
 
-        if ty::type_is_error(self.expr_ty) || ty::type_is_error(self.cast_ty) {
+        if self.expr_ty.references_error() || self.cast_ty.references_error() {
             // No sense in giving duplicate error messages
         } else if self.try_coercion_cast(fcx) {
             self.trivial_cast_lint(fcx);
diff --git a/src/librustc_typeck/check/closure.rs b/src/librustc_typeck/check/closure.rs
index 10b2459b220..d431c0fda98 100644
--- a/src/librustc_typeck/check/closure.rs
+++ b/src/librustc_typeck/check/closure.rs
@@ -60,17 +60,13 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         abi::RustCall,
         expected_sig);
 
-    let closure_type = ty::mk_closure(fcx.ccx.tcx,
-                                      expr_def_id,
-                                      fcx.ccx.tcx.mk_substs(
-                                        fcx.inh.param_env.free_substs.clone()));
+    let closure_type = fcx.ccx.tcx.mk_closure(expr_def_id,
+        fcx.ccx.tcx.mk_substs(fcx.inh.param_env.free_substs.clone()));
 
     fcx.write_ty(expr.id, closure_type);
 
-    let fn_sig =
-        ty::liberate_late_bound_regions(fcx.tcx(),
-                                        region::DestructionScopeData::new(body.id),
-                                        &fn_ty.sig);
+    let fn_sig = fcx.tcx().liberate_late_bound_regions(
+        region::DestructionScopeData::new(body.id), &fn_ty.sig);
 
     check_fn(fcx.ccx,
              ast::Unsafety::Normal,
@@ -83,7 +79,7 @@ fn check_closure<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
 
     // Tuple up the arguments and insert the resulting function type into
     // the `closures` table.
-    fn_ty.sig.0.inputs = vec![ty::mk_tup(fcx.tcx(), fn_ty.sig.0.inputs)];
+    fn_ty.sig.0.inputs = vec![fcx.tcx().mk_tup(fn_ty.sig.0.inputs)];
 
     debug!("closure for {:?} --> sig={:?} opt_kind={:?}",
            expr_def_id,
diff --git a/src/librustc_typeck/check/coercion.rs b/src/librustc_typeck/check/coercion.rs
index 785202de921..73b9a16d1eb 100644
--- a/src/librustc_typeck/check/coercion.rs
+++ b/src/librustc_typeck/check/coercion.rs
@@ -201,8 +201,8 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
                 // &T to autoref to &&T.
                 return None;
             }
-            let ty = ty::mk_rptr(self.tcx(), r_borrow,
-                                 mt {ty: inner_ty, mutbl: mutbl_b});
+            let ty = self.tcx().mk_ref(r_borrow,
+                                        mt {ty: inner_ty, mutbl: mutbl_b});
             if let Err(err) = self.subtype(ty, b) {
                 if first_error.is_none() {
                     first_error = Some(err);
@@ -271,7 +271,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
             }
             _ => (source, None)
         };
-        let source = ty::adjust_ty_for_autoref(self.tcx(), source, reborrow);
+        let source = source.adjust_for_autoref(self.tcx(), reborrow);
 
         let mut selcx = traits::SelectionContext::new(self.fcx.infcx(), self.fcx);
 
@@ -384,7 +384,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
 
             match b.sty {
                 ty::TyBareFn(None, _) => {
-                    let a_fn_pointer = ty::mk_bare_fn(self.tcx(), None, fn_ty_a);
+                    let a_fn_pointer = self.tcx().mk_fn(None, fn_ty_a);
                     try!(self.subtype(a_fn_pointer, b));
                     Ok(Some(ty::AdjustReifyFnPointer))
                 }
@@ -411,7 +411,7 @@ impl<'f, 'tcx> Coerce<'f, 'tcx> {
         };
 
         // Check that the types which they point at are compatible.
-        let a_unsafe = ty::mk_ptr(self.tcx(), ty::mt{ mutbl: mutbl_b, ty: mt_a.ty });
+        let a_unsafe = self.tcx().mk_ptr(ty::mt{ mutbl: mutbl_b, ty: mt_a.ty });
         try!(self.subtype(a_unsafe, b));
         try!(coerce_mutbls(mt_a.mutbl, mutbl_b));
 
diff --git a/src/librustc_typeck/check/compare_method.rs b/src/librustc_typeck/check/compare_method.rs
index 7cd5e4548ec..349d1a8bb65 100644
--- a/src/librustc_typeck/check/compare_method.rs
+++ b/src/librustc_typeck/check/compare_method.rs
@@ -100,7 +100,7 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
             token::get_name(trait_m.name),
             impl_m.fty.sig.0.inputs.len(),
             if impl_m.fty.sig.0.inputs.len() == 1 {""} else {"s"},
-            ty::item_path_str(tcx, trait_m.def_id),
+            tcx.item_path_str(trait_m.def_id),
             trait_m.fty.sig.0.inputs.len());
         return;
     }
@@ -275,9 +275,9 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
     // type.
 
     // Compute skolemized form of impl and trait method tys.
-    let impl_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(impl_m.fty.clone()));
+    let impl_fty = tcx.mk_fn(None, tcx.mk_bare_fn(impl_m.fty.clone()));
     let impl_fty = impl_fty.subst(tcx, impl_to_skol_substs);
-    let trait_fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(trait_m.fty.clone()));
+    let trait_fty = tcx.mk_fn(None, tcx.mk_bare_fn(trait_m.fty.clone()));
     let trait_fty = trait_fty.subst(tcx, &trait_to_skol_substs);
 
     let err = infcx.commit_if_ok(|snapshot| {
@@ -296,12 +296,11 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                  impl_m_span,
                                                  impl_m_body_id,
                                                  &impl_sig);
-        let impl_fty =
-            ty::mk_bare_fn(tcx,
-                           None,
-                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: impl_m.fty.unsafety,
-                                                         abi: impl_m.fty.abi,
-                                                         sig: ty::Binder(impl_sig) }));
+        let impl_fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
+            unsafety: impl_m.fty.unsafety,
+            abi: impl_m.fty.abi,
+            sig: ty::Binder(impl_sig)
+        }));
         debug!("compare_impl_method: impl_fty={:?}",
                impl_fty);
 
@@ -316,12 +315,11 @@ pub fn compare_impl_method<'tcx>(tcx: &ty::ctxt<'tcx>,
                                                  impl_m_span,
                                                  impl_m_body_id,
                                                  &trait_sig);
-        let trait_fty =
-            ty::mk_bare_fn(tcx,
-                           None,
-                           tcx.mk_bare_fn(ty::BareFnTy { unsafety: trait_m.fty.unsafety,
-                                                         abi: trait_m.fty.abi,
-                                                         sig: ty::Binder(trait_sig) }));
+        let trait_fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
+            unsafety: trait_m.fty.unsafety,
+            abi: trait_m.fty.abi,
+            sig: ty::Binder(trait_sig)
+        }));
 
         debug!("compare_impl_method: trait_fty={:?}",
                trait_fty);
diff --git a/src/librustc_typeck/check/dropck.rs b/src/librustc_typeck/check/dropck.rs
index fb17f41d88d..a48cffb4472 100644
--- a/src/librustc_typeck/check/dropck.rs
+++ b/src/librustc_typeck/check/dropck.rs
@@ -37,8 +37,8 @@ use syntax::codemap::{self, Span};
 ///
 pub fn check_drop_impl(tcx: &ty::ctxt, drop_impl_did: ast::DefId) -> Result<(), ()> {
     let ty::TypeScheme { generics: ref dtor_generics,
-                         ty: dtor_self_type } = ty::lookup_item_type(tcx, drop_impl_did);
-    let dtor_predicates = ty::lookup_predicates(tcx, drop_impl_did);
+                         ty: dtor_self_type } = tcx.lookup_item_type(drop_impl_did);
+    let dtor_predicates = tcx.lookup_predicates(drop_impl_did);
     match dtor_self_type.sty {
         ty::TyEnum(self_type_did, self_to_impl_substs) |
         ty::TyStruct(self_type_did, self_to_impl_substs) |
@@ -91,7 +91,7 @@ fn ensure_drop_params_and_item_params_correspond<'tcx>(
 
     let ty::TypeScheme { generics: ref named_type_generics,
                          ty: named_type } =
-        ty::lookup_item_type(tcx, self_type_did);
+        tcx.lookup_item_type(self_type_did);
 
     let infcx = infer::new_infer_ctxt(tcx);
     infcx.commit_if_ok(|snapshot| {
@@ -179,7 +179,7 @@ fn ensure_drop_predicates_are_implied_by_item_defn<'tcx>(
 
     // We can assume the predicates attached to struct/enum definition
     // hold.
-    let generic_assumptions = ty::lookup_predicates(tcx, self_type_did);
+    let generic_assumptions = tcx.lookup_predicates(self_type_did);
 
     let assumptions_in_impl_context = generic_assumptions.instantiate(tcx, &self_to_impl_substs);
     assert!(assumptions_in_impl_context.predicates.is_empty_in(subst::SelfSpace));
@@ -288,7 +288,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
                         rcx.tcx().sess,
                         span,
                         "overflowed on enum {} variant {} argument {} type: {}",
-                        ty::item_path_str(tcx, def_id),
+                        tcx.item_path_str(def_id),
                         variant,
                         arg_index,
                         detected_on_typ);
@@ -298,7 +298,7 @@ pub fn check_safety_of_destructor_if_necessary<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>
                         rcx.tcx().sess,
                         span,
                         "overflowed on struct {} field {} type: {}",
-                        ty::item_path_str(tcx, def_id),
+                        tcx.item_path_str(def_id),
                         field,
                         detected_on_typ);
                 }
@@ -365,7 +365,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
         let (typ, xref_depth) = match typ.sty {
             ty::TyStruct(struct_did, substs) => {
                 if opt_phantom_data_def_id == Some(struct_did) {
-                    let item_type = ty::lookup_item_type(rcx.tcx(), struct_did);
+                    let item_type = rcx.tcx().lookup_item_type(struct_did);
                     let tp_def = item_type.generics.types
                         .opt_get(subst::TypeSpace, 0).unwrap();
                     let new_typ = substs.type_for_def(tp_def);
@@ -471,13 +471,11 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
                     walker.skip_current_subtree();
 
                     let fields =
-                        ty::lookup_struct_fields(rcx.tcx(), struct_did);
+                        rcx.tcx().lookup_struct_fields(struct_did);
                     for field in &fields {
-                        let field_type =
-                            ty::lookup_field_type(rcx.tcx(),
-                                                  struct_did,
-                                                  field.id,
-                                                  substs);
+                        let field_type = rcx.tcx().lookup_field_type(struct_did,
+                                                                     field.id,
+                                                                     substs);
                         try!(iterate_over_potentially_unsafe_regions_in_type(
                             rcx,
                             breadcrumbs,
@@ -501,9 +499,7 @@ fn iterate_over_potentially_unsafe_regions_in_type<'a, 'tcx>(
                     walker.skip_current_subtree();
 
                     let all_variant_info =
-                        ty::substd_enum_variants(rcx.tcx(),
-                                                 enum_did,
-                                                 substs);
+                        rcx.tcx().substd_enum_variants(enum_did, substs);
                     for variant_info in &all_variant_info {
                         for (i, arg_type) in variant_info.args.iter().enumerate() {
                             try!(iterate_over_potentially_unsafe_regions_in_type(
@@ -591,13 +587,13 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
             }
         }
         DtorKind::KnownDropMethod(dtor_method_did) => {
-            let impl_did = ty::impl_of_method(tcx, dtor_method_did)
+            let impl_did = tcx.impl_of_method(dtor_method_did)
                 .unwrap_or_else(|| {
                     tcx.sess.span_bug(
                         span, "no Drop impl found for drop method")
                 });
 
-            let dtor_typescheme = ty::lookup_item_type(tcx, impl_did);
+            let dtor_typescheme = tcx.lookup_item_type(impl_did);
             let dtor_generics = dtor_typescheme.generics;
 
             let mut has_pred_of_interest = false;
@@ -609,7 +605,7 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
                     continue;
                 }
 
-                for pred in ty::lookup_predicates(tcx, item_def_id).predicates {
+                for pred in tcx.lookup_predicates(item_def_id).predicates {
                     let result = match pred {
                         ty::Predicate::Equate(..) |
                         ty::Predicate::RegionOutlives(..) |
@@ -623,7 +619,7 @@ fn has_dtor_of_interest<'tcx>(tcx: &ty::ctxt<'tcx>,
 
                         ty::Predicate::Trait(ty::Binder(ref t_pred)) => {
                             let def_id = t_pred.trait_ref.def_id;
-                            if ty::trait_items(tcx, def_id).len() != 0 {
+                            if tcx.trait_items(def_id).len() != 0 {
                                 // If trait has items, assume it adds
                                 // capability to access borrowed data.
                                 true
diff --git a/src/librustc_typeck/check/method/confirm.rs b/src/librustc_typeck/check/method/confirm.rs
index fd93a2493db..5f7a78ec611 100644
--- a/src/librustc_typeck/check/method/confirm.rs
+++ b/src/librustc_typeck/check/method/confirm.rs
@@ -108,7 +108,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
 
         // Create the final `MethodCallee`.
         let method_ty = pick.item.as_opt_method().unwrap();
-        let fty = ty::mk_bare_fn(self.tcx(), None, self.tcx().mk_bare_fn(ty::BareFnTy {
+        let fty = self.tcx().mk_fn(None, self.tcx().mk_bare_fn(ty::BareFnTy {
             sig: ty::Binder(method_sig),
             unsafety: method_ty.fty.unsafety,
             abi: method_ty.fty.abi.clone(),
@@ -139,7 +139,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             let region = self.infcx().next_region_var(infer::Autoref(self.span));
             let autoref = ty::AutoPtr(self.tcx().mk_region(region), mutbl);
             (Some(autoref), pick.unsize.map(|target| {
-                ty::adjust_ty_for_autoref(self.tcx(), target, Some(autoref))
+                target.adjust_for_autoref(self.tcx(), Some(autoref))
             }))
         } else {
             // No unsizing should be performed without autoref (at
@@ -179,7 +179,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
         if let Some(target) = unsize {
             target
         } else {
-            ty::adjust_ty_for_autoref(self.tcx(), autoderefd_ty, autoref)
+            autoderefd_ty.adjust_for_autoref(self.tcx(), autoref)
         }
     }
 
@@ -199,7 +199,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
     {
         match pick.kind {
             probe::InherentImplPick(impl_def_id) => {
-                assert!(ty::impl_trait_ref(self.tcx(), impl_def_id).is_none(),
+                assert!(self.tcx().impl_trait_ref(impl_def_id).is_none(),
                         "impl {:?} is not an inherent impl", impl_def_id);
                 let impl_polytype = check::impl_self_ty(self.fcx, self.span, impl_def_id);
 
@@ -254,7 +254,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                     self.fcx.instantiate_type_scheme(
                         self.span,
                         &impl_polytype.substs,
-                        &ty::impl_trait_ref(self.tcx(), impl_def_id).unwrap());
+                        &self.tcx().impl_trait_ref(impl_def_id).unwrap());
                 let origin = MethodTypeParam(MethodParam { trait_ref: impl_trait_ref.clone(),
                                                            method_num: method_num,
                                                            impl_def_id: Some(impl_def_id) });
@@ -262,7 +262,7 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
             }
 
             probe::TraitPick(trait_def_id, method_num) => {
-                let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
+                let trait_def = self.tcx().lookup_trait_def(trait_def_id);
 
                 // Make a trait reference `$0 : Trait<$1...$n>`
                 // consisting entirely of type variables. Later on in
@@ -536,8 +536,8 @@ impl<'a,'tcx> ConfirmContext<'a,'tcx> {
                                 }
                                 Some(ty::AutoPtr(_, _)) => {
                                     (adr.autoderefs, adr.unsize.map(|target| {
-                                        ty::deref(target, false)
-                                            .expect("fixup: AutoPtr is not &T").ty
+                                        target.builtin_deref(false)
+                                              .expect("fixup: AutoPtr is not &T").ty
                                     }))
                                 }
                                 Some(_) => {
diff --git a/src/librustc_typeck/check/method/mod.rs b/src/librustc_typeck/check/method/mod.rs
index 30fb830495e..0f8048f27a0 100644
--- a/src/librustc_typeck/check/method/mod.rs
+++ b/src/librustc_typeck/check/method/mod.rs
@@ -167,7 +167,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
            m_name,
            trait_def_id);
 
-    let trait_def = ty::lookup_trait_def(fcx.tcx(), trait_def_id);
+    let trait_def = fcx.tcx().lookup_trait_def(trait_def_id);
 
     let expected_number_of_input_types = trait_def.generics.types.len(subst::TypeSpace);
     let input_types = match opt_input_types {
@@ -224,7 +224,7 @@ pub fn lookup_in_trait_adjusted<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                                                        &method_ty.fty.sig).0;
     let fn_sig = fcx.instantiate_type_scheme(span, trait_ref.substs, &fn_sig);
     let transformed_self_ty = fn_sig.inputs[0];
-    let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
+    let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
         sig: ty::Binder(fn_sig),
         unsafety: method_ty.fty.unsafety,
         abi: method_ty.fty.abi.clone(),
@@ -359,7 +359,7 @@ fn trait_item<'tcx>(tcx: &ty::ctxt<'tcx>,
                     item_name: ast::Name)
                     -> Option<(usize, ty::ImplOrTraitItem<'tcx>)>
 {
-    let trait_items = ty::trait_items(tcx, trait_def_id);
+    let trait_items = tcx.trait_items(trait_def_id);
     trait_items
         .iter()
         .enumerate()
@@ -376,6 +376,6 @@ fn impl_item<'tcx>(tcx: &ty::ctxt<'tcx>,
     let impl_items = impl_items.get(&impl_def_id).unwrap();
     impl_items
         .iter()
-        .map(|&did| ty::impl_or_trait_item(tcx, did.def_id()))
+        .map(|&did| tcx.impl_or_trait_item(did.def_id()))
         .find(|m| m.name() == item_name)
 }
diff --git a/src/librustc_typeck/check/method/probe.rs b/src/librustc_typeck/check/method/probe.rs
index 46bffa8ccab..8026fce69ec 100644
--- a/src/librustc_typeck/check/method/probe.rs
+++ b/src/librustc_typeck/check/method/probe.rs
@@ -21,6 +21,7 @@ use middle::subst;
 use middle::subst::Subst;
 use middle::traits;
 use middle::ty::{self, RegionEscape, Ty, ToPolyTraitRef, TraitRef};
+use middle::ty::HasTypeFlags;
 use middle::ty_fold::TypeFoldable;
 use middle::infer;
 use middle::infer::InferCtxt;
@@ -217,9 +218,8 @@ fn create_steps<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
     match final_ty.sty {
         ty::TyArray(elem_ty, _) => {
-            let slice_ty = ty::mk_vec(fcx.tcx(), elem_ty, None);
             steps.push(CandidateStep {
-                self_ty: slice_ty,
+                self_ty: fcx.tcx().mk_slice(elem_ty),
                 autoderefs: dereferences,
                 unsize: true
             });
@@ -377,7 +377,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
     fn assemble_inherent_impl_for_primitive(&mut self, lang_def_id: Option<ast::DefId>) {
         if let Some(impl_def_id) = lang_def_id {
-            ty::populate_implementations_for_primitive_if_necessary(self.tcx(), impl_def_id);
+            self.tcx().populate_implementations_for_primitive_if_necessary(impl_def_id);
 
             self.assemble_inherent_impl_probe(impl_def_id);
         }
@@ -386,7 +386,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn assemble_inherent_impl_candidates_for_type(&mut self, def_id: ast::DefId) {
         // Read the inherent implementation candidates for this type from the
         // metadata if necessary.
-        ty::populate_inherent_implementations_for_type_if_necessary(self.tcx(), def_id);
+        self.tcx().populate_inherent_implementations_for_type_if_necessary(def_id);
 
         if let Some(impl_infos) = self.tcx().inherent_impls.borrow().get(&def_id) {
             for &impl_def_id in impl_infos.iter() {
@@ -528,7 +528,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             // artifacts. This means it is safe to put into the
             // `WhereClauseCandidate` and (eventually) into the
             // `WhereClausePick`.
-            assert!(trait_ref.substs.types.iter().all(|&t| !ty::type_needs_infer(t)));
+            assert!(!trait_ref.substs.types.needs_infer());
 
             this.inherent_candidates.push(Candidate {
                 xform_self_ty: xform_self_ty,
@@ -606,7 +606,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
         // Check whether `trait_def_id` defines a method with suitable name:
         let trait_items =
-            ty::trait_items(self.tcx(), trait_def_id);
+            self.tcx().trait_items(trait_def_id);
         let matching_index =
             trait_items.iter()
                        .position(|item| item.name() == self.item_name);
@@ -647,7 +647,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                                                      item: ty::ImplOrTraitItem<'tcx>,
                                                      item_index: usize)
     {
-        let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
+        let trait_def = self.tcx().lookup_trait_def(trait_def_id);
 
         // FIXME(arielb1): can we use for_each_relevant_impl here?
         trait_def.for_each_impl(self.tcx(), |impl_def_id| {
@@ -665,7 +665,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             debug!("impl_substs={:?}", impl_substs);
 
             let impl_trait_ref =
-                ty::impl_trait_ref(self.tcx(), impl_def_id)
+                self.tcx().impl_trait_ref(impl_def_id)
                 .unwrap() // we know this is a trait impl
                 .subst(self.tcx(), &impl_substs);
 
@@ -705,7 +705,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             None => { return true; }
         };
 
-        let impl_type = ty::lookup_item_type(self.tcx(), impl_def_id);
+        let impl_type = self.tcx().lookup_item_type(impl_def_id);
         let impl_simplified_type =
             match fast_reject::simplify_type(self.tcx(), impl_type.ty, false) {
                 Some(simplified_type) => simplified_type,
@@ -759,7 +759,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             // for the purposes of our method lookup, we only take
             // receiver type into account, so we can just substitute
             // fresh types here to use during substitution and subtyping.
-            let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
+            let trait_def = self.tcx().lookup_trait_def(trait_def_id);
             let substs = self.infcx().fresh_substs_for_trait(self.span,
                                                              &trait_def.generics,
                                                              step.self_ty);
@@ -802,8 +802,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
             debug!("assemble_projection_candidates: projection_trait_ref={:?}",
                    projection_trait_ref);
 
-            let trait_predicates = ty::lookup_predicates(self.tcx(),
-                                                         projection_trait_ref.def_id);
+            let trait_predicates = self.tcx().lookup_predicates(projection_trait_ref.def_id);
             let bounds = trait_predicates.instantiate(self.tcx(), projection_trait_ref.substs);
             let predicates = bounds.predicates.into_vec();
             debug!("assemble_projection_candidates: predicates={:?}",
@@ -894,7 +893,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                 match source {
                     TraitSource(id) => id,
                     ImplSource(impl_id) => {
-                        match ty::trait_id_of_impl(tcx, impl_id) {
+                        match tcx.trait_id_of_impl(impl_id) {
                             Some(id) => id,
                             None =>
                                 tcx.sess.span_bug(span,
@@ -928,7 +927,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn pick_step(&mut self, step: &CandidateStep<'tcx>) -> Option<PickResult<'tcx>> {
         debug!("pick_step: step={:?}", step);
 
-        if ty::type_is_error(step.self_ty) {
+        if step.self_ty.references_error() {
             return None;
         }
 
@@ -983,7 +982,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
 
         // Search through mutabilities in order to find one where pick works:
         [ast::MutImmutable, ast::MutMutable].iter().filter_map(|&m| {
-            let autoref_ty = ty::mk_rptr(tcx, region, ty::mt {
+            let autoref_ty = tcx.mk_ref(region, ty::mt {
                 ty: step.self_ty,
                 mutbl: m
             });
@@ -1081,7 +1080,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                     let cause = traits::ObligationCause::misc(self.span, self.fcx.body_id);
 
                     // Check whether the impl imposes obligations we have to worry about.
-                    let impl_bounds = ty::lookup_predicates(self.tcx(), impl_def_id);
+                    let impl_bounds = self.tcx().lookup_predicates(impl_def_id);
                     let impl_bounds = impl_bounds.instantiate(self.tcx(), substs);
                     let traits::Normalized { value: impl_bounds,
                                              obligations: norm_obligations } =
@@ -1266,7 +1265,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
                           impl_def_id: ast::DefId)
                           -> (Ty<'tcx>, subst::Substs<'tcx>)
     {
-        let impl_pty = ty::lookup_item_type(self.tcx(), impl_def_id);
+        let impl_pty = self.tcx().lookup_item_type(impl_def_id);
 
         let type_vars =
             impl_pty.generics.types.map(
@@ -1301,7 +1300,7 @@ impl<'a,'tcx> ProbeContext<'a,'tcx> {
     fn erase_late_bound_regions<T>(&self, value: &ty::Binder<T>) -> T
         where T : TypeFoldable<'tcx>
     {
-        ty::erase_late_bound_regions(self.tcx(), value)
+        self.tcx().erase_late_bound_regions(value)
     }
 }
 
@@ -1314,7 +1313,7 @@ fn impl_item<'tcx>(tcx: &ty::ctxt<'tcx>,
     let impl_items = impl_items.get(&impl_def_id).unwrap();
     impl_items
         .iter()
-        .map(|&did| ty::impl_or_trait_item(tcx, did.def_id()))
+        .map(|&did| tcx.impl_or_trait_item(did.def_id()))
         .find(|item| item.name() == item_name)
 }
 
@@ -1325,7 +1324,7 @@ fn trait_item<'tcx>(tcx: &ty::ctxt<'tcx>,
                     item_name: ast::Name)
                     -> Option<(usize, ty::ImplOrTraitItem<'tcx>)>
 {
-    let trait_items = ty::trait_items(tcx, trait_def_id);
+    let trait_items = tcx.trait_items(trait_def_id);
     debug!("trait_method; items: {:?}", trait_items);
     trait_items
         .iter()
@@ -1357,7 +1356,7 @@ impl<'tcx> Candidate<'tcx> {
                     // inference variables or other artifacts. This
                     // means they are safe to put into the
                     // `WhereClausePick`.
-                    assert!(trait_ref.substs().types.iter().all(|&t| !ty::type_needs_infer(t)));
+                    assert!(!trait_ref.substs().types.needs_infer());
 
                     WhereClausePick((*trait_ref).clone(), index)
                 }
diff --git a/src/librustc_typeck/check/method/suggest.rs b/src/librustc_typeck/check/method/suggest.rs
index a1d1ddff45a..b193ddcb213 100644
--- a/src/librustc_typeck/check/method/suggest.rs
+++ b/src/librustc_typeck/check/method/suggest.rs
@@ -15,7 +15,7 @@ use CrateCtxt;
 
 use astconv::AstConv;
 use check::{self, FnCtxt};
-use middle::ty::{self, Ty, ToPolyTraitRef, ToPredicate};
+use middle::ty::{self, Ty, ToPolyTraitRef, ToPredicate, HasTypeFlags};
 use middle::def;
 use middle::lang_items::FnOnceTraitLangItem;
 use middle::subst::Substs;
@@ -40,7 +40,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               error: MethodError<'tcx>)
 {
     // avoid suggestions when we don't know what's going on.
-    if ty::type_is_error(rcvr_ty) {
+    if rcvr_ty.references_error() {
         return
     }
 
@@ -66,7 +66,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
             // If the item has the name of a field, give a help note
             if let (&ty::TyStruct(did, substs), Some(expr)) = (&rcvr_ty.sty, rcvr_expr) {
-                let fields = ty::lookup_struct_fields(cx, did);
+                let fields = cx.lookup_struct_fields(did);
 
                 if let Some(field) = fields.iter().find(|f| f.name == item_name) {
                     let expr_string = match cx.sess.codemap().span_to_snippet(expr.span) {
@@ -89,7 +89,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     };
 
                     // Determine if the field can be used as a function in some way
-                    let field_ty = ty::lookup_field_type(cx, did, field.id, substs);
+                    let field_ty = cx.lookup_field_type(did, field.id, substs);
                     if let Ok(fn_once_trait_did) = cx.lang_items.require(FnOnceTraitLangItem) {
                         let infcx = fcx.infcx();
                         infcx.probe(|_| {
@@ -159,7 +159,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                invoked on this closure as we have not yet inferred what \
                                kind of closure it is",
                                item_name,
-                               ty::item_path_str(fcx.tcx(), trait_def_id));
+                               fcx.tcx().item_path_str(trait_def_id));
             let msg = if let Some(callee) = rcvr_expr {
                 format!("{}; use overloaded call notation instead (e.g., `{}()`)",
                         msg, pprust::expr_to_string(callee))
@@ -188,11 +188,12 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
                     let impl_ty = check::impl_self_ty(fcx, span, impl_did).ty;
 
-                    let insertion = match ty::impl_trait_ref(fcx.tcx(), impl_did) {
+                    let insertion = match fcx.tcx().impl_trait_ref(impl_did) {
                         None => format!(""),
-                        Some(trait_ref) => format!(" of the trait `{}`",
-                                                   ty::item_path_str(fcx.tcx(),
-                                                                     trait_ref.def_id)),
+                        Some(trait_ref) => {
+                            format!(" of the trait `{}`",
+                                    fcx.tcx().item_path_str(trait_ref.def_id))
+                        }
                     };
 
                     span_note!(fcx.sess(), item_span,
@@ -207,7 +208,7 @@ pub fn report_error<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     span_note!(fcx.sess(), item_span,
                                "candidate #{} is defined in the trait `{}`",
                                idx + 1,
-                               ty::item_path_str(fcx.tcx(), trait_did));
+                               fcx.tcx().item_path_str(trait_did));
                 }
             }
         }
@@ -243,7 +244,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             fcx.sess().fileline_help(span,
                                      &*format!("candidate #{}: use `{}`",
                                                i + 1,
-                                               ty::item_path_str(fcx.tcx(), *trait_did)))
+                                               fcx.tcx().item_path_str(*trait_did)))
 
         }
         return
@@ -289,7 +290,7 @@ fn suggest_traits_to_import<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             fcx.sess().fileline_help(span,
                                      &*format!("candidate #{}: `{}`",
                                                i + 1,
-                                               ty::item_path_str(fcx.tcx(), trait_info.def_id)))
+                                               fcx.tcx().item_path_str(trait_info.def_id)))
         }
     }
 }
diff --git a/src/librustc_typeck/check/mod.rs b/src/librustc_typeck/check/mod.rs
index 34df349b7a3..299ccd579cc 100644
--- a/src/librustc_typeck/check/mod.rs
+++ b/src/librustc_typeck/check/mod.rs
@@ -96,8 +96,7 @@ use middle::subst::{self, Subst, Substs, VecPerParamSpace, ParamSpace, TypeSpace
 use middle::traits::{self, report_fulfillment_errors};
 use middle::ty::{FnSig, GenericPredicates, TypeScheme};
 use middle::ty::{Disr, ParamTy, ParameterEnvironment};
-use middle::ty::{self, HasProjectionTypes, RegionEscape, ToPolyTraitRef, Ty};
-use middle::ty::liberate_late_bound_regions;
+use middle::ty::{self, HasTypeFlags, RegionEscape, ToPolyTraitRef, Ty};
 use middle::ty::{MethodCall, MethodCallee, MethodMap};
 use middle::ty_fold::{TypeFolder, TypeFoldable};
 use rscope::RegionScope;
@@ -229,7 +228,7 @@ impl<'tcx> Expectation<'tcx> {
         match *self {
             ExpectHasType(ety) => {
                 let ety = fcx.infcx().shallow_resolve(ety);
-                if !ty::type_is_ty_var(ety) {
+                if !ety.is_ty_var() {
                     ExpectHasType(ety)
                 } else {
                     NoExpectation
@@ -308,7 +307,7 @@ impl<'a, 'tcx> mc::Typer<'tcx> for FnCtxt<'a, 'tcx> {
         let ty = self.adjust_expr_ty(expr, self.inh.adjustments.borrow().get(&expr.id));
         self.resolve_type_vars_or_error(&ty)
     }
-    fn type_moves_by_default(&self, span: Span, ty: Ty<'tcx>) -> bool {
+    fn type_moves_by_default(&self, ty: Ty<'tcx>, span: Span) -> bool {
         let ty = self.infcx().resolve_type_vars_if_possible(&ty);
         !traits::type_known_to_meet_builtin_bound(self.infcx(), self, ty, ty::BoundCopy, span)
     }
@@ -363,9 +362,8 @@ impl<'a, 'tcx> ty::ClosureTyper<'tcx> for FnCtxt<'a, 'tcx> {
     fn closure_upvars(&self,
                       def_id: ast::DefId,
                       substs: &Substs<'tcx>)
-                      -> Option<Vec<ty::ClosureUpvar<'tcx>>>
-    {
-        ty::closure_upvars(self, def_id, substs)
+                      -> Option<Vec<ty::ClosureUpvar<'tcx>>> {
+        ty::ctxt::closure_upvars(self, def_id, substs)
     }
 }
 
@@ -397,7 +395,7 @@ impl<'a, 'tcx> Inherited<'a, 'tcx> {
                                         body_id: ast::NodeId,
                                         value: &T)
                                         -> T
-        where T : TypeFoldable<'tcx> + HasProjectionTypes
+        where T : TypeFoldable<'tcx> + HasTypeFlags
     {
         let mut fulfillment_cx = self.fulfillment_cx.borrow_mut();
         assoc::normalize_associated_types_in(&self.infcx,
@@ -430,7 +428,7 @@ fn static_inherited_fields<'a, 'tcx>(ccx: &'a CrateCtxt<'a, 'tcx>)
                                     -> Inherited<'a, 'tcx> {
     // It's kind of a kludge to manufacture a fake function context
     // and statement context, but we might as well do write the code only once
-    let param_env = ty::empty_parameter_environment(ccx.tcx);
+    let param_env = ccx.tcx.empty_parameter_environment();
     Inherited::new(ccx.tcx, param_env)
 }
 
@@ -512,9 +510,8 @@ fn check_bare_fn<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             let fn_sig =
                 fn_ty.sig.subst(ccx.tcx, &inh.param_env.free_substs);
             let fn_sig =
-                liberate_late_bound_regions(ccx.tcx,
-                                            region::DestructionScopeData::new(body.id),
-                                            &fn_sig);
+                ccx.tcx.liberate_late_bound_regions(region::DestructionScopeData::new(body.id),
+                                                    &fn_sig);
             let fn_sig =
                 inh.normalize_associated_types_in(&inh.param_env, body.span, body.id, &fn_sig);
 
@@ -718,7 +715,7 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
     check_representable(tcx, span, id, "struct");
     check_instantiable(tcx, span, id);
 
-    if ty::lookup_simd(tcx, local_def(id)) {
+    if tcx.lookup_simd(local_def(id)) {
         check_simd(tcx, span, id);
     }
 }
@@ -726,7 +723,7 @@ pub fn check_struct(ccx: &CrateCtxt, id: ast::NodeId, span: Span) {
 pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
     debug!("check_item_type(it.id={}, it.ident={})",
            it.id,
-           ty::item_path_str(ccx.tcx, local_def(it.id)));
+           ccx.tcx.item_path_str(local_def(it.id)));
     let _indenter = indenter();
     match it.node {
       // Consts can play a role in type-checking, so they are included here.
@@ -741,7 +738,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
       ast::ItemFn(..) => {} // entirely within check_item_body
       ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
           debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
-          match ty::impl_trait_ref(ccx.tcx, local_def(it.id)) {
+          match ccx.tcx.impl_trait_ref(local_def(it.id)) {
               Some(impl_trait_ref) => {
                 check_impl_items_against_trait(ccx,
                                                it.span,
@@ -758,7 +755,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
         check_struct(ccx, it.id, it.span);
       }
       ast::ItemTy(ref t, ref generics) => {
-        let pty_ty = ty::node_id_to_type(ccx.tcx, it.id);
+        let pty_ty = ccx.tcx.node_id_to_type(it.id);
         check_bounds_are_used(ccx, t.span, &generics.ty_params, pty_ty);
       }
       ast::ItemForeignMod(ref m) => {
@@ -768,7 +765,7 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
             }
         } else {
             for item in &m.items {
-                let pty = ty::lookup_item_type(ccx.tcx, local_def(item.id));
+                let pty = ccx.tcx.lookup_item_type(local_def(item.id));
                 if !pty.generics.types.is_empty() {
                     span_err!(ccx.tcx.sess, item.span, E0044,
                         "foreign items may not have type parameters");
@@ -790,18 +787,18 @@ pub fn check_item_type<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
 pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
     debug!("check_item_body(it.id={}, it.ident={})",
            it.id,
-           ty::item_path_str(ccx.tcx, local_def(it.id)));
+           ccx.tcx.item_path_str(local_def(it.id)));
     let _indenter = indenter();
     match it.node {
       ast::ItemFn(ref decl, _, _, _, _, ref body) => {
-        let fn_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
+        let fn_pty = ccx.tcx.lookup_item_type(ast_util::local_def(it.id));
         let param_env = ParameterEnvironment::for_item(ccx.tcx, it.id);
         check_bare_fn(ccx, &**decl, &**body, it.id, it.span, fn_pty.ty, param_env);
       }
       ast::ItemImpl(_, _, _, _, _, ref impl_items) => {
         debug!("ItemImpl {} with id {}", token::get_ident(it.ident), it.id);
 
-        let impl_pty = ty::lookup_item_type(ccx.tcx, ast_util::local_def(it.id));
+        let impl_pty = ccx.tcx.lookup_item_type(ast_util::local_def(it.id));
 
         for impl_item in impl_items {
             match impl_item.node {
@@ -820,7 +817,7 @@ pub fn check_item_body<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>, it: &'tcx ast::Item) {
         }
       }
       ast::ItemTrait(_, _, _, ref trait_items) => {
-        let trait_def = ty::lookup_trait_def(ccx.tcx, local_def(it.id));
+        let trait_def = ccx.tcx.lookup_trait_def(local_def(it.id));
         for trait_item in trait_items {
             match trait_item.node {
                 ast::ConstTraitItem(_, Some(ref expr)) => {
@@ -921,7 +918,7 @@ fn check_method_body<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             item_generics, id);
     let param_env = ParameterEnvironment::for_item(ccx.tcx, id);
 
-    let fty = ty::node_id_to_type(ccx.tcx, id);
+    let fty = ccx.tcx.node_id_to_type(id);
     debug!("check_method_body: fty={:?}", fty);
 
     check_bare_fn(ccx, &sig.decl, body, id, span, fty, param_env);
@@ -933,7 +930,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                             impl_items: &[P<ast::ImplItem>]) {
     // Locate trait methods
     let tcx = ccx.tcx;
-    let trait_items = ty::trait_items(tcx, impl_trait_ref.def_id);
+    let trait_items = tcx.trait_items(impl_trait_ref.def_id);
 
     // Check existing impl methods to see if they are both present in trait
     // and compatible with trait signature
@@ -941,8 +938,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         match impl_item.node {
             ast::ConstImplItem(..) => {
                 let impl_const_def_id = local_def(impl_item.id);
-                let impl_const_ty = ty::impl_or_trait_item(ccx.tcx,
-                                                           impl_const_def_id);
+                let impl_const_ty = ccx.tcx.impl_or_trait_item(impl_const_def_id);
 
                 // Find associated const definition.
                 let opt_associated_const =
@@ -985,8 +981,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                 check_trait_fn_not_const(ccx, impl_item.span, sig.constness);
 
                 let impl_method_def_id = local_def(impl_item.id);
-                let impl_item_ty = ty::impl_or_trait_item(ccx.tcx,
-                                                          impl_method_def_id);
+                let impl_item_ty = ccx.tcx.impl_or_trait_item(impl_method_def_id);
 
                 // If this is an impl of a trait method, find the
                 // corresponding method definition in the trait.
@@ -1027,8 +1022,7 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             }
             ast::TypeImplItem(_) => {
                 let typedef_def_id = local_def(impl_item.id);
-                let typedef_ty = ty::impl_or_trait_item(ccx.tcx,
-                                                        typedef_def_id);
+                let typedef_ty = ccx.tcx.impl_or_trait_item(typedef_def_id);
 
                 // If this is an impl of an associated type, find the
                 // corresponding type definition in the trait.
@@ -1067,8 +1061,8 @@ fn check_impl_items_against_trait<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     }
 
     // Check for missing items from trait
-    let provided_methods = ty::provided_trait_methods(tcx, impl_trait_ref.def_id);
-    let associated_consts = ty::associated_consts(tcx, impl_trait_ref.def_id);
+    let provided_methods = tcx.provided_trait_methods(impl_trait_ref.def_id);
+    let associated_consts = tcx.associated_consts(impl_trait_ref.def_id);
     let mut missing_items = Vec::new();
     for trait_item in trait_items.iter() {
         match *trait_item {
@@ -1146,7 +1140,7 @@ fn report_cast_to_unsized_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 ast::MutMutable => "mut ",
                 ast::MutImmutable => ""
             };
-            if ty::type_is_trait(t_cast) {
+            if t_cast.is_trait() {
                 match fcx.tcx().sess.codemap().span_to_snippet(t_span) {
                     Ok(s) => {
                         fcx.tcx().sess.span_suggestion(t_span,
@@ -1189,13 +1183,13 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
     fn get_item_type_scheme(&self, _: Span, id: ast::DefId)
                             -> Result<ty::TypeScheme<'tcx>, ErrorReported>
     {
-        Ok(ty::lookup_item_type(self.tcx(), id))
+        Ok(self.tcx().lookup_item_type(id))
     }
 
     fn get_trait_def(&self, _: Span, id: ast::DefId)
                      -> Result<&'tcx ty::TraitDef<'tcx>, ErrorReported>
     {
-        Ok(ty::lookup_trait_def(self.tcx(), id))
+        Ok(self.tcx().lookup_trait_def(id))
     }
 
     fn ensure_super_predicates(&self, _: Span, _: ast::DefId) -> Result<(), ErrorReported> {
@@ -1238,7 +1232,7 @@ impl<'a, 'tcx> AstConv<'tcx> for FnCtxt<'a, 'tcx> {
                                            assoc_name: ast::Name)
                                            -> bool
     {
-        let trait_def = ty::lookup_trait_def(self.ccx.tcx, trait_def_id);
+        let trait_def = self.ccx.tcx.lookup_trait_def(trait_def_id);
         trait_def.associated_type_names.contains(&assoc_name)
     }
 
@@ -1296,15 +1290,15 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     fn resolve_type_vars_if_possible(&self, mut ty: Ty<'tcx>) -> Ty<'tcx> {
         debug!("resolve_type_vars_if_possible(ty={:?})", ty);
 
-        // No ty::infer()? Nothing needs doing.
-        if !ty::type_has_ty_infer(ty) {
+        // No TyInfer()? Nothing needs doing.
+        if !ty.has_infer_types() {
             debug!("resolve_type_vars_if_possible: ty={:?}", ty);
             return ty;
         }
 
         // If `ty` is a type variable, see whether we already know what it is.
         ty = self.infcx().resolve_type_vars_if_possible(&ty);
-        if !ty::type_has_ty_infer(ty) {
+        if !ty.has_infer_types() {
             debug!("resolve_type_vars_if_possible: ty={:?}", ty);
             return ty;
         }
@@ -1312,7 +1306,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         // If not, try resolving any new fcx obligations that have cropped up.
         self.select_new_obligations();
         ty = self.infcx().resolve_type_vars_if_possible(&ty);
-        if !ty::type_has_ty_infer(ty) {
+        if !ty.has_infer_types() {
             debug!("resolve_type_vars_if_possible: ty={:?}", ty);
             return ty;
         }
@@ -1333,9 +1327,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     /// main checking when doing a second pass before writeback. The
     /// justification is that writeback will produce an error for
     /// these unconstrained type variables.
-    fn resolve_type_vars_or_error(&self, t: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
-        let t = self.infcx().resolve_type_vars_if_possible(t);
-        if ty::type_has_ty_infer(t) || ty::type_is_error(t) { Err(()) } else { Ok(t) }
+    fn resolve_type_vars_or_error(&self, ty: &Ty<'tcx>) -> mc::McResult<Ty<'tcx>> {
+        let ty = self.infcx().resolve_type_vars_if_possible(ty);
+        if ty.has_infer_types() || ty.references_error() { Err(()) } else { Ok(ty) }
     }
 
     fn record_deferred_call_resolution(&self,
@@ -1377,7 +1371,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         for (_, &mut ref ty) in &mut *self.inh.node_types.borrow_mut() {
             let resolved = self.infcx().resolve_type_vars_if_possible(ty);
             if self.infcx().type_var_diverges(resolved) {
-                demand::eqtype(self, codemap::DUMMY_SP, *ty, ty::mk_nil(self.tcx()));
+                demand::eqtype(self, codemap::DUMMY_SP, *ty, self.tcx().mk_nil());
             } else {
                 match self.infcx().type_is_unconstrained_numeric(resolved) {
                     UnconstrainedInt => {
@@ -1443,7 +1437,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                   substs: &Substs<'tcx>,
                                   value: &T)
                                   -> T
-        where T : TypeFoldable<'tcx> + HasProjectionTypes
+        where T : TypeFoldable<'tcx> + HasTypeFlags
     {
         let value = value.subst(self.tcx(), substs);
         let result = self.normalize_associated_types_in(span, &value);
@@ -1469,7 +1463,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
 
 
     fn normalize_associated_types_in<T>(&self, span: Span, value: &T) -> T
-        where T : TypeFoldable<'tcx> + HasProjectionTypes
+        where T : TypeFoldable<'tcx> + HasTypeFlags
     {
         self.inh.normalize_associated_types_in(self, span, self.body_id, value)
     }
@@ -1506,9 +1500,9 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                             -> TypeAndSubsts<'tcx>
     {
         let type_scheme =
-            ty::lookup_item_type(self.tcx(), def_id);
+            self.tcx().lookup_item_type(def_id);
         let type_predicates =
-            ty::lookup_predicates(self.tcx(), def_id);
+            self.tcx().lookup_predicates(def_id);
         let substs =
             self.infcx().fresh_substs_for_generics(
                 span,
@@ -1543,7 +1537,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let tcx = self.tcx();
 
         let ty::TypeScheme { generics, ty: decl_ty } =
-            ty::lookup_item_type(tcx, did);
+            tcx.lookup_item_type(did);
 
         let substs = astconv::ast_path_substs_for_ty(self, self,
                                                      path.span,
@@ -1557,7 +1551,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
     }
 
     pub fn write_nil(&self, node_id: ast::NodeId) {
-        self.write_ty(node_id, ty::mk_nil(self.tcx()));
+        self.write_ty(node_id, self.tcx().mk_nil());
     }
     pub fn write_error(&self, node_id: ast::NodeId) {
         self.write_ty(node_id, self.tcx().types.err);
@@ -1651,14 +1645,10 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
         let raw_ty = self.expr_ty(expr);
         let raw_ty = self.infcx().shallow_resolve(raw_ty);
         let resolve_ty = |ty: Ty<'tcx>| self.infcx().resolve_type_vars_if_possible(&ty);
-        ty::adjust_ty(self.tcx(),
-                      expr.span,
-                      expr.id,
-                      raw_ty,
-                      adjustment,
-                      |method_call| self.inh.method_map.borrow()
-                                                       .get(&method_call)
-                                                       .map(|method| resolve_ty(method.ty)))
+        raw_ty.adjust(self.tcx(), expr.span, expr.id, adjustment, |method_call| {
+            self.inh.method_map.borrow().get(&method_call)
+                                        .map(|method| resolve_ty(method.ty))
+        })
     }
 
     pub fn node_ty(&self, id: ast::NodeId) -> Ty<'tcx> {
@@ -1798,7 +1788,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                            -> Option<Ty<'tcx>>
     {
         let o_field = items.iter().find(|f| f.name == fieldname);
-        o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
+        o_field.map(|f| self.tcx().lookup_field_type(class_id, f.id, substs))
                .map(|t| self.normalize_associated_types_in(span, &t))
     }
 
@@ -1811,7 +1801,7 @@ impl<'a, 'tcx> FnCtxt<'a, 'tcx> {
                                -> Option<Ty<'tcx>>
     {
         let o_field = if idx < items.len() { Some(&items[idx]) } else { None };
-        o_field.map(|f| ty::lookup_field_type(self.tcx(), class_id, f.id, substs))
+        o_field.map(|f| self.tcx().lookup_field_type(class_id, f.id, substs))
                .map(|t| self.normalize_associated_types_in(span, &t))
     }
 
@@ -1948,13 +1938,13 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
             }
             UnresolvedTypeAction::Ignore => {
                 // We can continue even when the type cannot be resolved
-                // (i.e. it is an inference variable) because `ty::deref`
+                // (i.e. it is an inference variable) because `Ty::builtin_deref`
                 // and `try_overloaded_deref` both simply return `None`
                 // in such a case without producing spurious errors.
                 fcx.resolve_type_vars_if_possible(t)
             }
         };
-        if ty::type_is_error(resolved_t) {
+        if resolved_t.references_error() {
             return (resolved_t, autoderefs, None);
         }
 
@@ -1964,7 +1954,7 @@ pub fn autoderef<'a, 'tcx, T, F>(fcx: &FnCtxt<'a, 'tcx>,
         }
 
         // Otherwise, deref if type is derefable:
-        let mt = match ty::deref(resolved_t, false) {
+        let mt = match resolved_t.builtin_deref(false) {
             Some(mt) => Some(mt),
             None => {
                 let method_call =
@@ -2045,15 +2035,15 @@ fn make_overloaded_lvalue_return_type<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         Some(method) => {
             // extract method method return type, which will be &T;
             // all LB regions should have been instantiated during method lookup
-            let ret_ty = ty::ty_fn_ret(method.ty);
-            let ret_ty = ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap();
+            let ret_ty = method.ty.fn_ret();
+            let ret_ty = fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap();
 
             if let Some(method_call) = method_call {
                 fcx.inh.method_map.borrow_mut().insert(method_call, method);
             }
 
             // method returns &T, but the type as visible to user is T, so deref
-            ty::deref(ret_ty, true)
+            ret_ty.builtin_deref(true)
         }
         None => None,
     }
@@ -2089,7 +2079,7 @@ fn lookup_indexing<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // After we have fully autoderef'd, if the resulting type is [T; n], then
     // do a final unsized coercion to yield [T].
     if let ty::TyArray(element_ty, _) = ty.sty {
-        let adjusted_ty = ty::mk_vec(fcx.tcx(), element_ty, None);
+        let adjusted_ty = fcx.tcx().mk_slice(element_ty);
         try_index_step(fcx, MethodCall::expr(expr.id), expr, base_expr,
                        adjusted_ty, autoderefs, true, lvalue_pref, idx_ty)
     } else {
@@ -2125,7 +2115,7 @@ fn try_index_step<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let input_ty = fcx.infcx().next_ty_var();
 
     // First, try built-in indexing.
-    match (ty::index(adjusted_ty), &index_ty.sty) {
+    match (adjusted_ty.builtin_index(), &index_ty.sty) {
         (Some(ty), &ty::TyUint(ast::TyUs)) | (Some(ty), &ty::TyInfer(ty::IntVar(_))) => {
             debug!("try_index_step: success, using built-in indexing");
             // If we had `[T; N]`, we should've caught it before unsizing to `[T]`.
@@ -2186,12 +2176,12 @@ fn check_method_argument_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                                          tuple_arguments: TupleArgumentsFlag,
                                          expected: Expectation<'tcx>)
                                          -> ty::FnOutput<'tcx> {
-    if ty::type_is_error(method_fn_ty) {
+    if method_fn_ty.references_error() {
         let err_inputs = err_args(fcx.tcx(), args_no_rcvr.len());
 
         let err_inputs = match tuple_arguments {
             DontTupleArguments => err_inputs,
-            TupleArguments => vec![ty::mk_tup(fcx.tcx(), err_inputs)],
+            TupleArguments => vec![fcx.tcx().mk_tup(err_inputs)],
         };
 
         check_argument_types(fcx,
@@ -2433,17 +2423,15 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let tcx = fcx.ccx.tcx;
 
     match lit.node {
-        ast::LitStr(..) => ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic), ast::MutImmutable),
+        ast::LitStr(..) => tcx.mk_static_str(),
         ast::LitBinary(ref v) => {
-            ty::mk_rptr(tcx, tcx.mk_region(ty::ReStatic), ty::mt {
-                ty: ty::mk_vec(tcx, tcx.types.u8, Some(v.len())),
-                mutbl: ast::MutImmutable,
-            })
+            tcx.mk_imm_ref(tcx.mk_region(ty::ReStatic),
+                            tcx.mk_array(tcx.types.u8, v.len()))
         }
         ast::LitByte(_) => tcx.types.u8,
         ast::LitChar(_) => tcx.types.char,
-        ast::LitInt(_, ast::SignedIntLit(t, _)) => ty::mk_mach_int(tcx, t),
-        ast::LitInt(_, ast::UnsignedIntLit(t)) => ty::mk_mach_uint(tcx, t),
+        ast::LitInt(_, ast::SignedIntLit(t, _)) => tcx.mk_mach_int(t),
+        ast::LitInt(_, ast::UnsignedIntLit(t)) => tcx.mk_mach_uint(t),
         ast::LitInt(_, ast::UnsuffixedIntLit(_)) => {
             let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
@@ -2455,9 +2443,9 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 }
             });
             opt_ty.unwrap_or_else(
-                || ty::mk_int_var(tcx, fcx.infcx().next_int_var_id()))
+                || tcx.mk_int_var(fcx.infcx().next_int_var_id()))
         }
-        ast::LitFloat(_, t) => ty::mk_mach_float(tcx, t),
+        ast::LitFloat(_, t) => tcx.mk_mach_float(t),
         ast::LitFloatUnsuffixed(_) => {
             let opt_ty = expected.to_option(fcx).and_then(|ty| {
                 match ty.sty {
@@ -2466,7 +2454,7 @@ fn check_lit<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                 }
             });
             opt_ty.unwrap_or_else(
-                || ty::mk_float_var(tcx, fcx.infcx().next_float_var_id()))
+                || tcx.mk_float_var(fcx.infcx().next_float_var_id()))
         }
         ast::LitBool(_) => tcx.types.bool
     }
@@ -2530,7 +2518,7 @@ pub fn impl_self_ty<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                               -> TypeAndSubsts<'tcx> {
     let tcx = fcx.tcx();
 
-    let ity = ty::lookup_item_type(tcx, did);
+    let ity = tcx.lookup_item_type(did);
     let (n_tps, rps, raw_ty) =
         (ity.generics.types.len(subst::TypeSpace),
          ity.generics.regions.get_slice(subst::TypeSpace),
@@ -2607,7 +2595,7 @@ fn expected_types_for_fn_args<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
 
 /// Invariant:
 /// If an expression has any sub-expressions that result in a type error,
-/// inspecting that expression's type with `ty::type_is_error` will return
+/// inspecting that expression's type with `ty.references_error()` will return
 /// true. Likewise, if an expression is known to diverge, inspecting its
 /// type with `ty::type_is_bot` will return true (n.b.: since Rust is
 /// strict, _|_ can appear in the type of an expression that does not,
@@ -2705,12 +2693,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                         infer::IfExpressionWithNoElse(sp),
                                         false,
                                         then_ty,
-                                        ty::mk_nil(fcx.tcx()))
+                                        fcx.tcx().mk_nil())
             }
         };
 
         let cond_ty = fcx.expr_ty(cond_expr);
-        let if_ty = if ty::type_is_error(cond_ty) {
+        let if_ty = if cond_ty.references_error() {
             fcx.tcx().types.err
         } else {
             branches_ty
@@ -2740,7 +2728,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 match base_t.sty {
                     ty::TyStruct(base_id, substs) => {
                         debug!("struct named {:?}",  base_t);
-                        let fields = ty::lookup_struct_fields(tcx, base_id);
+                        let fields = tcx.lookup_struct_fields(base_id);
                         fcx.lookup_field_ty(expr.span, base_id, &fields[..],
                                             field.node.name, &(*substs))
                     }
@@ -2796,7 +2784,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let name = &ident;
         // only find fits with at least one matching letter
         let mut best_dist = name.len();
-        let fields = ty::lookup_struct_fields(tcx, id);
+        let fields = tcx.lookup_struct_fields(id);
         let mut best = None;
         for elem in &fields {
             let n = elem.name.as_str();
@@ -2841,10 +2829,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                   |base_t, _| {
                 match base_t.sty {
                     ty::TyStruct(base_id, substs) => {
-                        tuple_like = ty::is_tuple_struct(tcx, base_id);
+                        tuple_like = tcx.is_tuple_struct(base_id);
                         if tuple_like {
                             debug!("tuple struct named {:?}",  base_t);
-                            let fields = ty::lookup_struct_fields(tcx, base_id);
+                            let fields = tcx.lookup_struct_fields(base_id);
                             fcx.lookup_tup_field_ty(expr.span, base_id, &fields[..],
                                                     idx.node, &(*substs))
                         } else {
@@ -2917,8 +2905,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                         field.ident.span,
                         |actual| match enum_id_opt {
                             Some(enum_id) => {
-                                let variant_type = ty::enum_variant_with_id(tcx,
-                                                                            enum_id,
+                                let variant_type = tcx.enum_variant_with_id(enum_id,
                                                                             class_id);
                                 format!("struct variant `{}::{}` has no field named `{}`",
                                         actual, variant_type.name.as_str(),
@@ -2936,7 +2923,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                     let skip_fields = ast_fields.iter().map(|ref x| x.ident.node.name.as_str());
                     let actual_id = match enum_id_opt {
                         Some(_) => class_id,
-                        None => ty::ty_to_def_id(struct_ty).unwrap()
+                        None => struct_ty.ty_to_def_id().unwrap()
                     };
                     suggest_field_names(actual_id, &field.ident, tcx, skip_fields.collect());
                     error_happened = true;
@@ -2949,8 +2936,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 }
                 Some((field_id, false)) => {
                     expected_field_type =
-                        ty::lookup_field_type(
-                            tcx, class_id, field_id, substitutions);
+                        tcx.lookup_field_type(class_id, field_id, substitutions);
                     expected_field_type =
                         fcx.normalize_associated_types_in(
                             field.span, &expected_field_type);
@@ -2991,8 +2977,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         }
 
         if !error_happened {
-            fcx.write_ty(node_id, ty::mk_struct(fcx.ccx.tcx,
-                                class_id, substitutions));
+            fcx.write_ty(node_id, fcx.ccx.tcx.mk_struct(class_id, substitutions));
         }
     }
 
@@ -3011,7 +2996,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         } = fcx.instantiate_type(span, class_id);
 
         // Look up and check the fields.
-        let class_fields = ty::lookup_struct_fields(tcx, class_id);
+        let class_fields = tcx.lookup_struct_fields(class_id);
         check_struct_or_variant_fields(fcx,
                                        struct_type,
                                        span,
@@ -3022,7 +3007,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                        fields,
                                        base_expr.is_none(),
                                        None);
-        if ty::type_is_error(fcx.node_ty(id)) {
+        if fcx.node_ty(id).references_error() {
             struct_type = tcx.types.err;
         }
 
@@ -3054,7 +3039,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         } = fcx.instantiate_type(span, enum_id);
 
         // Look up and check the enum variant fields.
-        let variant_fields = ty::lookup_struct_fields(tcx, variant_id);
+        let variant_fields = tcx.lookup_struct_fields(variant_id);
         check_struct_or_variant_fields(fcx,
                                        enum_type,
                                        span,
@@ -3102,7 +3087,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                   let def_id = definition.def_id();
                   let referent_ty = fcx.expr_ty(&**subexpr);
                   if tcx.lang_items.exchange_heap() == Some(def_id) {
-                      fcx.write_ty(id, ty::mk_uniq(tcx, referent_ty));
+                      fcx.write_ty(id, tcx.mk_box(referent_ty));
                       checked = true
                   }
               }
@@ -3153,14 +3138,14 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             fcx, &**oprnd, expected_inner, lvalue_pref);
         let mut oprnd_t = fcx.expr_ty(&**oprnd);
 
-        if !ty::type_is_error(oprnd_t) {
+        if !oprnd_t.references_error() {
             match unop {
                 ast::UnUniq => {
-                    oprnd_t = ty::mk_uniq(tcx, oprnd_t);
+                    oprnd_t = tcx.mk_box(oprnd_t);
                 }
                 ast::UnDeref => {
                     oprnd_t = structurally_resolved_type(fcx, expr.span, oprnd_t);
-                    oprnd_t = match ty::deref(oprnd_t, true) {
+                    oprnd_t = match oprnd_t.builtin_deref(true) {
                         Some(mt) => mt.ty,
                         None => match try_overloaded_deref(fcx, expr.span,
                                                            Some(MethodCall::expr(expr.id)),
@@ -3179,8 +3164,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 ast::UnNot => {
                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
                                                          oprnd_t);
-                    if !(ty::type_is_integral(oprnd_t) ||
-                         oprnd_t.sty == ty::TyBool) {
+                    if !(oprnd_t.is_integral() || oprnd_t.sty == ty::TyBool) {
                         oprnd_t = op::check_user_unop(fcx, "!", "not",
                                                       tcx.lang_items.not_trait(),
                                                       expr, &**oprnd, oprnd_t, unop);
@@ -3189,8 +3173,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 ast::UnNeg => {
                     oprnd_t = structurally_resolved_type(fcx, oprnd.span,
                                                          oprnd_t);
-                    if !(ty::type_is_integral(oprnd_t) ||
-                         ty::type_is_fp(oprnd_t)) {
+                    if !(oprnd_t.is_integral() || oprnd_t.is_fp()) {
                         oprnd_t = op::check_user_unop(fcx, "-", "neg",
                                                       tcx.lang_items.neg_trait(),
                                                       expr, &**oprnd, oprnd_t, unop);
@@ -3213,7 +3196,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let hint = expected.only_has_type(fcx).map_or(NoExpectation, |ty| {
             match ty.sty {
                 ty::TyRef(_, ref mt) | ty::TyRawPtr(ref mt) => {
-                    if ty::expr_is_lval(fcx.tcx(), &**oprnd) {
+                    if fcx.tcx().expr_is_lval(&**oprnd) {
                         // Lvalues may legitimately have unsized types.
                         // For example, dereferences of a fat pointer and
                         // the last field of a struct can be unsized.
@@ -3232,7 +3215,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                     lvalue_pref);
 
         let tm = ty::mt { ty: fcx.expr_ty(&**oprnd), mutbl: mutbl };
-        let oprnd_t = if ty::type_is_error(tm.ty) {
+        let oprnd_t = if tm.ty.references_error() {
             tcx.types.err
         } else {
             // Note: at this point, we cannot say what the best lifetime
@@ -3249,7 +3232,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             // value whose address was taken can actually be made to live
             // as long as it needs to live.
             let region = fcx.infcx().next_region_var(infer::AddrOfRegion(expr.span));
-            ty::mk_rptr(tcx, tcx.mk_region(region), tm)
+            tcx.mk_ref(tcx.mk_region(region), tm)
         };
         fcx.write_ty(id, oprnd_t);
       }
@@ -3310,7 +3293,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 match *expr_opt {
                     None =>
                         if let Err(_) = fcx.mk_eqty(false, infer::Misc(expr.span),
-                                                    result_type, ty::mk_nil(fcx.tcx())) {
+                                                    result_type, fcx.tcx().mk_nil()) {
                             span_err!(tcx.sess, expr.span, E0069,
                                 "`return;` in a function whose return type is \
                                  not `()`");
@@ -3341,7 +3324,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         check_expr_with_lvalue_pref(fcx, &**lhs, PreferMutLvalue);
 
         let tcx = fcx.tcx();
-        if !ty::expr_is_lval(tcx, &**lhs) {
+        if !tcx.expr_is_lval(&**lhs) {
             span_err!(tcx.sess, expr.span, E0070,
                 "illegal left-hand side expression");
         }
@@ -3352,7 +3335,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 
         fcx.require_expr_have_sized_type(&**lhs, traits::AssignmentLhsSized);
 
-        if ty::type_is_error(lhs_ty) || ty::type_is_error(rhs_ty) {
+        if lhs_ty.references_error() || rhs_ty.references_error() {
             fcx.write_error(id);
         } else {
             fcx.write_nil(id);
@@ -3370,7 +3353,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         check_block_no_value(fcx, &**body);
         let cond_ty = fcx.expr_ty(&**cond);
         let body_ty = fcx.node_ty(body.id);
-        if ty::type_is_error(cond_ty) || ty::type_is_error(body_ty) {
+        if cond_ty.references_error() || body_ty.references_error() {
             fcx.write_error(id);
         }
         else {
@@ -3409,7 +3392,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let arg_tys = args.iter().map(|a| fcx.expr_ty(&**a));
         let  args_err = arg_tys.fold(false,
              |rest_err, a| {
-              rest_err || ty::type_is_error(a)});
+              rest_err || a.references_error()});
         if args_err {
             fcx.write_error(id);
         }
@@ -3427,7 +3410,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         let t_expr = fcx.expr_ty(e);
 
         // Eagerly check for some obvious errors.
-        if ty::type_is_error(t_expr) {
+        if t_expr.references_error() {
             fcx.write_error(id);
         } else if !fcx.type_is_known_to_be_sized(t_cast, expr.span) {
             report_cast_to_unsized_type(fcx, expr.span, t.span, e.span, t_cast, t_expr, id);
@@ -3465,12 +3448,12 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 t
             }
         };
-        let typ = ty::mk_vec(tcx, typ, Some(args.len()));
+        let typ = tcx.mk_array(typ, args.len());
         fcx.write_ty(id, typ);
       }
       ast::ExprRepeat(ref element, ref count_expr) => {
         check_expr_has_type(fcx, &**count_expr, tcx.types.usize);
-        let count = ty::eval_repeat_count(fcx.tcx(), &**count_expr);
+        let count = fcx.tcx().eval_repeat_count(&**count_expr);
 
         let uty = match expected {
             ExpectHasType(uty) => {
@@ -3504,10 +3487,10 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 ty::BoundCopy);
         }
 
-        if ty::type_is_error(element_ty) {
+        if element_ty.references_error() {
             fcx.write_error(id);
         } else {
-            let t = ty::mk_vec(tcx, t, Some(count));
+            let t = tcx.mk_array(t, count);
             fcx.write_ty(id, t);
         }
       }
@@ -3532,13 +3515,13 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                     fcx.expr_ty(&**e)
                 }
             };
-            err_field = err_field || ty::type_is_error(t);
+            err_field = err_field || t.references_error();
             t
         }).collect();
         if err_field {
             fcx.write_error(id);
         } else {
-            let typ = ty::mk_tup(tcx, elt_ts);
+            let typ = tcx.mk_tup(elt_ts);
             fcx.write_ty(id, typ);
         }
       }
@@ -3563,7 +3546,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
             },
             def => {
                 // Verify that this was actually a struct.
-                let typ = ty::lookup_item_type(fcx.ccx.tcx, def.def_id());
+                let typ = fcx.ccx.tcx.lookup_item_type(def.def_id());
                 match typ.ty.sty {
                     ty::TyStruct(struct_did, _) => {
                         check_struct_constructor(fcx,
@@ -3592,7 +3575,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
         // the resulting structure type. This is needed to handle type
         // parameters correctly.
         let actual_structure_type = fcx.expr_ty(&*expr);
-        if !ty::type_is_error(actual_structure_type) {
+        if !actual_structure_type.references_error() {
             let type_and_substs = fcx.instantiate_struct_literal_ty(struct_id, path);
             match fcx.mk_subty(false,
                                infer::Misc(path.span),
@@ -3610,7 +3593,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                             .ty_to_string(
                                                 actual_structure_type),
                                          type_error);
-                    ty::note_and_explain_type_err(tcx, &type_error, path.span);
+                    tcx.note_and_explain_type_err(&type_error, path.span);
                 }
             }
         }
@@ -3630,9 +3613,9 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
           let base_t = fcx.expr_ty(&**base);
           let idx_t = fcx.expr_ty(&**idx);
 
-          if ty::type_is_error(base_t) {
+          if base_t.references_error() {
               fcx.write_ty(id, base_t);
-          } else if ty::type_is_error(idx_t) {
+          } else if idx_t.references_error() {
               fcx.write_ty(id, idx_t);
           } else {
               let base_t = structurally_resolved_type(fcx, expr.span, base_t);
@@ -3671,8 +3654,8 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
               (Some(ty), None) | (None, Some(ty)) => {
                   Some(ty)
               }
-              (Some(t_start), Some(t_end)) if (ty::type_is_error(t_start) ||
-                                               ty::type_is_error(t_end)) => {
+              (Some(t_start), Some(t_end)) if (t_start.references_error() ||
+                                               t_end.references_error()) => {
                   Some(fcx.tcx().types.err)
               }
               (Some(t_start), Some(t_end)) => {
@@ -3690,7 +3673,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
           // some bounds, then we'll need to check `t_start` against them here.
 
           let range_type = match idx_type {
-            Some(idx_type) if ty::type_is_error(idx_type) => {
+            Some(idx_type) if idx_type.references_error() => {
                 fcx.tcx().types.err
             }
             Some(idx_type) => {
@@ -3705,7 +3688,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 };
 
                 if let Some(did) = did {
-                    let predicates = ty::lookup_predicates(tcx, did);
+                    let predicates = tcx.lookup_predicates(did);
                     let substs = Substs::new_type(vec![idx_type], vec![]);
                     let bounds = fcx.instantiate_bounds(expr.span, &substs, &predicates);
                     fcx.add_obligations_for_parameters(
@@ -3714,7 +3697,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                                                      traits::ItemObligation(did)),
                         &bounds);
 
-                    ty::mk_struct(tcx, did, tcx.mk_substs(substs))
+                    tcx.mk_struct(did, tcx.mk_substs(substs))
                 } else {
                     span_err!(tcx.sess, expr.span, E0236, "no lang item for range syntax");
                     fcx.tcx().types.err
@@ -3724,7 +3707,7 @@ fn check_expr_with_unifier<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
                 // Neither start nor end => RangeFull
                 if let Some(did) = tcx.lang_items.range_full_struct() {
                     let substs = Substs::new_type(vec![], vec![]);
-                    ty::mk_struct(tcx, did, tcx.mk_substs(substs))
+                    tcx.mk_struct(did, tcx.mk_substs(substs))
                 } else {
                     span_err!(tcx.sess, expr.span, E0237, "no lang item for range syntax");
                     fcx.tcx().types.err
@@ -3765,7 +3748,7 @@ pub fn resolve_ty_and_def_ufcs<'a, 'b, 'tcx>(fcx: &FnCtxt<'b, 'tcx>,
                                                 node_id: ast::NodeId) -> bool {
         match def {
             def::DefAssociatedConst(..) => {
-                if ty::type_has_params(ty) || ty::type_has_self(ty) {
+                if ty.has_param_types() || ty.has_self_ty() {
                     span_err!(fcx.sess(), span, E0329,
                               "Associated consts cannot depend \
                                on type parameters or Self.");
@@ -3933,7 +3916,7 @@ pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local)
     if let Some(ref init) = local.init {
         check_decl_initializer(fcx, local, &**init);
         let init_ty = fcx.expr_ty(&**init);
-        if ty::type_is_error(init_ty) {
+        if init_ty.references_error() {
             fcx.write_ty(local.id, init_ty);
         }
     }
@@ -3944,7 +3927,7 @@ pub fn check_decl_local<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, local: &'tcx ast::Local)
     };
     _match::check_pat(&pcx, &*local.pat, t);
     let pat_ty = fcx.node_ty(local.pat.id);
-    if ty::type_is_error(pat_ty) {
+    if pat_ty.references_error() {
         fcx.write_ty(local.id, pat_ty);
     }
 }
@@ -3961,7 +3944,7 @@ pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt)  {
               check_decl_local(fcx, &**l);
               let l_t = fcx.node_ty(l.id);
               saw_bot = saw_bot || fcx.infcx().type_var_diverges(l_t);
-              saw_err = saw_err || ty::type_is_error(l_t);
+              saw_err = saw_err || l_t.references_error();
           }
           ast::DeclItem(_) => {/* ignore for now */ }
         }
@@ -3969,17 +3952,17 @@ pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt)  {
       ast::StmtExpr(ref expr, id) => {
         node_id = id;
         // Check with expected type of ()
-        check_expr_has_type(fcx, &**expr, ty::mk_nil(fcx.tcx()));
+        check_expr_has_type(fcx, &**expr, fcx.tcx().mk_nil());
         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);
+        saw_err = saw_err || expr_ty.references_error();
       }
       ast::StmtSemi(ref expr, id) => {
         node_id = id;
         check_expr(fcx, &**expr);
         let expr_ty = fcx.expr_ty(&**expr);
         saw_bot |= fcx.infcx().type_var_diverges(expr_ty);
-        saw_err |= ty::type_is_error(expr_ty);
+        saw_err |= expr_ty.references_error();
       }
       ast::StmtMac(..) => fcx.ccx.tcx.sess.bug("unexpanded macro")
     }
@@ -3995,12 +3978,12 @@ pub fn check_stmt<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, stmt: &'tcx ast::Stmt)  {
 }
 
 pub fn check_block_no_value<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>, blk: &'tcx ast::Block)  {
-    check_block_with_expected(fcx, blk, ExpectHasType(ty::mk_nil(fcx.tcx())));
+    check_block_with_expected(fcx, blk, ExpectHasType(fcx.tcx().mk_nil()));
     let blkty = fcx.node_ty(blk.id);
-    if ty::type_is_error(blkty) {
+    if blkty.references_error() {
         fcx.write_error(blk.id);
     } else {
-        let nilty = ty::mk_nil(fcx.tcx());
+        let nilty = fcx.tcx().mk_nil();
         demand::suptype(fcx, blk.span, nilty, blkty);
     }
 }
@@ -4041,7 +4024,7 @@ fn check_block_with_expected<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             warned = true;
         }
         any_diverges = any_diverges || fcx.infcx().type_var_diverges(s_ty);
-        any_err = any_err || ty::type_is_error(s_ty);
+        any_err = any_err || s_ty.references_error();
     }
     match blk.expr {
         None => if any_err {
@@ -4101,7 +4084,7 @@ fn check_const<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                         e: &'tcx ast::Expr,
                         id: ast::NodeId) {
     let inh = static_inherited_fields(ccx);
-    let rty = ty::node_id_to_type(ccx.tcx, id);
+    let rty = ccx.tcx.node_id_to_type(id);
     let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), e.id);
     let declty = fcx.ccx.tcx.tcache.borrow().get(&local_def(id)).unwrap().ty;
     check_const_with_ty(&fcx, sp, e, declty);
@@ -4134,14 +4117,14 @@ pub fn check_representable(tcx: &ty::ctxt,
                            sp: Span,
                            item_id: ast::NodeId,
                            designation: &str) -> bool {
-    let rty = ty::node_id_to_type(tcx, item_id);
+    let rty = tcx.node_id_to_type(item_id);
 
     // Check that it is possible to represent this type. This call identifies
     // (1) types that contain themselves and (2) types that contain a different
     // recursive type. It is only necessary to throw an error on those that
     // contain themselves. For case 2, there must be an inner type that will be
     // caught by case 1.
-    match ty::is_type_representable(tcx, sp, rty) {
+    match rty.is_representable(tcx, sp) {
       ty::SelfRecursive => {
         span_err!(tcx.sess, sp, E0072,
             "illegal recursive {} type; \
@@ -4169,8 +4152,8 @@ pub fn check_instantiable(tcx: &ty::ctxt,
                           sp: Span,
                           item_id: ast::NodeId)
                           -> bool {
-    let item_ty = ty::node_id_to_type(tcx, item_id);
-    if !ty::is_instantiable(tcx, item_ty) {
+    let item_ty = tcx.node_id_to_type(item_id);
+    if !item_ty.is_instantiable(tcx) {
         span_err!(tcx.sess, sp, E0073,
             "this type cannot be instantiated without an \
              instance of itself");
@@ -4183,25 +4166,25 @@ pub fn check_instantiable(tcx: &ty::ctxt,
 }
 
 pub fn check_simd(tcx: &ty::ctxt, sp: Span, id: ast::NodeId) {
-    let t = ty::node_id_to_type(tcx, id);
-    if ty::type_needs_subst(t) {
+    let t = tcx.node_id_to_type(id);
+    if t.needs_subst() {
         span_err!(tcx.sess, sp, E0074, "SIMD vector cannot be generic");
         return;
     }
     match t.sty {
         ty::TyStruct(did, substs) => {
-            let fields = ty::lookup_struct_fields(tcx, did);
+            let fields = tcx.lookup_struct_fields(did);
             if fields.is_empty() {
                 span_err!(tcx.sess, sp, E0075, "SIMD vector cannot be empty");
                 return;
             }
-            let e = ty::lookup_field_type(tcx, did, fields[0].id, substs);
+            let e = tcx.lookup_field_type(did, fields[0].id, substs);
             if !fields.iter().all(
-                         |f| ty::lookup_field_type(tcx, did, f.id, substs) == e) {
+                         |f| tcx.lookup_field_type(did, f.id, substs) == e) {
                 span_err!(tcx.sess, sp, E0076, "SIMD vector should be homogeneous");
                 return;
             }
-            if !ty::type_is_machine(e) {
+            if !e.is_machine() {
                 span_err!(tcx.sess, sp, E0077,
                     "SIMD vector element type should be machine type");
                 return;
@@ -4249,13 +4232,13 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                           hint: attr::ReprAttr) {
         #![allow(trivial_numeric_casts)]
 
-        let rty = ty::node_id_to_type(ccx.tcx, id);
+        let rty = ccx.tcx.node_id_to_type(id);
         let mut disr_vals: Vec<ty::Disr> = Vec::new();
 
         let inh = static_inherited_fields(ccx);
         let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(rty), id);
 
-        let (_, repr_type_ty) = ty::enum_repr_type(ccx.tcx, Some(&hint));
+        let (_, repr_type_ty) = ccx.tcx.enum_repr_type(Some(&hint));
         for v in vs {
             if let Some(ref e) = v.node.disr_expr {
                 check_const_with_ty(&fcx, e.span, e, repr_type_ty);
@@ -4266,7 +4249,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
 
         // ty::enum_variants guards against discriminant overflows, so
         // we need not check for that.
-        let variants = ty::enum_variants(ccx.tcx, def_id);
+        let variants = ccx.tcx.enum_variants(def_id);
 
         for (v, variant) in vs.iter().zip(variants.iter()) {
             let current_disr_val = variant.disr_val;
@@ -4300,7 +4283,7 @@ pub fn check_enum_variants<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         }
     }
 
-    let hint = *ty::lookup_repr_hints(ccx.tcx, ast::DefId { krate: ast::LOCAL_CRATE, node: id })
+    let hint = *ccx.tcx.lookup_repr_hints(ast::DefId { krate: ast::LOCAL_CRATE, node: id })
         .get(0).unwrap_or(&attr::ReprAny);
 
     if hint != attr::ReprAny && vs.len() <= 1 {
@@ -4338,7 +4321,7 @@ fn type_scheme_and_predicates_for_def<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         def::DefFn(id, _) | def::DefMethod(id, _) |
         def::DefStatic(id, _) | def::DefVariant(_, id, _) |
         def::DefStruct(id) | def::DefConst(id) | def::DefAssociatedConst(id, _) => {
-            (ty::lookup_item_type(fcx.tcx(), id), ty::lookup_predicates(fcx.tcx(), id))
+            (fcx.tcx().lookup_item_type(id), fcx.tcx().lookup_predicates(id))
         }
         def::DefTrait(_) |
         def::DefTy(..) |
@@ -4600,7 +4583,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         // is inherent, there is no `Self` parameter, instead, the impl needs
         // type parameters, which we can infer by unifying the provided `Self`
         // with the substituted impl type.
-        let impl_scheme = ty::lookup_item_type(fcx.tcx(), impl_def_id);
+        let impl_scheme = fcx.tcx().lookup_item_type(impl_def_id);
         assert_eq!(substs.types.len(subst::TypeSpace),
                    impl_scheme.generics.types.len(subst::TypeSpace));
         assert_eq!(substs.regions().len(subst::TypeSpace),
@@ -4736,8 +4719,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         let input_tys: Vec<Ty> =
             data.inputs.iter().map(|ty| fcx.to_ty(&**ty)).collect();
 
-        let tuple_ty =
-            ty::mk_tup(fcx.tcx(), input_tys);
+        let tuple_ty = fcx.tcx().mk_tup(input_tys);
 
         if type_count >= 1 {
             substs.types.push(space, tuple_ty);
@@ -4747,7 +4729,7 @@ pub fn instantiate_path<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             data.output.as_ref().map(|ty| fcx.to_ty(&**ty));
 
         let output_ty =
-            output_ty.unwrap_or(ty::mk_nil(fcx.tcx()));
+            output_ty.unwrap_or(fcx.tcx().mk_nil());
 
         if type_count >= 2 {
             substs.types.push(space, output_ty);
@@ -4870,11 +4852,11 @@ fn structurally_resolve_type_or_else<'a, 'tcx, F>(fcx: &FnCtxt<'a, 'tcx>,
 {
     let mut ty = fcx.resolve_type_vars_if_possible(ty);
 
-    if ty::type_is_ty_var(ty) {
+    if ty.is_ty_var() {
         let alternative = f();
 
         // If not, error.
-        if ty::type_is_ty_var(alternative) || ty::type_is_error(alternative) {
+        if alternative.is_ty_var() || alternative.references_error() {
             fcx.type_error_message(sp, |_actual| {
                 "the type of this value must be known in this context".to_string()
             }, ty, None);
@@ -4933,15 +4915,12 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     if tps.is_empty() { return; }
     let mut tps_used: Vec<_> = repeat(false).take(tps.len()).collect();
 
-    ty::walk_ty(ty, |t| {
-            match t.sty {
-                ty::TyParam(ParamTy {idx, ..}) => {
-                    debug!("Found use of ty param num {}", idx);
-                    tps_used[idx as usize] = true;
-                }
-                _ => ()
-            }
-        });
+    for leaf_ty in ty.walk() {
+        if let ty::TyParam(ParamTy {idx, ..}) = leaf_ty.sty {
+            debug!("Found use of ty param num {}", idx);
+            tps_used[idx as usize] = true;
+        }
+    }
 
     for (i, b) in tps_used.iter().enumerate() {
         if !*b {
@@ -4957,7 +4936,7 @@ pub fn check_bounds_are_used<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
     fn param<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, n: u32) -> Ty<'tcx> {
         let name = token::intern(&format!("P{}", n));
-        ty::mk_param(ccx.tcx, subst::FnSpace, n, name)
+        ccx.tcx.mk_param(subst::FnSpace, n, name)
     }
 
     let tcx = ccx.tcx;
@@ -4968,22 +4947,22 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
 
         //We only care about the operation here
         let (n_tps, inputs, output) = match split[1] {
-            "cxchg" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)),
+            "cxchg" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)),
                                 param(ccx, 0),
                                 param(ccx, 0)),
                         param(ccx, 0)),
-            "load" => (1, vec!(ty::mk_imm_ptr(tcx, param(ccx, 0))),
+            "load" => (1, vec!(tcx.mk_imm_ptr(param(ccx, 0))),
                        param(ccx, 0)),
-            "store" => (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
-                        ty::mk_nil(tcx)),
+            "store" => (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
+                        tcx.mk_nil()),
 
             "xchg" | "xadd" | "xsub" | "and"  | "nand" | "or" | "xor" | "max" |
             "min"  | "umax" | "umin" => {
-                (1, vec!(ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0)),
+                (1, vec!(tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0)),
                  param(ccx, 0))
             }
             "fence" | "singlethreadfence" => {
-                (0, Vec::new(), ty::mk_nil(tcx))
+                (0, Vec::new(), tcx.mk_nil())
             }
             op => {
                 span_err!(tcx.sess, it.span, E0092,
@@ -4996,50 +4975,47 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
         (0, Vec::new(), ty::FnDiverging)
     } else {
         let (n_tps, inputs, output) = match &name[..] {
-            "breakpoint" => (0, Vec::new(), ty::mk_nil(tcx)),
+            "breakpoint" => (0, Vec::new(), tcx.mk_nil()),
             "size_of" |
             "pref_align_of" | "min_align_of" => (1, Vec::new(), ccx.tcx.types.usize),
             "size_of_val" |  "min_align_of_val" => {
                 (1, vec![
-                    ty::mk_imm_rptr(tcx,
-                                    tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
+                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
                                                                   ty::BrAnon(0))),
                                     param(ccx, 0))
                  ], ccx.tcx.types.usize)
             }
             "init" | "init_dropped" => (1, Vec::new(), param(ccx, 0)),
             "uninit" => (1, Vec::new(), param(ccx, 0)),
-            "forget" => (1, vec!( param(ccx, 0) ), ty::mk_nil(tcx)),
+            "forget" => (1, vec!( param(ccx, 0) ), tcx.mk_nil()),
             "transmute" => (2, vec!( param(ccx, 0) ), param(ccx, 1)),
             "move_val_init" => {
                 (1,
                  vec!(
-                    ty::mk_mut_rptr(tcx,
-                                    tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
+                    tcx.mk_mut_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
                                                                   ty::BrAnon(0))),
                                     param(ccx, 0)),
                     param(ccx, 0)
                   ),
-               ty::mk_nil(tcx))
+               tcx.mk_nil())
             }
             "drop_in_place" => {
-                (1, vec![ty::mk_mut_ptr(tcx, param(ccx, 0))], ty::mk_nil(tcx))
+                (1, vec![tcx.mk_mut_ptr(param(ccx, 0))], tcx.mk_nil())
             }
             "needs_drop" => (1, Vec::new(), ccx.tcx.types.bool),
 
-            "type_name" => (1, Vec::new(), ty::mk_str_slice(tcx, tcx.mk_region(ty::ReStatic),
-                                                             ast::MutImmutable)),
+            "type_name" => (1, Vec::new(), tcx.mk_static_str()),
             "type_id" => (1, Vec::new(), ccx.tcx.types.u64),
             "offset" | "arith_offset" => {
               (1,
                vec!(
-                  ty::mk_ptr(tcx, ty::mt {
+                  tcx.mk_ptr(ty::mt {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
                   ccx.tcx.types.isize
                ),
-               ty::mk_ptr(tcx, ty::mt {
+               tcx.mk_ptr(ty::mt {
                    ty: param(ccx, 0),
                    mutbl: ast::MutImmutable
                }))
@@ -5047,44 +5023,44 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
             "copy" | "copy_nonoverlapping" => {
               (1,
                vec!(
-                  ty::mk_ptr(tcx, ty::mt {
+                  tcx.mk_ptr(ty::mt {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
-                  ty::mk_ptr(tcx, ty::mt {
+                  tcx.mk_ptr(ty::mt {
                       ty: param(ccx, 0),
                       mutbl: ast::MutMutable
                   }),
                   tcx.types.usize,
                ),
-               ty::mk_nil(tcx))
+               tcx.mk_nil())
             }
             "volatile_copy_memory" | "volatile_copy_nonoverlapping_memory" => {
               (1,
                vec!(
-                  ty::mk_ptr(tcx, ty::mt {
+                  tcx.mk_ptr(ty::mt {
                       ty: param(ccx, 0),
                       mutbl: ast::MutMutable
                   }),
-                  ty::mk_ptr(tcx, ty::mt {
+                  tcx.mk_ptr(ty::mt {
                       ty: param(ccx, 0),
                       mutbl: ast::MutImmutable
                   }),
                   tcx.types.usize,
                ),
-               ty::mk_nil(tcx))
+               tcx.mk_nil())
             }
             "write_bytes" | "volatile_set_memory" => {
               (1,
                vec!(
-                  ty::mk_ptr(tcx, ty::mt {
+                  tcx.mk_ptr(ty::mt {
                       ty: param(ccx, 0),
                       mutbl: ast::MutMutable
                   }),
                   tcx.types.u8,
                   tcx.types.usize,
                ),
-               ty::mk_nil(tcx))
+               tcx.mk_nil())
             }
             "sqrtf32" => (0, vec!( tcx.types.f32 ), tcx.types.f32),
             "sqrtf64" => (0, vec!( tcx.types.f64 ), tcx.types.f64),
@@ -5165,41 +5141,41 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
             "bswap64"      => (0, vec!( tcx.types.u64 ), tcx.types.u64),
 
             "volatile_load" =>
-                (1, vec!( ty::mk_imm_ptr(tcx, param(ccx, 0)) ), param(ccx, 0)),
+                (1, vec!( tcx.mk_imm_ptr(param(ccx, 0)) ), param(ccx, 0)),
             "volatile_store" =>
-                (1, vec!( ty::mk_mut_ptr(tcx, param(ccx, 0)), param(ccx, 0) ), ty::mk_nil(tcx)),
+                (1, vec!( tcx.mk_mut_ptr(param(ccx, 0)), param(ccx, 0) ), tcx.mk_nil()),
 
             "i8_add_with_overflow" | "i8_sub_with_overflow" | "i8_mul_with_overflow" =>
                 (0, vec!(tcx.types.i8, tcx.types.i8),
-                ty::mk_tup(tcx, vec!(tcx.types.i8, tcx.types.bool))),
+                tcx.mk_tup(vec!(tcx.types.i8, tcx.types.bool))),
 
             "i16_add_with_overflow" | "i16_sub_with_overflow" | "i16_mul_with_overflow" =>
                 (0, vec!(tcx.types.i16, tcx.types.i16),
-                ty::mk_tup(tcx, vec!(tcx.types.i16, tcx.types.bool))),
+                tcx.mk_tup(vec!(tcx.types.i16, tcx.types.bool))),
 
             "i32_add_with_overflow" | "i32_sub_with_overflow" | "i32_mul_with_overflow" =>
                 (0, vec!(tcx.types.i32, tcx.types.i32),
-                ty::mk_tup(tcx, vec!(tcx.types.i32, tcx.types.bool))),
+                tcx.mk_tup(vec!(tcx.types.i32, tcx.types.bool))),
 
             "i64_add_with_overflow" | "i64_sub_with_overflow" | "i64_mul_with_overflow" =>
                 (0, vec!(tcx.types.i64, tcx.types.i64),
-                ty::mk_tup(tcx, vec!(tcx.types.i64, tcx.types.bool))),
+                tcx.mk_tup(vec!(tcx.types.i64, tcx.types.bool))),
 
             "u8_add_with_overflow" | "u8_sub_with_overflow" | "u8_mul_with_overflow" =>
                 (0, vec!(tcx.types.u8, tcx.types.u8),
-                ty::mk_tup(tcx, vec!(tcx.types.u8, tcx.types.bool))),
+                tcx.mk_tup(vec!(tcx.types.u8, tcx.types.bool))),
 
             "u16_add_with_overflow" | "u16_sub_with_overflow" | "u16_mul_with_overflow" =>
                 (0, vec!(tcx.types.u16, tcx.types.u16),
-                ty::mk_tup(tcx, vec!(tcx.types.u16, tcx.types.bool))),
+                tcx.mk_tup(vec!(tcx.types.u16, tcx.types.bool))),
 
             "u32_add_with_overflow" | "u32_sub_with_overflow" | "u32_mul_with_overflow"=>
                 (0, vec!(tcx.types.u32, tcx.types.u32),
-                ty::mk_tup(tcx, vec!(tcx.types.u32, tcx.types.bool))),
+                tcx.mk_tup(vec!(tcx.types.u32, tcx.types.bool))),
 
             "u64_add_with_overflow" | "u64_sub_with_overflow"  | "u64_mul_with_overflow" =>
                 (0, vec!(tcx.types.u64, tcx.types.u64),
-                ty::mk_tup(tcx, vec!(tcx.types.u64, tcx.types.bool))),
+                tcx.mk_tup(vec!(tcx.types.u64, tcx.types.bool))),
 
             "unchecked_udiv" | "unchecked_sdiv" | "unchecked_urem" | "unchecked_srem" =>
                 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
@@ -5207,13 +5183,12 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
             "overflowing_add" | "overflowing_sub" | "overflowing_mul" =>
                 (1, vec![param(ccx, 0), param(ccx, 0)], param(ccx, 0)),
 
-            "return_address" => (0, vec![], ty::mk_imm_ptr(tcx, tcx.types.u8)),
+            "return_address" => (0, vec![], tcx.mk_imm_ptr(tcx.types.u8)),
 
-            "assume" => (0, vec![tcx.types.bool], ty::mk_nil(tcx)),
+            "assume" => (0, vec![tcx.types.bool], tcx.mk_nil()),
 
             "discriminant_value" => (1, vec![
-                    ty::mk_imm_rptr(tcx,
-                                    tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
+                    tcx.mk_imm_ref(tcx.mk_region(ty::ReLateBound(ty::DebruijnIndex::new(1),
                                                                   ty::BrAnon(0))),
                                     param(ccx, 0))], tcx.types.u64),
 
@@ -5225,7 +5200,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
         };
         (n_tps, inputs, ty::FnConverging(output))
     };
-    let fty = ty::mk_bare_fn(tcx, None, tcx.mk_bare_fn(ty::BareFnTy {
+    let fty = tcx.mk_fn(None, tcx.mk_bare_fn(ty::BareFnTy {
         unsafety: ast::Unsafety::Unsafe,
         abi: abi::RustIntrinsic,
         sig: ty::Binder(FnSig {
@@ -5234,7 +5209,7 @@ pub fn check_intrinsic_type(ccx: &CrateCtxt, it: &ast::ForeignItem) {
             variadic: false,
         }),
     }));
-    let i_ty = ty::lookup_item_type(ccx.tcx, local_def(it.id));
+    let i_ty = ccx.tcx.lookup_item_type(local_def(it.id));
     let i_n_tps = i_ty.generics.types.len(subst::FnSpace);
     if i_n_tps != n_tps {
         span_err!(tcx.sess, it.span, E0094,
diff --git a/src/librustc_typeck/check/op.rs b/src/librustc_typeck/check/op.rs
index a5e4e0fab59..5a114c81119 100644
--- a/src/librustc_typeck/check/op.rs
+++ b/src/librustc_typeck/check/op.rs
@@ -21,7 +21,7 @@ use super::{
     structurally_resolved_type,
 };
 use middle::traits;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use syntax::ast;
 use syntax::ast_util;
 use syntax::parse::token;
@@ -46,7 +46,7 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
         fcx.write_nil(expr.id);
     } else {
         // error types are considered "builtin"
-        assert!(!ty::type_is_error(lhs_ty) || !ty::type_is_error(rhs_ty));
+        assert!(!lhs_ty.references_error() || !rhs_ty.references_error());
         span_err!(tcx.sess, lhs_expr.span, E0368,
                   "binary assignment operation `{}=` cannot be applied to types `{}` and `{}`",
                   ast_util::binop_to_string(op.node),
@@ -56,7 +56,7 @@ pub fn check_binop_assign<'a,'tcx>(fcx: &FnCtxt<'a,'tcx>,
     }
 
     let tcx = fcx.tcx();
-    if !ty::expr_is_lval(tcx, lhs_expr) {
+    if !tcx.expr_is_lval(lhs_expr) {
         span_err!(tcx.sess, lhs_expr.span, E0067, "illegal left-hand side expression");
     }
 
@@ -86,7 +86,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     // traits, because their return type is not bool. Perhaps this
     // should change, but for now if LHS is SIMD we go down a
     // different path that bypassess all traits.
-    if ty::type_is_simd(fcx.tcx(), lhs_ty) {
+    if lhs_ty.is_simd(fcx.tcx()) {
         check_expr_coercable_to_type(fcx, rhs_expr, lhs_ty);
         let rhs_ty = fcx.resolve_type_vars_if_possible(fcx.expr_ty(lhs_expr));
         let return_ty = enforce_builtin_binop_types(fcx, lhs_expr, lhs_ty, rhs_expr, rhs_ty, op);
@@ -97,9 +97,9 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     match BinOpCategory::from(op) {
         BinOpCategory::Shortcircuit => {
             // && and || are a simple case.
-            demand::suptype(fcx, lhs_expr.span, ty::mk_bool(tcx), lhs_ty);
-            check_expr_coercable_to_type(fcx, rhs_expr, ty::mk_bool(tcx));
-            fcx.write_ty(expr.id, ty::mk_bool(tcx));
+            demand::suptype(fcx, lhs_expr.span, tcx.mk_bool(), lhs_ty);
+            check_expr_coercable_to_type(fcx, rhs_expr, tcx.mk_bool());
+            fcx.write_ty(expr.id, tcx.mk_bool());
         }
         _ => {
             // Otherwise, we always treat operators as if they are
@@ -122,8 +122,7 @@ pub fn check_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             // can't pin this down to a specific impl.
             let rhs_ty = fcx.resolve_type_vars_if_possible(rhs_ty);
             if
-                !ty::type_is_ty_var(lhs_ty) &&
-                !ty::type_is_ty_var(rhs_ty) &&
+                !lhs_ty.is_ty_var() && !rhs_ty.is_ty_var() &&
                 is_builtin_binop(fcx.tcx(), lhs_ty, rhs_ty, op)
             {
                 let builtin_return_ty =
@@ -149,15 +148,15 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
     let tcx = fcx.tcx();
     match BinOpCategory::from(op) {
         BinOpCategory::Shortcircuit => {
-            demand::suptype(fcx, lhs_expr.span, ty::mk_bool(tcx), lhs_ty);
-            demand::suptype(fcx, rhs_expr.span, ty::mk_bool(tcx), rhs_ty);
-            ty::mk_bool(tcx)
+            demand::suptype(fcx, lhs_expr.span, tcx.mk_bool(), lhs_ty);
+            demand::suptype(fcx, rhs_expr.span, tcx.mk_bool(), rhs_ty);
+            tcx.mk_bool()
         }
 
         BinOpCategory::Shift => {
             // For integers, the shift amount can be of any integral
             // type. For simd, the type must match exactly.
-            if ty::type_is_simd(tcx, lhs_ty) {
+            if lhs_ty.is_simd(tcx) {
                 demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty);
             }
 
@@ -177,12 +176,12 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
             demand::suptype(fcx, rhs_expr.span, lhs_ty, rhs_ty);
 
             // if this is simd, result is same as lhs, else bool
-            if ty::type_is_simd(tcx, lhs_ty) {
-                let unit_ty = ty::simd_type(tcx, lhs_ty);
+            if lhs_ty.is_simd(tcx) {
+                let unit_ty = lhs_ty.simd_type(tcx);
                 debug!("enforce_builtin_binop_types: lhs_ty={:?} unit_ty={:?}",
                        lhs_ty,
                        unit_ty);
-                if !ty::type_is_integral(unit_ty) {
+                if !unit_ty.is_integral() {
                     tcx.sess.span_err(
                         lhs_expr.span,
                         &format!("binary comparison operation `{}` not supported \
@@ -194,7 +193,7 @@ fn enforce_builtin_binop_types<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
                     lhs_ty
                 }
             } else {
-                ty::mk_bool(tcx)
+                tcx.mk_bool()
             }
         }
     }
@@ -228,7 +227,7 @@ fn check_overloaded_binop<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         Ok(return_ty) => return_ty,
         Err(()) => {
             // error types are considered "builtin"
-            if !ty::type_is_error(lhs_ty) {
+            if !lhs_ty.references_error() {
                 span_err!(fcx.tcx().sess, lhs_expr.span, E0369,
                           "binary operation `{}` cannot be applied to type `{}`",
                           ast_util::binop_to_string(op.node),
@@ -335,8 +334,8 @@ fn lookup_op_method<'a, 'tcx>(fcx: &'a FnCtxt<'a, 'tcx>,
 
             // extract return type for method; all late bound regions
             // should have been instantiated by now
-            let ret_ty = ty::ty_fn_ret(method_ty);
-            Ok(ty::no_late_bound_regions(fcx.tcx(), &ret_ty).unwrap().unwrap())
+            let ret_ty = method_ty.fn_ret();
+            Ok(fcx.tcx().no_late_bound_regions(&ret_ty).unwrap().unwrap())
         }
         None => {
             Err(())
@@ -428,30 +427,30 @@ fn is_builtin_binop<'tcx>(cx: &ty::ctxt<'tcx>,
         }
 
         BinOpCategory::Shift => {
-            ty::type_is_error(lhs) || ty::type_is_error(rhs) ||
-                ty::type_is_integral(lhs) && ty::type_is_integral(rhs) ||
-                ty::type_is_simd(cx, lhs) && ty::type_is_simd(cx, rhs)
+            lhs.references_error() || rhs.references_error() ||
+                lhs.is_integral() && rhs.is_integral() ||
+                lhs.is_simd(cx) && rhs.is_simd(cx)
         }
 
         BinOpCategory::Math => {
-            ty::type_is_error(lhs) || ty::type_is_error(rhs) ||
-                ty::type_is_integral(lhs) && ty::type_is_integral(rhs) ||
-                ty::type_is_floating_point(lhs) && ty::type_is_floating_point(rhs) ||
-                ty::type_is_simd(cx, lhs) && ty::type_is_simd(cx, rhs)
+            lhs.references_error() || rhs.references_error() ||
+                lhs.is_integral() && rhs.is_integral() ||
+                lhs.is_floating_point() && rhs.is_floating_point() ||
+                lhs.is_simd(cx) && rhs.is_simd(cx)
         }
 
         BinOpCategory::Bitwise => {
-            ty::type_is_error(lhs) || ty::type_is_error(rhs) ||
-                ty::type_is_integral(lhs) && ty::type_is_integral(rhs) ||
-                ty::type_is_floating_point(lhs) && ty::type_is_floating_point(rhs) ||
-                ty::type_is_simd(cx, lhs) && ty::type_is_simd(cx, rhs) ||
-                ty::type_is_bool(lhs) && ty::type_is_bool(rhs)
+            lhs.references_error() || rhs.references_error() ||
+                lhs.is_integral() && rhs.is_integral() ||
+                lhs.is_floating_point() && rhs.is_floating_point() ||
+                lhs.is_simd(cx) && rhs.is_simd(cx) ||
+                lhs.is_bool() && rhs.is_bool()
         }
 
         BinOpCategory::Comparison => {
-            ty::type_is_error(lhs) || ty::type_is_error(rhs) ||
-                ty::type_is_scalar(lhs) && ty::type_is_scalar(rhs) ||
-                ty::type_is_simd(cx, lhs) && ty::type_is_simd(cx, rhs)
+            lhs.references_error() || rhs.references_error() ||
+                lhs.is_scalar() && rhs.is_scalar() ||
+                lhs.is_simd(cx) && rhs.is_simd(cx)
         }
     }
 }
diff --git a/src/librustc_typeck/check/regionck.rs b/src/librustc_typeck/check/regionck.rs
index a96e7864fe6..13961834aeb 100644
--- a/src/librustc_typeck/check/regionck.rs
+++ b/src/librustc_typeck/check/regionck.rs
@@ -91,7 +91,7 @@ use middle::mem_categorization as mc;
 use middle::region::CodeExtent;
 use middle::subst::Substs;
 use middle::traits;
-use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall};
+use middle::ty::{self, ClosureTyper, ReScope, Ty, MethodCall, HasTypeFlags};
 use middle::infer::{self, GenericKind};
 use middle::pat_util;
 
@@ -262,13 +262,13 @@ impl<'a, 'tcx> Rcx<'a, 'tcx> {
     /// Try to resolve the type for the given node.
     pub fn resolve_expr_type_adjusted(&mut self, expr: &ast::Expr) -> Ty<'tcx> {
         let ty_unadjusted = self.resolve_node_type(expr.id);
-        if ty::type_is_error(ty_unadjusted) {
+        if ty_unadjusted.references_error() {
             ty_unadjusted
         } else {
-            let tcx = self.fcx.tcx();
-            ty::adjust_ty(tcx, expr.span, expr.id, ty_unadjusted,
-                          self.fcx.inh.adjustments.borrow().get(&expr.id),
-                          |method_call| self.resolve_method_type(method_call))
+            ty_unadjusted.adjust(
+                self.fcx.tcx(), expr.span, expr.id,
+                self.fcx.inh.adjustments.borrow().get(&expr.id),
+                |method_call| self.resolve_method_type(method_call))
         }
     }
 
@@ -662,7 +662,7 @@ fn visit_expr(rcx: &mut Rcx, expr: &ast::Expr) {
                     constrain_call(rcx, expr, Some(&**base),
                                    None::<ast::Expr>.iter(), true);
                     let fn_ret = // late-bound regions in overloaded method calls are instantiated
-                        ty::no_late_bound_regions(rcx.tcx(), &ty::ty_fn_ret(method.ty)).unwrap();
+                        rcx.tcx().no_late_bound_regions(&method.ty.fn_ret()).unwrap();
                     fn_ret.unwrap()
                 }
                 None => rcx.resolve_node_type(base.id)
@@ -891,9 +891,9 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
 
                 // Treat overloaded autoderefs as if an AutoRef adjustment
                 // was applied on the base type, as that is always the case.
-                let fn_sig = ty::ty_fn_sig(method.ty);
+                let fn_sig = method.ty.fn_sig();
                 let fn_sig = // late-bound regions should have been instantiated
-                    ty::no_late_bound_regions(rcx.tcx(), fn_sig).unwrap();
+                    rcx.tcx().no_late_bound_regions(fn_sig).unwrap();
                 let self_ty = fn_sig.inputs[0];
                 let (m, r) = match self_ty.sty {
                     ty::TyRef(r, ref m) => (m.mutbl, r),
@@ -937,7 +937,7 @@ fn constrain_autoderefs<'a, 'tcx>(rcx: &mut Rcx<'a, 'tcx>,
                                             r_deref_expr, *r_ptr);
         }
 
-        match ty::deref(derefd_ty, true) {
+        match derefd_ty.builtin_deref(true) {
             Some(mt) => derefd_ty = mt.ty,
             /* if this type can't be dereferenced, then there's already an error
                in the session saying so. Just bail out for now */
@@ -1017,9 +1017,9 @@ fn type_of_node_must_outlive<'a, 'tcx>(
     // is going to fail anyway, so just stop here and let typeck
     // report errors later on in the writeback phase.
     let ty0 = rcx.resolve_node_type(id);
-    let ty = ty::adjust_ty(tcx, origin.span(), id, ty0,
-                           rcx.fcx.inh.adjustments.borrow().get(&id),
-                           |method_call| rcx.resolve_method_type(method_call));
+    let ty = ty0.adjust(tcx, origin.span(), id,
+                        rcx.fcx.inh.adjustments.borrow().get(&id),
+                        |method_call| rcx.resolve_method_type(method_call));
     debug!("constrain_regions_in_type_of_node(\
             ty={}, ty0={}, id={}, minimum_lifetime={:?})",
             ty,  ty0,
@@ -1172,10 +1172,8 @@ fn link_region_from_node_type<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
            id, mutbl, cmt_borrowed);
 
     let rptr_ty = rcx.resolve_node_type(id);
-    if !ty::type_is_error(rptr_ty) {
-        let tcx = rcx.fcx.ccx.tcx;
+    if let ty::TyRef(&r, _) = rptr_ty.sty {
         debug!("rptr_ty={}",  rptr_ty);
-        let r = ty::ty_region(tcx, span, rptr_ty);
         link_region(rcx, span, &r, ty::BorrowKind::from_mutbl(mutbl),
                     cmt_borrowed);
     }
@@ -1462,10 +1460,8 @@ fn generic_must_outlive<'a, 'tcx>(rcx: &Rcx<'a, 'tcx>,
            generic);
 
     // To start, collect bounds from user:
-    let mut param_bounds =
-        ty::required_region_bounds(rcx.tcx(),
-                                   generic.to_ty(rcx.tcx()),
-                                   param_env.caller_bounds.clone());
+    let mut param_bounds = rcx.tcx().required_region_bounds(generic.to_ty(rcx.tcx()),
+                                                            param_env.caller_bounds.clone());
 
     // In the case of a projection T::Foo, we may be able to extract bounds from the trait def:
     match *generic {
@@ -1520,7 +1516,7 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
     debug!("projection_bounds(projection_ty={:?})",
            projection_ty);
 
-    let ty = ty::mk_projection(tcx, projection_ty.trait_ref.clone(), projection_ty.item_name);
+    let ty = tcx.mk_projection(projection_ty.trait_ref.clone(), projection_ty.item_name);
 
     // Say we have a projection `<T as SomeTrait<'a>>::SomeType`. We are interested
     // in looking for a trait definition like:
@@ -1532,7 +1528,7 @@ fn projection_bounds<'a,'tcx>(rcx: &Rcx<'a, 'tcx>,
     // ```
     //
     // we can thus deduce that `<T as SomeTrait<'a>>::SomeType : 'a`.
-    let trait_predicates = ty::lookup_predicates(tcx, projection_ty.trait_ref.def_id);
+    let trait_predicates = tcx.lookup_predicates(projection_ty.trait_ref.def_id);
     let predicates = trait_predicates.predicates.as_slice().to_vec();
     traits::elaborate_predicates(tcx, predicates)
         .filter_map(|predicate| {
diff --git a/src/librustc_typeck/check/upvar.rs b/src/librustc_typeck/check/upvar.rs
index 99e6309918c..1345f322476 100644
--- a/src/librustc_typeck/check/upvar.rs
+++ b/src/librustc_typeck/check/upvar.rs
@@ -136,7 +136,7 @@ impl<'a,'tcx> SeedBorrowKind<'a,'tcx> {
                    closure_def_id);
         }
 
-        ty::with_freevars(self.tcx(), expr.id, |freevars| {
+        self.tcx().with_freevars(expr.id, |freevars| {
             for freevar in freevars {
                 let var_node_id = freevar.def.local_node_id();
                 let upvar_id = ty::UpvarId { var_id: var_node_id,
diff --git a/src/librustc_typeck/check/wf.rs b/src/librustc_typeck/check/wf.rs
index c048845892c..00bbbafd5cd 100644
--- a/src/librustc_typeck/check/wf.rs
+++ b/src/librustc_typeck/check/wf.rs
@@ -16,7 +16,6 @@ use middle::region;
 use middle::subst::{self, TypeSpace, FnSpace, ParamSpace, SelfSpace};
 use middle::traits;
 use middle::ty::{self, Ty};
-use middle::ty::liberate_late_bound_regions;
 use middle::ty_fold::{TypeFolder, TypeFoldable, super_fold_ty};
 
 use std::collections::HashSet;
@@ -56,7 +55,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         let ccx = self.ccx;
         debug!("check_item_well_formed(it.id={}, it.ident={})",
                item.id,
-               ty::item_path_str(ccx.tcx, local_def(item.id)));
+               ccx.tcx.item_path_str(local_def(item.id)));
 
         match item.node {
             /// Right now we check that every default trait implementation
@@ -80,13 +79,12 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                 self.check_impl(item);
             }
             ast::ItemImpl(_, ast::ImplPolarity::Negative, _, Some(_), _, _) => {
-                let trait_ref = ty::impl_trait_ref(ccx.tcx,
-                                                   local_def(item.id)).unwrap();
-                ty::populate_implementations_for_trait_if_necessary(ccx.tcx, trait_ref.def_id);
+                let trait_ref = ccx.tcx.impl_trait_ref(local_def(item.id)).unwrap();
+                ccx.tcx.populate_implementations_for_trait_if_necessary(trait_ref.def_id);
                 match ccx.tcx.lang_items.to_builtin_kind(trait_ref.def_id) {
                     Some(ty::BoundSend) | Some(ty::BoundSync) => {}
                     Some(_) | None => {
-                        if !ty::trait_has_default_impl(ccx.tcx, trait_ref.def_id) {
+                        if !ccx.tcx.trait_has_default_impl(trait_ref.def_id) {
                             span_err!(ccx.tcx.sess, item.span, E0192,
                                       "negative impls are only allowed for traits with \
                                        default impls (e.g., `Send` and `Sync`)")
@@ -119,9 +117,9 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             }
             ast::ItemTrait(_, _, _, ref items) => {
                 let trait_predicates =
-                    ty::lookup_predicates(ccx.tcx, local_def(item.id));
+                    ccx.tcx.lookup_predicates(local_def(item.id));
                 reject_non_type_param_bounds(ccx.tcx, item.span, &trait_predicates);
-                if ty::trait_has_default_impl(ccx.tcx, local_def(item.id)) {
+                if ccx.tcx.trait_has_default_impl(local_def(item.id)) {
                     if !items.is_empty() {
                         span_err!(ccx.tcx.sess, item.span, E0380,
                                   "traits with default impls (`e.g. unsafe impl \
@@ -138,15 +136,13 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
     {
         let ccx = self.ccx;
         let item_def_id = local_def(item.id);
-        let type_scheme = ty::lookup_item_type(ccx.tcx, item_def_id);
-        let type_predicates = ty::lookup_predicates(ccx.tcx, item_def_id);
+        let type_scheme = ccx.tcx.lookup_item_type(item_def_id);
+        let type_predicates = ccx.tcx.lookup_predicates(item_def_id);
         reject_non_type_param_bounds(ccx.tcx, item.span, &type_predicates);
-        let param_env =
-            ty::construct_parameter_environment(ccx.tcx,
-                                                item.span,
-                                                &type_scheme.generics,
-                                                &type_predicates,
-                                                item.id);
+        let param_env = ccx.tcx.construct_parameter_environment(item.span,
+                                                                &type_scheme.generics,
+                                                                &type_predicates,
+                                                                item.id);
         let inh = Inherited::new(ccx.tcx, param_env);
         let fcx = blank_fn_ctxt(ccx, &inh, ty::FnConverging(type_scheme.ty), item.id);
         f(self, &fcx);
@@ -201,7 +197,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                                                         Some(&mut this.cache));
             debug!("check_item_type at bounds_checker.scope: {:?}", bounds_checker.scope);
 
-            let type_scheme = ty::lookup_item_type(fcx.tcx(), local_def(item.id));
+            let type_scheme = fcx.tcx().lookup_item_type(local_def(item.id));
             let item_ty = fcx.instantiate_type_scheme(item.span,
                                                       &fcx.inh.param_env.free_substs,
                                                       &type_scheme.ty);
@@ -222,7 +218,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
             // Find the impl self type as seen from the "inside" --
             // that is, with all type parameters converted from bound
             // to free.
-            let self_ty = ty::node_id_to_type(fcx.tcx(), item.id);
+            let self_ty = fcx.tcx().node_id_to_type(item.id);
             let self_ty = fcx.instantiate_type_scheme(item.span,
                                                       &fcx.inh.param_env.free_substs,
                                                       &self_ty);
@@ -231,7 +227,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 
             // Similarly, obtain an "inside" reference to the trait
             // that the impl implements.
-            let trait_ref = match ty::impl_trait_ref(fcx.tcx(), local_def(item.id)) {
+            let trait_ref = match fcx.tcx().impl_trait_ref(local_def(item.id)) {
                 None => { return; }
                 Some(t) => { t }
             };
@@ -258,7 +254,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 
             // Find the supertrait bounds. This will add `int:Bar`.
             let poly_trait_ref = ty::Binder(trait_ref);
-            let predicates = ty::lookup_super_predicates(fcx.tcx(), poly_trait_ref.def_id());
+            let predicates = fcx.tcx().lookup_super_predicates(poly_trait_ref.def_id());
             let predicates = predicates.instantiate_supertrait(fcx.tcx(), &poly_trait_ref);
             let predicates = {
                 let selcx = &mut traits::SelectionContext::new(fcx.infcx(), fcx);
@@ -278,8 +274,8 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                                      ast_generics: &ast::Generics)
     {
         let item_def_id = local_def(item.id);
-        let ty_predicates = ty::lookup_predicates(self.tcx(), item_def_id);
-        let variances = ty::item_variances(self.tcx(), item_def_id);
+        let ty_predicates = self.tcx().lookup_predicates(item_def_id);
+        let variances = self.tcx().item_variances(item_def_id);
 
         let mut constrained_parameters: HashSet<_> =
             variances.types
@@ -358,7 +354,7 @@ impl<'ccx, 'tcx> CheckTypeWellFormedVisitor<'ccx, 'tcx> {
                     span,
                     &format!("consider removing `{}` or using a marker such as `{}`",
                              param_name,
-                             ty::item_path_str(self.tcx(), def_id)));
+                             self.tcx().item_path_str(def_id)));
             }
             None => {
                 // no lang items, no help!
@@ -432,7 +428,7 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
         match fk {
             visit::FkFnBlock | visit::FkItemFn(..) => {}
             visit::FkMethod(..) => {
-                match ty::impl_or_trait_item(self.tcx(), local_def(id)) {
+                match self.tcx().impl_or_trait_item(local_def(id)) {
                     ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
                         reject_shadowing_type_parameters(self.tcx(), span, &ty_method.generics)
                     }
@@ -445,7 +441,7 @@ impl<'ccx, 'tcx, 'v> Visitor<'v> for CheckTypeWellFormedVisitor<'ccx, 'tcx> {
 
     fn visit_trait_item(&mut self, trait_item: &'v ast::TraitItem) {
         if let ast::MethodTraitItem(_, None) = trait_item.node {
-            match ty::impl_or_trait_item(self.tcx(), local_def(trait_item.id)) {
+            match self.tcx().impl_or_trait_item(local_def(trait_item.id)) {
                 ty::ImplOrTraitItem::MethodTraitItem(ty_method) => {
                     reject_non_type_param_bounds(
                         self.tcx(),
@@ -496,7 +492,7 @@ impl<'cx,'tcx> BoundsChecker<'cx,'tcx> {
     /// Note that it does not (currently, at least) check that `A : Copy` (that check is delegated
     /// to the point where impl `A : Trait<B>` is implemented).
     pub fn check_trait_ref(&mut self, trait_ref: &ty::TraitRef<'tcx>, span: Span) {
-        let trait_predicates = ty::lookup_predicates(self.fcx.tcx(), trait_ref.def_id);
+        let trait_predicates = self.fcx.tcx().lookup_predicates(trait_ref.def_id);
 
         let bounds = self.fcx.instantiate_bounds(span,
                                                  trait_ref.substs,
@@ -538,8 +534,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
         where T : TypeFoldable<'tcx>
     {
         self.binding_count += 1;
-        let value = liberate_late_bound_regions(
-            self.fcx.tcx(),
+        let value = self.fcx.tcx().liberate_late_bound_regions(
             region::DestructionScopeData::new(self.scope),
             binder);
         debug!("BoundsChecker::fold_binder: late-bound regions replaced: {:?} at scope: {:?}",
@@ -567,7 +562,7 @@ impl<'cx,'tcx> TypeFolder<'tcx> for BoundsChecker<'cx,'tcx> {
         match t.sty{
             ty::TyStruct(type_id, substs) |
             ty::TyEnum(type_id, substs) => {
-                let type_predicates = ty::lookup_predicates(self.fcx.tcx(), type_id);
+                let type_predicates = self.fcx.tcx().lookup_predicates(type_id);
                 let bounds = self.fcx.instantiate_bounds(self.span, substs,
                                                          &type_predicates);
 
@@ -638,7 +633,7 @@ fn struct_variant<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         struct_def.fields
         .iter()
         .map(|field| {
-            let field_ty = ty::node_id_to_type(fcx.tcx(), field.node.id);
+            let field_ty = fcx.tcx().node_id_to_type(field.node.id);
             let field_ty = fcx.instantiate_type_scheme(field.span,
                                                        &fcx.inh.param_env.free_substs,
                                                        &field_ty);
@@ -655,13 +650,11 @@ fn enum_variants<'a, 'tcx>(fcx: &FnCtxt<'a, 'tcx>,
         .map(|variant| {
             match variant.node.kind {
                 ast::TupleVariantKind(ref args) if !args.is_empty() => {
-                    let ctor_ty = ty::node_id_to_type(fcx.tcx(), variant.node.id);
+                    let ctor_ty = fcx.tcx().node_id_to_type(variant.node.id);
 
                     // the regions in the argument types come from the
                     // enum def'n, and hence will all be early bound
-                    let arg_tys =
-                        ty::no_late_bound_regions(
-                            fcx.tcx(), &ty::ty_fn_args(ctor_ty)).unwrap();
+                    let arg_tys = fcx.tcx().no_late_bound_regions(&ctor_ty.fn_args()).unwrap();
                     AdtVariant {
                         fields: args.iter().enumerate().map(|(index, arg)| {
                             let arg_ty = arg_tys[index];
diff --git a/src/librustc_typeck/check/writeback.rs b/src/librustc_typeck/check/writeback.rs
index 05cc3077fc9..29119f3b594 100644
--- a/src/librustc_typeck/check/writeback.rs
+++ b/src/librustc_typeck/check/writeback.rs
@@ -95,7 +95,7 @@ impl<'cx, 'tcx> WritebackCx<'cx, 'tcx> {
             let rhs_ty = self.fcx.node_ty(rhs.id);
             let rhs_ty = self.fcx.infcx().resolve_type_vars_if_possible(&rhs_ty);
 
-            if ty::type_is_scalar(lhs_ty) && ty::type_is_scalar(rhs_ty) {
+            if lhs_ty.is_scalar() && rhs_ty.is_scalar() {
                 self.fcx.inh.method_map.borrow_mut().remove(&MethodCall::expr(e.id));
 
                 // weird but true: the by-ref binops put an
@@ -128,7 +128,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
             return;
         }
 
-        self.visit_node_id(ResolvingExpr(s.span), ty::stmt_node_id(s));
+        self.visit_node_id(ResolvingExpr(s.span), ast_util::stmt_id(s));
         visit::walk_stmt(self, s);
     }
 
@@ -171,7 +171,7 @@ impl<'cx, 'tcx, 'v> Visitor<'v> for WritebackCx<'cx, 'tcx> {
         debug!("Type for pattern binding {} (id {}) resolved to {:?}",
                pat_to_string(p),
                p.id,
-               ty::node_id_to_type(self.tcx(), p.id));
+               self.tcx().node_id_to_type(p.id));
 
         visit::walk_pat(self, p);
     }
@@ -334,11 +334,11 @@ impl ResolveReason {
             ResolvingLocal(s) => s,
             ResolvingPattern(s) => s,
             ResolvingUpvar(upvar_id) => {
-                ty::expr_span(tcx, upvar_id.closure_expr_id)
+                tcx.expr_span(upvar_id.closure_expr_id)
             }
             ResolvingClosure(did) => {
                 if did.krate == ast::LOCAL_CRATE {
-                    ty::expr_span(tcx, did.node)
+                    tcx.expr_span(did.node)
                 } else {
                     DUMMY_SP
                 }
@@ -403,7 +403,7 @@ impl<'cx, 'tcx> Resolver<'cx, 'tcx> {
                     let span = self.reason.span(self.tcx);
                     span_err!(self.tcx.sess, span, E0104,
                         "cannot resolve lifetime for captured variable `{}`: {}",
-                        ty::local_var_name_str(self.tcx, upvar_id.var_id).to_string(),
+                        self.tcx.local_var_name_str(upvar_id.var_id).to_string(),
                         infer::fixup_err_to_string(e));
                 }
 
diff --git a/src/librustc_typeck/coherence/mod.rs b/src/librustc_typeck/coherence/mod.rs
index b66c76048c6..06bd572ac12 100644
--- a/src/librustc_typeck/coherence/mod.rs
+++ b/src/librustc_typeck/coherence/mod.rs
@@ -139,15 +139,14 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
     fn check_implementation(&self, item: &Item) {
         let tcx = self.crate_context.tcx;
         let impl_did = local_def(item.id);
-        let self_type = ty::lookup_item_type(tcx, impl_did);
+        let self_type = tcx.lookup_item_type(impl_did);
 
         // If there are no traits, then this implementation must have a
         // base type.
 
         let impl_items = self.create_impl_from_item(item);
 
-        if let Some(trait_ref) = ty::impl_trait_ref(self.crate_context.tcx,
-                                                    impl_did) {
+        if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(impl_did) {
             debug!("(checking implementation) adding impl for trait '{:?}', item '{}'",
                    trait_ref,
                    item.ident);
@@ -181,9 +180,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         debug!("instantiate_default_methods(impl_id={:?}, trait_ref={:?})",
                impl_id, trait_ref);
 
-        let impl_type_scheme = ty::lookup_item_type(tcx, impl_id);
+        let impl_type_scheme = tcx.lookup_item_type(impl_id);
 
-        let prov = ty::provided_trait_methods(tcx, trait_ref.def_id);
+        let prov = tcx.provided_trait_methods(trait_ref.def_id);
         for trait_method in &prov {
             // Synthesize an ID.
             let new_id = tcx.sess.next_node_id();
@@ -210,8 +209,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             // impl, plus its own.
             let new_polytype = ty::TypeScheme {
                 generics: new_method_ty.generics.clone(),
-                ty: ty::mk_bare_fn(tcx, Some(new_did),
-                                   tcx.mk_bare_fn(new_method_ty.fty.clone()))
+                ty: tcx.mk_fn(Some(new_did),
+                              tcx.mk_bare_fn(new_method_ty.fty.clone()))
             };
             debug!("new_polytype={:?}", new_polytype);
 
@@ -245,8 +244,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
     fn add_trait_impl(&self, impl_trait_ref: ty::TraitRef<'tcx>, impl_def_id: DefId) {
         debug!("add_trait_impl: impl_trait_ref={:?} impl_def_id={:?}",
                impl_trait_ref, impl_def_id);
-        let trait_def = ty::lookup_trait_def(self.crate_context.tcx,
-                                             impl_trait_ref.def_id);
+        let trait_def = self.crate_context.tcx.lookup_trait_def(impl_trait_ref.def_id);
         trait_def.record_impl(self.crate_context.tcx, impl_def_id, impl_trait_ref);
     }
 
@@ -273,11 +271,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     }
                 }).collect();
 
-                if let Some(trait_ref) = ty::impl_trait_ref(self.crate_context.tcx,
-                                                            local_def(item.id)) {
-                    self.instantiate_default_methods(local_def(item.id),
-                                                     &trait_ref,
-                                                     &mut items);
+                let def_id = local_def(item.id);
+                if let Some(trait_ref) = self.crate_context.tcx.impl_trait_ref(def_id) {
+                    self.instantiate_default_methods(def_id, &trait_ref, &mut items);
                 }
 
                 items
@@ -299,8 +295,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
         let drop_trait = match tcx.lang_items.drop_trait() {
             Some(id) => id, None => { return }
         };
-        ty::populate_implementations_for_trait_if_necessary(tcx, drop_trait);
-        let drop_trait = ty::lookup_trait_def(tcx, drop_trait);
+        tcx.populate_implementations_for_trait_if_necessary(drop_trait);
+        let drop_trait = tcx.lookup_trait_def(drop_trait);
 
         let impl_items = tcx.impl_items.borrow();
 
@@ -312,7 +308,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             }
             let method_def_id = items[0];
 
-            let self_type = ty::lookup_item_type(tcx, impl_did);
+            let self_type = tcx.lookup_item_type(impl_did);
             match self_type.ty.sty {
                 ty::TyEnum(type_def_id, _) |
                 ty::TyStruct(type_def_id, _) |
@@ -355,8 +351,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             Some(id) => id,
             None => return,
         };
-        ty::populate_implementations_for_trait_if_necessary(tcx, copy_trait);
-        let copy_trait = ty::lookup_trait_def(tcx, copy_trait);
+        tcx.populate_implementations_for_trait_if_necessary(copy_trait);
+        let copy_trait = tcx.lookup_trait_def(copy_trait);
 
         copy_trait.for_each_impl(tcx, |impl_did| {
             debug!("check_implementations_of_copy: impl_did={:?}",
@@ -368,7 +364,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 return
             }
 
-            let self_type = ty::lookup_item_type(tcx, impl_did);
+            let self_type = tcx.lookup_item_type(impl_did);
             debug!("check_implementations_of_copy: self_type={:?} (bound)",
                    self_type);
 
@@ -380,7 +376,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             debug!("check_implementations_of_copy: self_type={:?} (free)",
                    self_type);
 
-            match ty::can_type_implement_copy(&param_env, span, self_type) {
+            match param_env.can_type_implement_copy(self_type, span) {
                 Ok(()) => {}
                 Err(ty::FieldDoesNotImplementCopy(name)) => {
                        span_err!(tcx.sess, span, E0204,
@@ -425,7 +421,7 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
             }
         };
 
-        let trait_def = ty::lookup_trait_def(tcx, coerce_unsized_trait);
+        let trait_def = tcx.lookup_trait_def(coerce_unsized_trait);
 
         trait_def.for_each_impl(tcx, |impl_did| {
             debug!("check_implementations_of_coerce_unsized: impl_did={:?}",
@@ -437,9 +433,8 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                 return;
             }
 
-            let source = ty::lookup_item_type(tcx, impl_did).ty;
-            let trait_ref = ty::impl_trait_ref(self.crate_context.tcx,
-                                               impl_did).unwrap();
+            let source = tcx.lookup_item_type(impl_did).ty;
+            let trait_ref = self.crate_context.tcx.impl_trait_ref(impl_did).unwrap();
             let target = *trait_ref.substs.types.get(subst::TypeSpace, 0);
             debug!("check_implementations_of_coerce_unsized: {:?} -> {:?} (bound)",
                    source, target);
@@ -468,18 +463,18 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
 
                 (&ty::TyRef(r_a, mt_a), &ty::TyRef(r_b, mt_b)) => {
                     infer::mk_subr(&infcx, infer::RelateObjectBound(span), *r_b, *r_a);
-                    check_mutbl(mt_a, mt_b, &|ty| ty::mk_imm_rptr(tcx, r_b, ty))
+                    check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ref(r_b, ty))
                 }
 
                 (&ty::TyRef(_, mt_a), &ty::TyRawPtr(mt_b)) |
                 (&ty::TyRawPtr(mt_a), &ty::TyRawPtr(mt_b)) => {
-                    check_mutbl(mt_a, mt_b, &|ty| ty::mk_imm_ptr(tcx, ty))
+                    check_mutbl(mt_a, mt_b, &|ty| tcx.mk_imm_ptr(ty))
                 }
 
                 (&ty::TyStruct(def_id_a, substs_a), &ty::TyStruct(def_id_b, substs_b)) => {
                     if def_id_a != def_id_b {
-                        let source_path = ty::item_path_str(tcx, def_id_a);
-                        let target_path = ty::item_path_str(tcx, def_id_b);
+                        let source_path = tcx.item_path_str(def_id_a);
+                        let target_path = tcx.item_path_str(def_id_b);
                         span_err!(tcx.sess, span, E0377,
                                   "the trait `CoerceUnsized` may only be implemented \
                                    for a coercion between structures with the same \
@@ -489,9 +484,9 @@ impl<'a, 'tcx> CoherenceChecker<'a, 'tcx> {
                     }
 
                     let origin = infer::Misc(span);
-                    let fields = ty::lookup_struct_fields(tcx, def_id_a);
+                    let fields = tcx.lookup_struct_fields(def_id_a);
                     let diff_fields = fields.iter().enumerate().filter_map(|(i, f)| {
-                        let ty = ty::lookup_field_type_unsubstituted(tcx, def_id_a, f.id);
+                        let ty = tcx.lookup_field_type_unsubstituted(def_id_a, f.id);
                         let (a, b) = (ty.subst(tcx, substs_a), ty.subst(tcx, substs_b));
                         if infcx.sub_types(false, origin, b, a).is_ok() {
                             None
@@ -592,7 +587,7 @@ fn subst_receiver_types_in_method_ty<'tcx>(tcx: &ty::ctxt<'tcx>,
                                            provided_source: Option<ast::DefId>)
                                            -> ty::Method<'tcx>
 {
-    let combined_substs = ty::make_substs_for_receiver_types(tcx, trait_ref, method);
+    let combined_substs = tcx.make_substs_for_receiver_types(trait_ref, method);
 
     debug!("subst_receiver_types_in_method_ty: combined_substs={:?}",
            combined_substs);
diff --git a/src/librustc_typeck/coherence/orphan.rs b/src/librustc_typeck/coherence/orphan.rs
index 8376b92da3d..e585b8cd2bd 100644
--- a/src/librustc_typeck/coherence/orphan.rs
+++ b/src/librustc_typeck/coherence/orphan.rs
@@ -67,7 +67,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                 // defined in this crate.
                 debug!("coherence2::orphan check: inherent impl {}",
                        self.tcx.map.node_to_string(item.id));
-                let self_ty = ty::lookup_item_type(self.tcx, def_id).ty;
+                let self_ty = self.tcx.lookup_item_type(def_id).ty;
                 match self_ty.sty {
                     ty::TyEnum(def_id, _) |
                     ty::TyStruct(def_id, _) => {
@@ -210,7 +210,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                 // "Trait" impl
                 debug!("coherence2::orphan check: trait impl {}",
                        self.tcx.map.node_to_string(item.id));
-                let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
+                let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
                 let trait_def_id = trait_ref.def_id;
                 match traits::orphan_check(self.tcx, def_id) {
                     Ok(()) => { }
@@ -269,9 +269,9 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                 debug!("trait_ref={:?} trait_def_id={:?} trait_has_default_impl={}",
                        trait_ref,
                        trait_def_id,
-                       ty::trait_has_default_impl(self.tcx, trait_def_id));
+                       self.tcx.trait_has_default_impl(trait_def_id));
                 if
-                    ty::trait_has_default_impl(self.tcx, trait_def_id) &&
+                    self.tcx.trait_has_default_impl(trait_def_id) &&
                     trait_def_id.krate != ast::LOCAL_CRATE
                 {
                     let self_ty = trait_ref.self_ty();
@@ -297,7 +297,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                                     "cross-crate traits with a default impl, like `{}`, \
                                      can only be implemented for a struct/enum type \
                                      defined in the current crate",
-                                    ty::item_path_str(self.tcx, trait_def_id)))
+                                    self.tcx.item_path_str(trait_def_id)))
                             }
                         }
                         _ => {
@@ -305,7 +305,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                                 "cross-crate traits with a default impl, like `{}`, \
                                  can only be implemented for a struct/enum type, \
                                  not `{}`",
-                                ty::item_path_str(self.tcx, trait_def_id),
+                                self.tcx.item_path_str(trait_def_id),
                                 self_ty))
                         }
                     };
@@ -332,7 +332,7 @@ impl<'cx, 'tcx> OrphanChecker<'cx, 'tcx> {
                 // "Trait" impl
                 debug!("coherence2::orphan check: default trait impl {}",
                        self.tcx.map.node_to_string(item.id));
-                let trait_ref = ty::impl_trait_ref(self.tcx, def_id).unwrap();
+                let trait_ref = self.tcx.impl_trait_ref(def_id).unwrap();
                 if trait_ref.def_id.krate != ast::LOCAL_CRATE {
                     span_err!(self.tcx.sess, item.span, E0318,
                               "cannot create default implementations for traits outside the \
diff --git a/src/librustc_typeck/coherence/overlap.rs b/src/librustc_typeck/coherence/overlap.rs
index 0e8067e7181..b4ad55ef2e4 100644
--- a/src/librustc_typeck/coherence/overlap.rs
+++ b/src/librustc_typeck/coherence/overlap.rs
@@ -50,9 +50,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
         let trait_defs: Vec<_> = self.tcx.trait_defs.borrow().values().cloned().collect();
 
         for trait_def in trait_defs {
-            ty::populate_implementations_for_trait_if_necessary(
-                self.tcx,
-                trait_def.trait_ref.def_id);
+            self.tcx.populate_implementations_for_trait_if_necessary(trait_def.trait_ref.def_id);
             self.check_for_overlapping_impls_of_trait(trait_def);
         }
     }
@@ -147,7 +145,7 @@ impl<'cx, 'tcx> OverlapChecker<'cx, 'tcx> {
 
         span_err!(self.tcx.sess, self.span_of_impl(impl1), E0119,
                   "conflicting implementations for trait `{}`",
-                  ty::item_path_str(self.tcx, trait_def_id));
+                  self.tcx.item_path_str(trait_def_id));
 
         self.report_overlap_note(impl1, impl2);
     }
@@ -181,7 +179,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
                 // general orphan/coherence rules, it must always be
                 // in this crate.
                 let impl_def_id = ast_util::local_def(item.id);
-                let trait_ref = ty::impl_trait_ref(self.tcx, impl_def_id).unwrap();
+                let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
                 let prev_default_impl = self.default_impls.insert(trait_ref.def_id, item.id);
                 match prev_default_impl {
                     Some(prev_id) => {
@@ -194,7 +192,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
             }
             ast::ItemImpl(_, _, _, Some(_), ref self_ty, _) => {
                 let impl_def_id = ast_util::local_def(item.id);
-                let trait_ref = ty::impl_trait_ref(self.tcx, impl_def_id).unwrap();
+                let trait_ref = self.tcx.impl_trait_ref(impl_def_id).unwrap();
                 let trait_def_id = trait_ref.def_id;
                 match trait_ref.self_ty().sty {
                     ty::TyTrait(ref data) => {
@@ -208,7 +206,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
                             // giving a misleading message below.
                             span_err!(self.tcx.sess, self_ty.span, E0372,
                                       "the trait `{}` cannot be made into an object",
-                                      ty::item_path_str(self.tcx, data.principal_def_id()));
+                                      self.tcx.item_path_str(data.principal_def_id()));
                         } else {
                             let mut supertrait_def_ids =
                                 traits::supertrait_def_ids(self.tcx, data.principal_def_id());
@@ -217,7 +215,7 @@ impl<'cx, 'tcx,'v> visit::Visitor<'v> for OverlapChecker<'cx, 'tcx> {
                                           "the object type `{}` automatically \
                                            implements the trait `{}`",
                                           trait_ref.self_ty(),
-                                          ty::item_path_str(self.tcx, trait_def_id));
+                                          self.tcx.item_path_str(trait_def_id));
                             }
                         }
                     }
diff --git a/src/librustc_typeck/coherence/unsafety.rs b/src/librustc_typeck/coherence/unsafety.rs
index fa39e9d0491..c0323ba60fc 100644
--- a/src/librustc_typeck/coherence/unsafety.rs
+++ b/src/librustc_typeck/coherence/unsafety.rs
@@ -30,7 +30,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
     fn check_unsafety_coherence(&mut self, item: &'v ast::Item,
                                 unsafety: ast::Unsafety,
                                 polarity: ast::ImplPolarity) {
-        match ty::impl_trait_ref(self.tcx, ast_util::local_def(item.id)) {
+        match self.tcx.impl_trait_ref(ast_util::local_def(item.id)) {
             None => {
                 // Inherent impl.
                 match unsafety {
@@ -43,7 +43,7 @@ impl<'cx, 'tcx, 'v> UnsafetyChecker<'cx, 'tcx> {
             }
 
             Some(trait_ref) => {
-                let trait_def = ty::lookup_trait_def(self.tcx, trait_ref.def_id);
+                let trait_def = self.tcx.lookup_trait_def(trait_ref.def_id);
                 match (trait_def.unsafety, unsafety, polarity) {
                     (ast::Unsafety::Unsafe,
                      ast::Unsafety::Unsafe, ast::ImplPolarity::Negative) => {
diff --git a/src/librustc_typeck/collect.rs b/src/librustc_typeck/collect.rs
index a873900b5fc..e43a3542b6e 100644
--- a/src/librustc_typeck/collect.rs
+++ b/src/librustc_typeck/collect.rs
@@ -242,12 +242,12 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
             AstConvRequest::GetTraitDef(def_id) => {
                 tcx.sess.note(
                     &format!("the cycle begins when processing `{}`...",
-                             ty::item_path_str(tcx, def_id)));
+                             tcx.item_path_str(def_id)));
             }
             AstConvRequest::EnsureSuperPredicates(def_id) => {
                 tcx.sess.note(
                     &format!("the cycle begins when computing the supertraits of `{}`...",
-                             ty::item_path_str(tcx, def_id)));
+                             tcx.item_path_str(def_id)));
             }
             AstConvRequest::GetTypeParameterBounds(id) => {
                 let def = tcx.type_parameter_def(id);
@@ -264,12 +264,12 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
                 AstConvRequest::GetTraitDef(def_id) => {
                     tcx.sess.note(
                         &format!("...which then requires processing `{}`...",
-                                 ty::item_path_str(tcx, def_id)));
+                                 tcx.item_path_str(def_id)));
                 }
                 AstConvRequest::EnsureSuperPredicates(def_id) => {
                     tcx.sess.note(
                         &format!("...which then requires computing the supertraits of `{}`...",
-                                 ty::item_path_str(tcx, def_id)));
+                                 tcx.item_path_str(def_id)));
                 }
                 AstConvRequest::GetTypeParameterBounds(id) => {
                     let def = tcx.type_parameter_def(id);
@@ -286,13 +286,13 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
             AstConvRequest::GetTraitDef(def_id) => {
                 tcx.sess.note(
                     &format!("...which then again requires processing `{}`, completing the cycle.",
-                             ty::item_path_str(tcx, def_id)));
+                             tcx.item_path_str(def_id)));
             }
             AstConvRequest::EnsureSuperPredicates(def_id) => {
                 tcx.sess.note(
                     &format!("...which then again requires computing the supertraits of `{}`, \
                               completing the cycle.",
-                             ty::item_path_str(tcx, def_id)));
+                             tcx.item_path_str(def_id)));
             }
             AstConvRequest::GetTypeParameterBounds(id) => {
                 let def = tcx.type_parameter_def(id);
@@ -311,7 +311,7 @@ impl<'a,'tcx> CrateCtxt<'a,'tcx> {
         let tcx = self.tcx;
 
         if trait_id.krate != ast::LOCAL_CRATE {
-            return ty::lookup_trait_def(tcx, trait_id)
+            return tcx.lookup_trait_def(trait_id)
         }
 
         let item = match tcx.map.get(trait_id.node) {
@@ -399,7 +399,7 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
         if trait_def_id.krate == ast::LOCAL_CRATE {
             trait_defines_associated_type_named(self.ccx, trait_def_id.node, assoc_name)
         } else {
-            let trait_def = ty::lookup_trait_def(self.tcx(), trait_def_id);
+            let trait_def = self.tcx().lookup_trait_def(trait_def_id);
             trait_def.associated_type_names.contains(&assoc_name)
         }
     }
@@ -416,7 +416,7 @@ impl<'a, 'tcx> AstConv<'tcx> for ItemCtxt<'a, 'tcx> {
                     item_name: ast::Name)
                     -> Ty<'tcx>
     {
-        ty::mk_projection(self.tcx(), trait_ref, item_name)
+        self.tcx().mk_projection(trait_ref, item_name)
     }
 }
 
@@ -508,7 +508,7 @@ impl<'tcx> GetTypeParameterBounds<'tcx> for ast::Generics {
         // `where T:Foo`.
 
         let def = astconv.tcx().type_parameter_def(node_id);
-        let ty = ty::mk_param_from_def(astconv.tcx(), &def);
+        let ty = astconv.tcx().mk_param_from_def(&def);
 
         let from_ty_params =
             self.ty_params
@@ -577,7 +577,7 @@ fn get_enum_variant_types<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             ast::TupleVariantKind(ref args) if !args.is_empty() => {
                 let rs = ExplicitRscope;
                 let input_tys: Vec<_> = args.iter().map(|va| icx.to_ty(&rs, &*va.ty)).collect();
-                ty::mk_ctor_fn(tcx, variant_def_id, &input_tys, enum_scheme.ty)
+                tcx.mk_ctor_fn(variant_def_id, &input_tys, enum_scheme.ty)
             }
 
             ast::TupleVariantKind(_) => {
@@ -631,8 +631,8 @@ fn convert_method<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                     container,
                                     None);
 
-    let fty = ty::mk_bare_fn(ccx.tcx, Some(def_id),
-                             ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
+    let fty = ccx.tcx.mk_fn(Some(def_id),
+                            ccx.tcx.mk_bare_fn(ty_method.fty.clone()));
     debug!("method {} (id {}) has type {:?}",
             ident, id, fty);
     ccx.tcx.tcache.borrow_mut().insert(def_id,TypeScheme {
@@ -822,7 +822,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                                                     ast_trait_ref,
                                                     None);
 
-            ty::record_trait_has_default_impl(tcx, trait_ref.def_id);
+            tcx.record_trait_has_default_impl(trait_ref.def_id);
 
             tcx.impl_trait_refs.borrow_mut().insert(local_def(it.id), Some(trait_ref));
         }
@@ -944,7 +944,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             let _: Result<(), ErrorReported> = // any error is already reported, can ignore
                 ccx.ensure_super_predicates(it.span, local_def(it.id));
             convert_trait_predicates(ccx, it);
-            let trait_predicates = ty::lookup_predicates(tcx, local_def(it.id));
+            let trait_predicates = tcx.lookup_predicates(local_def(it.id));
 
             debug!("convert: trait_bounds={:?}", trait_predicates);
 
@@ -995,7 +995,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
             convert_methods(ccx,
                             TraitContainer(local_def(it.id)),
                             methods,
-                            ty::mk_self_type(tcx),
+                            tcx.mk_self_type(),
                             &trait_def.generics,
                             &trait_predicates);
 
@@ -1026,7 +1026,7 @@ fn convert_item(ccx: &CrateCtxt, it: &ast::Item) {
                 check_method_self_type(ccx,
                                        &BindingRscope::new(),
                                        ccx.method_ty(trait_item.id),
-                                       ty::mk_self_type(tcx),
+                                       tcx.mk_self_type(),
                                        &sig.explicit_self,
                                        it.id)
             }
@@ -1088,7 +1088,7 @@ fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     tcx.struct_fields.borrow_mut().insert(local_def(id), Rc::new(field_tys));
 
     let substs = mk_item_substs(ccx, &scheme.generics);
-    let selfty = ty::mk_struct(tcx, local_def(id), tcx.mk_substs(substs));
+    let selfty = tcx.mk_struct(local_def(id), tcx.mk_substs(substs));
 
     // If this struct is enum-like or tuple-like, create the type of its
     // constructor.
@@ -1110,8 +1110,7 @@ fn convert_struct<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
                                                               .unwrap()
                                                               .ty)
                               .collect();
-                let ctor_fn_ty = ty::mk_ctor_fn(tcx,
-                                                local_def(ctor_id),
+                let ctor_fn_ty = tcx.mk_ctor_fn(local_def(ctor_id),
                                                 &inputs[..],
                                                 selfty);
                 write_ty_to_tcx(tcx, ctor_id, ctor_fn_ty);
@@ -1177,7 +1176,7 @@ fn ensure_super_predicates_step(ccx: &CrateCtxt,
         let scope = &(generics, &self_predicate);
 
         // Convert the bounds that follow the colon, e.g. `Bar+Zed` in `trait Foo : Bar+Zed`.
-        let self_param_ty = ty::mk_self_type(tcx);
+        let self_param_ty = tcx.mk_self_type();
         let superbounds1 = compute_bounds(&ccx.icx(scope),
                                     self_param_ty,
                                     bounds,
@@ -1231,7 +1230,7 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
         _ => tcx.sess.span_bug(it.span, "trait_def_of_item invoked on non-trait"),
     };
 
-    let paren_sugar = ty::has_attr(tcx, def_id, "rustc_paren_sugar");
+    let paren_sugar = tcx.has_attr(def_id, "rustc_paren_sugar");
     if paren_sugar && !ccx.tcx.sess.features.borrow().unboxed_closures {
         ccx.tcx.sess.span_err(
             it.span,
@@ -1295,12 +1294,12 @@ fn trait_def_of_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
             generics.ty_params
                     .iter()
                     .enumerate()
-                    .map(|(i, def)| ty::mk_param(tcx, TypeSpace,
+                    .map(|(i, def)| tcx.mk_param(TypeSpace,
                                                  i as u32, def.ident.name))
                     .collect();
 
         // ...and also create the `Self` parameter.
-        let self_ty = ty::mk_self_type(tcx);
+        let self_ty = tcx.mk_self_type();
 
         Substs::new_trait(types, regions, self_ty)
     }
@@ -1344,7 +1343,7 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
         }
     };
 
-    let super_predicates = ty::lookup_super_predicates(ccx.tcx, def_id);
+    let super_predicates = ccx.tcx.lookup_super_predicates(def_id);
 
     // `ty_generic_predicates` below will consider the bounds on the type
     // parameters (including `Self`) and the explicit where-clauses,
@@ -1389,9 +1388,8 @@ fn convert_trait_predicates<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>, it: &ast::Item)
                 }
             };
 
-            let assoc_ty = ty::mk_projection(ccx.tcx,
-                                             self_trait_ref,
-                                             trait_item.ident.name);
+            let assoc_ty = ccx.tcx.mk_projection(self_trait_ref,
+                                                 trait_item.ident.name);
 
             let bounds = compute_bounds(&ccx.icx(&(ast_generics, trait_predicates)),
                                         assoc_ty,
@@ -1409,7 +1407,7 @@ fn type_scheme_of_def_id<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
                                   -> ty::TypeScheme<'tcx>
 {
     if def_id.krate != ast::LOCAL_CRATE {
-        return ty::lookup_item_type(ccx.tcx, def_id);
+        return ccx.tcx.lookup_item_type(def_id);
     }
 
     match ccx.tcx.map.find(def_id.node) {
@@ -1450,7 +1448,7 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
         ast::ItemFn(ref decl, unsafety, _, abi, ref generics, _) => {
             let ty_generics = ty_generics_for_fn(ccx, generics, &ty::Generics::empty());
             let tofd = astconv::ty_of_bare_fn(&ccx.icx(generics), unsafety, abi, &**decl);
-            let ty = ty::mk_bare_fn(tcx, Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
+            let ty = tcx.mk_fn(Some(local_def(it.id)), tcx.mk_bare_fn(tofd));
             ty::TypeScheme { ty: ty, generics: ty_generics }
         }
         ast::ItemTy(ref t, ref generics) => {
@@ -1462,13 +1460,13 @@ fn compute_type_scheme_of_item<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             // Create a new generic polytype.
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
-            let t = ty::mk_enum(tcx, local_def(it.id), tcx.mk_substs(substs));
+            let t = tcx.mk_enum(local_def(it.id), tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
         ast::ItemStruct(_, ref generics) => {
             let ty_generics = ty_generics_for_type_or_impl(ccx, generics);
             let substs = mk_item_substs(ccx, &ty_generics);
-            let t = ty::mk_struct(tcx, local_def(it.id), tcx.mk_substs(substs));
+            let t = tcx.mk_struct(local_def(it.id), tcx.mk_substs(substs));
             ty::TypeScheme { ty: t, generics: ty_generics }
         }
         ast::ItemDefaultImpl(..) |
@@ -1531,7 +1529,7 @@ fn convert_typed_item<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
     assert!(prev_predicates.is_none());
 
     // Debugging aid.
-    if ty::has_attr(tcx, local_def(it.id), "rustc_object_lifetime_default") {
+    if tcx.has_attr(local_def(it.id), "rustc_object_lifetime_default") {
         let object_lifetime_default_reprs: String =
             scheme.generics.types.iter()
                                  .map(|t| match t.object_lifetime_default {
@@ -1693,20 +1691,20 @@ fn add_unsized_bound<'tcx>(astconv: &AstConv<'tcx>,
     match unbound {
         Some(ref tpb) => {
             // FIXME(#8559) currently requires the unbound to be built-in.
-            let trait_def_id = ty::trait_ref_to_def_id(tcx, tpb);
+            let trait_def_id = tcx.trait_ref_to_def_id(tpb);
             match kind_id {
                 Ok(kind_id) if trait_def_id != kind_id => {
                     tcx.sess.span_warn(span,
                                        "default bound relaxed for a type parameter, but \
                                        this does nothing because the given bound is not \
                                        a default. Only `?Sized` is supported");
-                    ty::try_add_builtin_trait(tcx, kind_id, bounds);
+                    tcx.try_add_builtin_trait(kind_id, bounds);
                 }
                 _ => {}
             }
         }
         _ if kind_id.is_ok() => {
-            ty::try_add_builtin_trait(tcx, kind_id.unwrap(), bounds);
+            tcx.try_add_builtin_trait(kind_id.unwrap(), bounds);
         }
         // No lang item for Sized, so we can't add it as a bound.
         None => {}
@@ -1882,16 +1880,15 @@ fn get_or_create_type_parameter_def<'a,'tcx>(ccx: &CrateCtxt<'a,'tcx>,
             let ty = ast_ty_to_ty(&ccx.icx(&()), &ExplicitRscope, &**path);
             let cur_idx = index;
 
-            ty::walk_ty(ty, |t| {
-                match t.sty {
-                    ty::TyParam(p) => if p.idx > cur_idx {
+            for leaf_ty in ty.walk() {
+                if let ty::TyParam(p) = leaf_ty.sty {
+                    if p.idx > cur_idx {
                         span_err!(tcx.sess, path.span, E0128,
                                   "type parameters with a default cannot use \
                                    forward declared identifiers");
-                        },
-                        _ => {}
                     }
-            });
+                }
+            }
 
             Some(ty)
         }
@@ -2122,14 +2119,12 @@ fn compute_type_scheme_of_foreign_fn_decl<'a, 'tcx>(
         ast::Return(ref ty) =>
             ty::FnConverging(ast_ty_to_ty(&ccx.icx(ast_generics), &rb, &**ty)),
         ast::DefaultReturn(..) =>
-            ty::FnConverging(ty::mk_nil(ccx.tcx)),
+            ty::FnConverging(ccx.tcx.mk_nil()),
         ast::NoReturn(..) =>
             ty::FnDiverging
     };
 
-    let t_fn = ty::mk_bare_fn(
-        ccx.tcx,
-        None,
+    let t_fn = ccx.tcx.mk_fn(None,
         ccx.tcx.mk_bare_fn(ty::BareFnTy {
             abi: abi,
             unsafety: ast::Unsafety::Unsafe,
@@ -2150,7 +2145,7 @@ fn mk_item_substs<'a, 'tcx>(ccx: &CrateCtxt<'a, 'tcx>,
 {
     let types =
         ty_generics.types.map(
-            |def| ty::mk_param_from_def(ccx.tcx, def));
+            |def| ccx.tcx.mk_param_from_def(def));
 
     let regions =
         ty_generics.regions.map(
@@ -2192,8 +2187,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
         let required_type_free =
             liberate_early_bound_regions(
                 tcx, body_scope,
-                &ty::liberate_late_bound_regions(
-                    tcx, body_scope, &ty::Binder(required_type)));
+                &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(required_type)));
 
         // The "base type" comes from the impl. It too may have late-bound
         // regions from the method.
@@ -2201,8 +2195,7 @@ fn check_method_self_type<'a, 'tcx, RS:RegionScope>(
         let base_type_free =
             liberate_early_bound_regions(
                 tcx, body_scope,
-                &ty::liberate_late_bound_regions(
-                    tcx, body_scope, &ty::Binder(base_type)));
+                &tcx.liberate_late_bound_regions(body_scope, &ty::Binder(base_type)));
 
         debug!("required_type={:?} required_type_free={:?} \
                 base_type={:?} base_type_free={:?}",
@@ -2267,9 +2260,9 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
                                              impl_def_id: ast::DefId,
                                              impl_items: &[P<ast::ImplItem>])
 {
-    let impl_scheme = ty::lookup_item_type(tcx, impl_def_id);
-    let impl_predicates = ty::lookup_predicates(tcx, impl_def_id);
-    let impl_trait_ref = ty::impl_trait_ref(tcx, impl_def_id);
+    let impl_scheme = tcx.lookup_item_type(impl_def_id);
+    let impl_predicates = tcx.lookup_predicates(impl_def_id);
+    let impl_trait_ref = tcx.impl_trait_ref(impl_def_id);
 
     // The trait reference is an input, so find all type parameters
     // reachable from there, to start (if this is an inherent impl,
@@ -2298,7 +2291,7 @@ fn enforce_impl_params_are_constrained<'tcx>(tcx: &ty::ctxt<'tcx>,
 
     let lifetimes_in_associated_types: HashSet<_> =
         impl_items.iter()
-                  .map(|item| ty::impl_or_trait_item(tcx, local_def(item.id)))
+                  .map(|item| tcx.impl_or_trait_item(local_def(item.id)))
                   .filter_map(|item| match item {
                       ty::TypeTraitItem(ref assoc_ty) => assoc_ty.ty,
                       ty::ConstTraitItem(..) | ty::MethodTraitItem(..) => None
diff --git a/src/librustc_typeck/constrained_type_params.rs b/src/librustc_typeck/constrained_type_params.rs
index b1580a74876..7844d71462c 100644
--- a/src/librustc_typeck/constrained_type_params.rs
+++ b/src/librustc_typeck/constrained_type_params.rs
@@ -24,7 +24,7 @@ pub enum Parameter {
 /// by `ty` (see RFC 447).
 pub fn parameters_for_type<'tcx>(ty: Ty<'tcx>) -> Vec<Parameter> {
     let mut result = vec![];
-    ty::maybe_walk_ty(ty, |t| {
+    ty.maybe_walk(|t| {
         if let ty::TyProjection(..) = t.sty {
             false // projections are not injective.
         } else {
diff --git a/src/librustc_typeck/lib.rs b/src/librustc_typeck/lib.rs
index 8feecd15613..fc825c198e7 100644
--- a/src/librustc_typeck/lib.rs
+++ b/src/librustc_typeck/lib.rs
@@ -105,7 +105,7 @@ pub use rustc::util;
 use middle::def;
 use middle::infer;
 use middle::subst;
-use middle::ty::{self, Ty};
+use middle::ty::{self, Ty, HasTypeFlags};
 use rustc::ast_map;
 use session::config;
 use util::common::time;
@@ -148,7 +148,7 @@ pub struct CrateCtxt<'a, 'tcx: 'a> {
 // Functions that write types into the node type table
 fn write_ty_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>, node_id: ast::NodeId, ty: Ty<'tcx>) {
     debug!("write_ty_to_tcx({}, {:?})", node_id,  ty);
-    assert!(!ty::type_needs_infer(ty));
+    assert!(!ty.needs_infer());
     tcx.node_type_insert(node_id, ty);
 }
 
@@ -160,7 +160,7 @@ fn write_substs_to_tcx<'tcx>(tcx: &ty::ctxt<'tcx>,
                node_id,
                item_substs);
 
-        assert!(item_substs.substs.types.all(|t| !ty::type_needs_infer(*t)));
+        assert!(!item_substs.substs.types.needs_infer());
 
         tcx.item_substs.borrow_mut().insert(node_id, item_substs);
     }
@@ -199,7 +199,7 @@ fn require_same_types<'a, 'tcx, M>(tcx: &ty::ctxt<'tcx>,
         Ok(_) => true,
         Err(ref terr) => {
             span_err!(tcx.sess, span, E0211, "{}: {}", msg(), terr);
-            ty::note_and_explain_type_err(tcx, terr, span);
+            tcx.note_and_explain_type_err(terr, span);
             false
         }
     }
@@ -209,7 +209,7 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                     main_id: ast::NodeId,
                     main_span: Span) {
     let tcx = ccx.tcx;
-    let main_t = ty::node_id_to_type(tcx, main_id);
+    let main_t = tcx.node_id_to_type(main_id);
     match main_t.sty {
         ty::TyBareFn(..) => {
             match tcx.map.find(main_id) {
@@ -226,12 +226,12 @@ fn check_main_fn_ty(ccx: &CrateCtxt,
                 }
                 _ => ()
             }
-            let se_ty = ty::mk_bare_fn(tcx, Some(local_def(main_id)), tcx.mk_bare_fn(ty::BareFnTy {
+            let se_ty = tcx.mk_fn(Some(local_def(main_id)), tcx.mk_bare_fn(ty::BareFnTy {
                 unsafety: ast::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
                     inputs: Vec::new(),
-                    output: ty::FnConverging(ty::mk_nil(tcx)),
+                    output: ty::FnConverging(tcx.mk_nil()),
                     variadic: false
                 })
             }));
@@ -254,7 +254,7 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                      start_id: ast::NodeId,
                      start_span: Span) {
     let tcx = ccx.tcx;
-    let start_t = ty::node_id_to_type(tcx, start_id);
+    let start_t = tcx.node_id_to_type(start_id);
     match start_t.sty {
         ty::TyBareFn(..) => {
             match tcx.map.find(start_id) {
@@ -272,13 +272,13 @@ fn check_start_fn_ty(ccx: &CrateCtxt,
                 _ => ()
             }
 
-            let se_ty = ty::mk_bare_fn(tcx, Some(local_def(start_id)), tcx.mk_bare_fn(ty::BareFnTy {
+            let se_ty = tcx.mk_fn(Some(local_def(start_id)), tcx.mk_bare_fn(ty::BareFnTy {
                 unsafety: ast::Unsafety::Normal,
                 abi: abi::Rust,
                 sig: ty::Binder(ty::FnSig {
                     inputs: vec!(
                         tcx.types.isize,
-                        ty::mk_imm_ptr(tcx, ty::mk_imm_ptr(tcx, tcx.types.u8))
+                        tcx.mk_imm_ptr(tcx.mk_imm_ptr(tcx.types.u8))
                     ),
                     output: ty::FnConverging(tcx.types.isize),
                     variadic: false,
diff --git a/src/librustc_typeck/variance.rs b/src/librustc_typeck/variance.rs
index 1f4e1343651..c1f9725fc81 100644
--- a/src/librustc_typeck/variance.rs
+++ b/src/librustc_typeck/variance.rs
@@ -485,7 +485,7 @@ impl<'a, 'tcx> TermsContext<'a, 'tcx> {
                 param_id={}, \
                 inf_index={:?}, \
                 initial_variance={:?})",
-               ty::item_path_str(self.tcx, ast_util::local_def(item_id)),
+               self.tcx.item_path_str(ast_util::local_def(item_id)),
                item_id, kind, space, index, param_id, inf_index,
                initial_variance);
     }
@@ -603,7 +603,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
 
         match item.node {
             ast::ItemEnum(ref enum_definition, _) => {
-                let scheme = ty::lookup_item_type(tcx, did);
+                let scheme = tcx.lookup_item_type(did);
 
                 // Not entirely obvious: constraints on structs/enums do not
                 // affect the variance of their type parameters. See discussion
@@ -633,7 +633,7 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
             }
 
             ast::ItemStruct(..) => {
-                let scheme = ty::lookup_item_type(tcx, did);
+                let scheme = tcx.lookup_item_type(did);
 
                 // Not entirely obvious: constraints on structs/enums do not
                 // affect the variance of their type parameters. See discussion
@@ -641,16 +641,16 @@ impl<'a, 'tcx, 'v> Visitor<'v> for ConstraintContext<'a, 'tcx> {
                 //
                 // self.add_constraints_from_generics(&scheme.generics);
 
-                let struct_fields = ty::lookup_struct_fields(tcx, did);
+                let struct_fields = tcx.lookup_struct_fields(did);
                 for field_info in &struct_fields {
                     assert_eq!(field_info.id.krate, ast::LOCAL_CRATE);
-                    let field_ty = ty::node_id_to_type(tcx, field_info.id.node);
+                    let field_ty = tcx.node_id_to_type(field_info.id.node);
                     self.add_constraints_from_ty(&scheme.generics, field_ty, self.covariant);
                 }
             }
 
             ast::ItemTrait(..) => {
-                let trait_def = ty::lookup_trait_def(tcx, did);
+                let trait_def = tcx.lookup_trait_def(did);
                 self.add_constraints_from_trait_ref(&trait_def.generics,
                                                     trait_def.trait_ref,
                                                     self.invariant);
@@ -781,7 +781,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
         } else {
             // Parameter on an item defined within another crate:
             // variance already inferred, just look it up.
-            let variances = ty::item_variances(self.tcx(), item_def_id);
+            let variances = self.tcx().item_variances(item_def_id);
             let variance = match kind {
                 TypeParam => *variances.types.get(space, index),
                 RegionParam => *variances.regions.get(space, index),
@@ -848,7 +848,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
                trait_ref,
                variance);
 
-        let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id);
+        let trait_def = self.tcx().lookup_trait_def(trait_ref.def_id);
 
         self.add_constraints_from_substs(
             generics,
@@ -904,7 +904,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
             ty::TyEnum(def_id, substs) |
             ty::TyStruct(def_id, substs) => {
-                let item_type = ty::lookup_item_type(self.tcx(), def_id);
+                let item_type = self.tcx().lookup_item_type(def_id);
 
                 // All type parameters on enums and structs should be
                 // in the TypeSpace.
@@ -924,7 +924,7 @@ impl<'a, 'tcx> ConstraintContext<'a, 'tcx> {
 
             ty::TyProjection(ref data) => {
                 let trait_ref = &data.trait_ref;
-                let trait_def = ty::lookup_trait_def(self.tcx(), trait_ref.def_id);
+                let trait_def = self.tcx().lookup_trait_def(trait_ref.def_id);
                 self.add_constraints_from_substs(
                     generics,
                     trait_ref.def_id,
@@ -1200,7 +1200,7 @@ impl<'a, 'tcx> SolveContext<'a, 'tcx> {
 
             // For unit testing: check for a special "rustc_variance"
             // attribute and report an error with various results if found.
-            if ty::has_attr(tcx, item_def_id, "rustc_variance") {
+            if tcx.has_attr(item_def_id, "rustc_variance") {
                 span_err!(tcx.sess, tcx.map.span(item_id), E0208, "{:?}", item_variances);
             }
 
diff --git a/src/librustdoc/clean/inline.rs b/src/librustdoc/clean/inline.rs
index 53063c6247e..e80fd360e04 100644
--- a/src/librustdoc/clean/inline.rs
+++ b/src/librustdoc/clean/inline.rs
@@ -150,9 +150,9 @@ pub fn record_extern_fqn(cx: &DocContext, did: ast::DefId, kind: clean::TypeKind
 
 pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt,
                             did: ast::DefId) -> clean::Trait {
-    let def = ty::lookup_trait_def(tcx, did);
-    let trait_items = ty::trait_items(tcx, did).clean(cx);
-    let predicates = ty::lookup_predicates(tcx, did);
+    let def = tcx.lookup_trait_def(did);
+    let trait_items = tcx.trait_items(did).clean(cx);
+    let predicates = tcx.lookup_predicates(did);
     let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
     let generics = filter_non_trait_generics(did, generics);
     let (generics, supertrait_bounds) = separate_supertrait_bounds(generics);
@@ -165,12 +165,12 @@ pub fn build_external_trait(cx: &DocContext, tcx: &ty::ctxt,
 }
 
 fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Function {
-    let t = ty::lookup_item_type(tcx, did);
+    let t = tcx.lookup_item_type(did);
     let (decl, style, abi) = match t.ty.sty {
         ty::TyBareFn(_, ref f) => ((did, &f.sig).clean(cx), f.unsafety, f.abi),
         _ => panic!("bad function"),
     };
-    let predicates = ty::lookup_predicates(tcx, did);
+    let predicates = tcx.lookup_predicates(did);
     clean::Function {
         decl: decl,
         generics: (&t.generics, &predicates, subst::FnSpace).clean(cx),
@@ -183,9 +183,9 @@ fn build_external_function(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) ->
 fn build_struct(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Struct {
     use syntax::parse::token::special_idents::unnamed_field;
 
-    let t = ty::lookup_item_type(tcx, did);
-    let predicates = ty::lookup_predicates(tcx, did);
-    let fields = ty::lookup_struct_fields(tcx, did);
+    let t = tcx.lookup_item_type(did);
+    let predicates = tcx.lookup_predicates(did);
+    let fields = tcx.lookup_struct_fields(did);
 
     clean::Struct {
         struct_type: match &*fields {
@@ -201,14 +201,14 @@ fn build_struct(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::Stru
 }
 
 fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEnum {
-    let t = ty::lookup_item_type(tcx, did);
-    let predicates = ty::lookup_predicates(tcx, did);
+    let t = tcx.lookup_item_type(did);
+    let predicates = tcx.lookup_predicates(did);
     match t.ty.sty {
         ty::TyEnum(edid, _) if !csearch::is_typedef(&tcx.sess.cstore, did) => {
             return clean::EnumItem(clean::Enum {
                 generics: (&t.generics, &predicates, subst::TypeSpace).clean(cx),
                 variants_stripped: false,
-                variants: ty::enum_variants(tcx, edid).clean(cx),
+                variants: tcx.enum_variants(edid).clean(cx),
             })
         }
         _ => {}
@@ -222,7 +222,7 @@ fn build_type(cx: &DocContext, tcx: &ty::ctxt, did: ast::DefId) -> clean::ItemEn
 
 pub fn build_impls(cx: &DocContext, tcx: &ty::ctxt,
                    did: ast::DefId) -> Vec<clean::Item> {
-    ty::populate_inherent_implementations_for_type_if_necessary(tcx, did);
+    tcx.populate_inherent_implementations_for_type_if_necessary(did);
     let mut impls = Vec::new();
 
     match tcx.inherent_impls.borrow().get(&did) {
@@ -307,16 +307,16 @@ pub fn build_impl(cx: &DocContext,
         });
     }
 
-    let predicates = ty::lookup_predicates(tcx, did);
+    let predicates = tcx.lookup_predicates(did);
     let trait_items = csearch::get_impl_items(&tcx.sess.cstore, did)
             .iter()
             .filter_map(|did| {
         let did = did.def_id();
-        let impl_item = ty::impl_or_trait_item(tcx, did);
+        let impl_item = tcx.impl_or_trait_item(did);
         match impl_item {
             ty::ConstTraitItem(ref assoc_const) => {
                 let did = assoc_const.def_id;
-                let type_scheme = ty::lookup_item_type(tcx, did);
+                let type_scheme = tcx.lookup_item_type(did);
                 let default = match assoc_const.default {
                     Some(_) => Some(const_eval::lookup_const_by_id(tcx, did, None)
                                                .unwrap().span.to_src(cx)),
@@ -383,7 +383,7 @@ pub fn build_impl(cx: &DocContext,
         }
     }).collect::<Vec<_>>();
     let polarity = csearch::get_impl_polarity(tcx, did);
-    let ty = ty::lookup_item_type(tcx, did);
+    let ty = tcx.lookup_item_type(did);
     let trait_ = associated_trait.clean(cx).map(|bound| {
         match bound {
             clean::TraitBound(polyt, _) => polyt.trait_,
@@ -477,7 +477,7 @@ fn build_const(cx: &DocContext, tcx: &ty::ctxt,
     debug!("got snippet {}", sn);
 
     clean::Constant {
-        type_: ty::lookup_item_type(tcx, did).ty.clean(cx),
+        type_: tcx.lookup_item_type(did).ty.clean(cx),
         expr: sn
     }
 }
@@ -486,7 +486,7 @@ fn build_static(cx: &DocContext, tcx: &ty::ctxt,
                 did: ast::DefId,
                 mutable: bool) -> clean::Static {
     clean::Static {
-        type_: ty::lookup_item_type(tcx, did).ty.clean(cx),
+        type_: tcx.lookup_item_type(did).ty.clean(cx),
         mutability: if mutable {clean::Mutable} else {clean::Immutable},
         expr: "\n\n\n".to_string(), // trigger the "[definition]" links
     }
diff --git a/src/librustdoc/clean/mod.rs b/src/librustdoc/clean/mod.rs
index 8ba4470c3ef..c25267520cc 100644
--- a/src/librustdoc/clean/mod.rs
+++ b/src/librustdoc/clean/mod.rs
@@ -1332,7 +1332,7 @@ impl<'tcx> Clean<Item> for ty::Method<'tcx> {
         let provided = match self.container {
             ty::ImplContainer(..) => false,
             ty::TraitContainer(did) => {
-                ty::provided_trait_methods(cx.tcx(), did).iter().any(|m| {
+                cx.tcx().provided_trait_methods(did).iter().any(|m| {
                     m.def_id == self.def_id
                 })
             }
@@ -1742,7 +1742,7 @@ impl Clean<Item> for ty::field_ty {
             (Some(self.name), Some(attr_map.get(&self.id.node).unwrap()))
         };
 
-        let ty = ty::lookup_item_type(cx.tcx(), self.id);
+        let ty = cx.tcx().lookup_item_type(self.id);
 
         Item {
             name: name.clean(cx),
@@ -2731,8 +2731,8 @@ impl<'tcx> Clean<Item> for ty::AssociatedType<'tcx> {
             // are actually located on the trait/impl itself, so we need to load
             // all of the generics from there and then look for bounds that are
             // applied to this associated type in question.
-            let def = ty::lookup_trait_def(cx.tcx(), did);
-            let predicates = ty::lookup_predicates(cx.tcx(), did);
+            let def = cx.tcx().lookup_trait_def(did);
+            let predicates = cx.tcx().lookup_predicates(did);
             let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
             generics.where_predicates.iter().filter_map(|pred| {
                 let (name, self_type, trait_, bounds) = match *pred {
diff --git a/src/librustdoc/clean/simplify.rs b/src/librustdoc/clean/simplify.rs
index 2bde8d5bfb5..e65cdd8ff5d 100644
--- a/src/librustdoc/clean/simplify.rs
+++ b/src/librustdoc/clean/simplify.rs
@@ -30,7 +30,6 @@ use std::mem;
 use std::collections::HashMap;
 
 use rustc::middle::subst;
-use rustc::middle::ty;
 use syntax::ast;
 
 use clean::PathParameters as PP;
@@ -154,8 +153,8 @@ fn trait_is_same_or_supertrait(cx: &DocContext, child: ast::DefId,
     if child == trait_ {
         return true
     }
-    let def = ty::lookup_trait_def(cx.tcx(), child);
-    let predicates = ty::lookup_predicates(cx.tcx(), child);
+    let def = cx.tcx().lookup_trait_def(child);
+    let predicates = cx.tcx().lookup_predicates(child);
     let generics = (&def.generics, &predicates, subst::TypeSpace).clean(cx);
     generics.where_predicates.iter().filter_map(|pred| {
         match *pred {